集群上线只是开始,长期稳定依赖持续的运维与监控。健康状态怎么读、分片怎么调配、版本怎么滚动升级、容量怎么预估、故障怎么排查,是每个 ES 运维者的日常。本文从健康诊断讲起,覆盖节点分片管理、滚动升级、容量规划、监控告警与典型故障处理。
1. 健康诊断
一句话总结: 集群健康三色表示可用性,配合分片分配与节点状态可以快速定位红黄背后的原因。
1.1 三色健康
_cluster/health 返回 green/yellow/red:green 全部主分片与副本就绪;yellow 主分片就绪但副本未分配;red 有主分片未分配,数据不可写。健康只是起点,还要看具体的未分配原因:
curl -s "localhost:9200/_cluster/health?pretty"
curl -s "localhost:9200/_cluster/allocation/explain?pretty"
1.2 allocation explain 定位未分配
_cluster/allocation/explain 对未分配分片给出原因与建议,是排查红黄的钥匙:
curl -X POST "localhost:9200/_cluster/allocation/explain?pretty" -H "Content-Type: application/json" -d'
{
"index": "orders-2026-10-01",
"shard": 0,
"primary": true
}
'
常见原因:节点磁盘水印、分片分配规则冲突、节点不足、副本数超过节点数、曾因故障触发延迟分配。逐条对照即可定位。
1.3 节点与索引状态
结合 _cat/nodes 与 _cat/indices 看资源与索引健康;_cat/shards 看分片分布是否倾斜。健康巡检应沉淀为脚本定期执行,红黄即告警:
curl -s "localhost:9200/_cat/nodes?v&h=name,node.role,heap.percent,disk.used_percent,load_1m"
curl -s "localhost:9200/_cat/indices?v&h=index,health,status,pri,rep,docs.count,store.size"
curl -s "localhost:9200/_cat/shards?v&h=index,shard,prirep,state,node,store"
1.4 延迟分配与恢复
节点宕机后,未分配分片会等待延迟分配窗口(默认 1 分钟)再开始重建,给节点一个重新加入的机会,避免频繁重平衡放大故障。紧急场景可显式调小延迟:
PUT /_cluster/settings
{
"transient": { "index.unassigned.node_left.delayed_timeout": "30s" }
}
2. 节点与分片管理
一句话总结: 节点按角色分工、分片按规则分配,调配分片与调整副本是运维的日常操作。
2.1 节点角色划分
生产集群按角色拆分:master 专司集群状态、data 专司数据、ingest 处理管道、ml 跑机器学习。职责单一化避免主节点被数据写入拖垮。小集群至少保证 3 个 master 候选节点防脑裂。
2.2 分片分配与平衡
分片分配受分配规则(attribute、filter)、平衡因子与磁盘水印共同控制。热点分片可用 _cluster/reroute 手动迁移,但仅是临时手段,根治靠调整数据分布或分片数:
curl -X POST "localhost:9200/_cluster/reroute?pretty" -H "Content-Type: application/json" -d'
{
"commands": [
{ "move": { "index": "orders-2026-10-01", "shard": 0, "from_node": "node-01", "to_node": "node-03" } }
]
}
'
2.3 副本调整与滚动重启
修改副本数走索引设置即时生效;节点重启要逐个进行(滚动),重启期间副本自动补位。调整 index.number_of_replicas 时考虑磁盘余量,副本翻倍意味着存储翻倍:
PUT /orders-2026-10-01/_settings
{
"number_of_replicas": 1
}
2.4 分片总数治理
单分片在节点间会因段大小与热点出现倾斜,数量过多则元数据与选路开销上升。合并小索引的段、限制每节点分片数(cluster.routing.allocation.total_shards_per_node)可以收敛碎片:
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.total_shards_per_node": 100
}
}
分片数在索引创建时即确定,规划失误只能 reindex 到新分片数的新索引。新建索引前用总量与单分片目标反推,是成本最低的治理。
3. 滚动升级
一句话总结: 滚动升级逐节点停、更、启,配合兼容性检查与回滚预案,把版本升级的爆炸半径降到最小。
3.1 升级前的检查
先确认目标版本与当前版本的跨版本兼容规则,关闭分片分配防止升级中数据重平衡,执行 _cluster/health 等待 green:
curl -X PUT "localhost:9200/_cluster/settings" -H "Content-Type: application/json" -d'
{
"persistent": { "cluster.routing.allocation.enable": "none" }
}
'
curl -s "localhost:9200/_cluster/health?wait_for_status=green&timeout=60s"
3.2 逐节点升级流程
对每个节点:停掉 ES、备份配置、替换安装包或镜像、启动、等待加入集群、观察健康再升级下一个。升级后先恢复分片分配并等待 rebalance 完成:
curl -X PUT "localhost:9200/_cluster/settings" -H "Content-Type: application/json" -d'
{
"persistent": { "cluster.routing.allocation.enable": "all" }
}
'
3.3 回滚预案
升级前保留上一版本二进制与配置快照。若升级后出现兼容性故障,按原路径回滚单个节点,数据层不受影响——ES 的段格式向后兼容,只要不是跨大版本数据迁移,回滚成本可控。回滚前先恢复分片分配并确保无未分配分片。
4. 容量规划
一句话总结: 容量规划按文档量、增长率与分片上限倒推节点数,同时为 CPU 与磁盘水印留出余量。
4.1 估算分片数
单分片建议控制在 20~50GB,按总量倒推分片数:总量 1TB、单分片 30GB,约需 35 个分片,再考虑副本数。分片过少无法扩展,分片过多则段与元数据开销高,规划要在两者间取平衡。
4.2 节点与内存估算
数据节点内存按「JVM heap ≤ 32GB + 页缓存尽量大」设计;单节点承载的分片数与 heap 相关,heap 32GB 时单节点几百个分片即需警惕。容量规划要乘上增长率并预留 30% 磁盘余量,防止突发写流量触达水印。
4.3 磁盘水印的三级防线
低水印 85%、高水印 90%、洪水水印 95% 是默认阈值。配置按百分比或绝对值均可,生产建议绝对值与百分比并用:
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.disk.watermark.low": "85%",
"cluster.routing.allocation.disk.watermark.high": "90%",
"cluster.routing.allocation.disk.watermark.flood_stage": "95%"
}
}
5. 监控指标与告警
一句话总结: 监控覆盖集群健康、节点资源、查询延迟与分片状态,指标接入 Prometheus/Grafana 后按阈值告警。
5.1 核心指标集
必盯指标:集群健康色、活跃分片、查询与索引延迟、拒绝线程池队列、JVM heap 占用、磁盘水位、节点 GC 次数、bulk 拒绝率。_cat/thread_pool 看 search/write 队列是否积压:
curl -s "localhost:9200/_cat/thread_pool/search,write?v"
5.2 指标采集
8.x 的指标模块以 _monitoring 内部索引暴露,可对接 Metricbeat 抓取后送 Prometheus:
# metricbeat.yml
metricbeat.modules:
- module: elasticsearch
metricsets: ["node", "shard", "cluster_stats", "index"]
period: 10s
hosts: ["localhost:9200"]
5.3 告警设计
告警分级:健康变黄警告、变红紧急;heap 超 85% 警告;磁盘高水印警告、洪水水印紧急;bulk 拒绝率持续上升即预警。告警要带自愈动作:磁盘高水印触发后可自动删除过期索引或关副本。告警阈值要结合基线设定,固定阈值在业务波动时容易误报,宜对每日曲线取 P95 做动态基线。
5.4 Grafana 面板沉淀
指标接入 Prometheus 后,把核心图表沉淀成运维大盘:总览(健康/节点数/分片数)、资源(CPU/heap/磁盘)、性能(查询延迟/bulk 吞吐/线程池队列)、GC 与慢日志统计。大盘供值班快速判断「哪里异常」,明细指标再下钻到单节点。面板按告警项反向设计,确保每个告警都有对应图表可追溯。
6. 日志与排查
一句话总结: 故障排查遵循「日志 → 慢查询 → 现场指标」的顺序,慢日志定位查询,gc 日志定位堆问题。
6.1 慢日志启用
查询与索引慢日志超过阈值即记录,是定位查询性能的第一步:
PUT /orders/_settings
{
"index.search.slowlog.threshold.query.warn": "2s",
"index.search.slowlog.threshold.fetch.warn": "1s",
"index.indexing.slowlog.threshold.index.warn": "5s"
}
6.2 常见故障模式
堆不足、磁盘水印、段合并风暴、脑裂是四大典型故障。堆不足看 gc 日志与 heap 曲线,磁盘水印查 allocation explain,段合并看 _cat/segments,脑裂查 master 选举日志并检查网络与投票配置。
6.3 现场取证
故障时保留:集群健康、thread_pool 队列、gc 日志、_nodes/stats 快照、查询日志。先恢复可用再定位根因,切勿在故障现场反复触发昂贵诊断。定位后用监控曲线复盘,形成文档沉淀进 runbook:
# 快速取证命令组
curl -s "localhost:9200/_cluster/health?pretty" > health.json
curl -s "localhost:9200/_nodes/stats?pretty" > nodes_stats.json
curl -s "localhost:9200/_cat/thread_pool?v" > thread_pool.txt
6.4 段合并风暴排查
写入高峰期容易触发段合并风暴,表现为 CPU 飙升、写入延迟增大。排查看 _cat/segments 的段数与合并队列,必要时限制合并并发或暂停自动合并,待低峰恢复:
PUT /orders-2026-10-01/_settings
{
"index.merge.scheduler.max_thread_count": 1
}
7. 最佳实践
一句话总结: 运维最佳实践把日常动作脚本化、巡检自动化、故障预案化,用制度对抗人的失误。
7.1 日常巡检清单
每日巡检:健康色、分片分配、磁盘水位、heap、线程池队列、慢日志峰值、备份执行状态。巡检脚本化后接告警,出现异常自动通知值班。
7.2 备份即保险
快照是最后防线,S3 仓库按天执行,恢复演练每季度一次。只靠副本不叫备份——误删索引、配置错误、机房故障都要靠快照兜底。
7.3 变更管理
配置、升级、reindex 都走变更单与灰度:先预发集群验证,再按节点滚动,最后观察指标回稳。任何变更都要有回滚步骤,变更窗口避开业务高峰。
| 事项 | 频率 | 触发动作 |
|---|---|---|
| 健康巡检 | 每日 | 变黄即告警 |
| 磁盘水位 | 实时 | 高水印删旧索引 |
| 快照备份 | 每日 | 失败立即补跑 |
| 恢复演练 | 季度 | 验证可恢复 |
| 慢日志复盘 | 每周 | 定位慢查询 |
8. 总结
| 环节 | 要点 |
|---|---|
| 健康诊断 | 三色健康 + allocation explain 定位 |
| 分片管理 | 角色分工、reroute 调配、副本调整 |
| 滚动升级 | 关分配 → 逐节点升 → 恢复分配 |
| 容量规划 | 单分片 20~50GB,预留 30% 磁盘 |
| 监控告警 | 指标采集 + 分级告警 + 自愈动作 |
| 日志排查 | 慢日志定位、gc 日志看堆、现场取证 |
| 最佳实践 | 巡检脚本化、备份即保险、变更受控 |
集群运维的本质是把不确定性转成制度:健康三色一眼可知,未分配分片一条命令可查,升级回滚有预案,容量预估有公式,告警分级有动作。把日常动作脚本化、故障处理 runbook 化,集群才能在业务增长中保持稳定。集群架构原理见《集群分片与高可用架构》,备份恢复看《部署运维与备份恢复》,性能治理参考《性能调优与缓存策略》。
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。