4、集群健康诊断:掌握Elasticsearch集群健康状态(绿/黄/红)的含义,学习分片分配、节点故障的诊断方法。
说实话,我见过太多团队,ES集群一报警就慌。看到状态变黄就重启,看到变红就重建索引。其实没必要。你只要搞懂那三种颜色到底在说什么,大部分问题都能自己搞定。
今天我们就聊聊集群健康诊断。我会把绿、黄、红的含义讲透,再分享一些我实战中总结的分片分配和节点故障排查方法。
4.1 集群健康状态:绿、黄、红到底代表什么?
ES集群的健康状态,说白了就是看所有主分片和副本分片是否都到位了。它只有三种颜色:绿、黄、红。
| 状态 | 含义 | 是否可用 | 常见原因 |
|---|---|---|---|
| 绿色 | 所有主分片和副本分片都已分配 | 完全可用 | 正常状态 |
| 黄色 | 所有主分片已分配,但部分副本未分配 | 可用,但有风险 | 节点数不足、磁盘空间不足、副本配置问题 |
| 红色 | 至少一个主分片未分配 | 部分数据不可用 | 节点宕机、磁盘故障、分片损坏 |
你可能会问:黄色状态到底要不要管?我个人习惯是,如果只是短暂出现,比如集群在滚动重启,那可以等。但如果持续超过几分钟,就得查了。我曾经遇到过一个案例,黄色状态持续了一周,结果一个节点挂了,数据直接丢了——因为副本根本没到位。
4.2 如何查看集群健康状态?
最直接的方式就是调用API:
GET _cluster/health
返回结果长这样:
{
"cluster_name" : "my_cluster",
"status" : "yellow",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 120,
"active_shards" : 180,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 60,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 75.0
}
这里有个关键字段:unassigned_shards。如果这个值大于0,说明有分片没分配。黄色状态下,没分配的都是副本;红色状态下,没分配的有主分片。
unassigned_shards 和 active_shards_percent_as_number。一旦发现未分配分片数超过阈值,或者活跃分片占比低于99%,就自动告警。这比等用户报错要快得多。
4.3 分片分配问题诊断
分片分配问题,是集群健康问题的核心。说白了,就是ES不知道该把分片放哪,或者放不上去。
4.3.1 查看未分配分片的原因
先找到哪些分片没分配:
GET _cat/shards?v&h=index,shard,prirep,state,node,unassigned.reason
返回结果中,unassigned.reason 字段会告诉你原因。常见的有:
- INDEX_CREATED:索引刚创建,分片正在分配中
- CLUSTER_RECOVERED:集群恢复中
- NODE_LEFT:节点离开集群,分片需要重新分配
- REPLICA_ADDED:新增副本,正在分配
- ALLOCATION_FAILED:分配失败,需要进一步排查
- REROUTE_CANCELLED:重新路由被取消
嗯,这里要注意:ALLOCATION_FAILED 是最棘手的。我曾经遇到过,原因是磁盘空间不足,但ES的分配器没正确识别。最后手动清理了磁盘才解决。
4.3.2 深入排查分配失败
如果看到 ALLOCATION_FAILED,可以用这个API看详细错误:
GET _cluster/allocation/explain?pretty
返回结果会告诉你为什么分配失败,比如:
{
"index" : "my_index",
"shard" : 0,
"primary" : true,
"current_state" : "unassigned",
"unassigned_info" : {
"reason" : "ALLOCATION_FAILED",
"details" : "failed to allocate, failure message: [shard] creation of shard [my_index][0] failed on node [node-1]"
},
"can_allocate" : "no",
"allocate_explanation" : "cannot allocate because allocation is not permitted to any of the nodes",
"node_allocation_decisions" : [
{
"node_id" : "node-1",
"node_name" : "node-1",
"deciders" : [
{
"decider" : "disk_threshold",
"decision" : "NO",
"explanation" : "the node has insufficient disk space"
}
]
}
]
}
你看,这里明确说了是磁盘空间不足。所以排查时,先看这个API,能省很多时间。
_cluster/allocation/explain 返回的是 "no allocations",但磁盘明明还有空间。后来发现是ES的磁盘水位线配置有问题。检查一下 cluster.routing.allocation.disk.watermark.low 和 high 这两个参数,默认是85%和90%。如果你的磁盘使用率刚好卡在阈值附近,就会出现这种诡异情况。
4.4 节点故障诊断
节点故障,是导致集群变红的最常见原因。一个节点挂了,它上面的主分片就会变成未分配状态。
4.4.1 检查节点状态
先看看集群里还有哪些节点活着:
GET _cat/nodes?v
重点关注 node.role 和 master 字段。如果某个数据节点消失了,那它上面的分片就需要重新分配。
我习惯用这个命令快速定位问题节点:
GET _cat/nodes?v&h=name,node.role,master,heap.percent,ram.percent,cpu,load_1m,disk.used_percent
这样能一眼看出哪个节点的资源使用率异常。比如CPU飙到100%,或者磁盘快满了,那这个节点很可能就是罪魁祸首。
4.4.2 节点宕机后的恢复流程
当一个节点宕机,ES会做这几件事:
- 检测到节点离开集群(默认30秒超时)
- 将该节点上的主分片标记为未分配
- 集群状态变为红色(如果有主分片丢失)
- 开始在其他节点上分配这些主分片
- 主分片分配完成后,再分配对应的副本
- 集群状态恢复为绿色(如果所有分片都分配成功)
你想想看,这个过程需要时间。如果节点只是短暂重启,ES可能会等一段时间再重新分配。这个等待时间由 index.unassigned.node_left.delayed_timeout 控制,默认是5分钟。
PUT _all/_settings {"settings": {"index.unassigned.node_left.delayed_timeout": "30m"}}
4.4.3 手动重新分配分片
有时候ES的自动分配不够智能,或者你想手动干预。可以用 _cluster/reroute API:
POST _cluster/reroute
{
"commands": [
{
"allocate_stale_primary": {
"index": "my_index",
"shard": 0,
"node": "node-2",
"accept_data_loss": true
}
}
]
}
这个命令会把一个未分配的主分片分配到指定节点。注意 accept_data_loss 参数,它表示你接受可能的数据丢失。因为那个分片可能已经损坏了。
4.5 实战:一个典型的红色集群恢复过程
我记得有一次,凌晨三点被报警吵醒。集群状态变红了。我按这个步骤排查:
- 先看健康状态:
GET _cluster/health,确认是红色,unassigned_shards是12 - 找未分配分片:
GET _cat/shards?v&h=index,shard,prirep,state,node,unassigned.reason,发现有两个主分片未分配,原因是NODE_LEFT - 查节点状态:
GET _cat/nodes?v,发现少了一个数据节点 - 看分配解释:
GET _cluster/allocation/explain,发现是因为剩余节点磁盘空间不足,无法分配 - 临时解决:清理了一个节点的磁盘,然后手动触发重新分配:
POST _cluster/reroute?retry_failed=true - 恢复:几分钟后,集群变回绿色
整个过程大概15分钟。如果当时慌了,直接重启集群,可能反而会出更多问题。
4.6 总结
集群健康诊断,说白了就是三件事:看颜色、找原因、动手修。绿色不用管,黄色查副本,红色查主分片。记住这几个API,大部分问题都能搞定:
_cluster/health:看整体状态_cat/shards:看分片分布_cluster/allocation/explain:看分配失败原因_cat/nodes:看节点状态_cluster/reroute:手动干预
嗯,今天就聊到这。下一章我们会讲如何用监控工具实时跟踪这些指标,到时候再分享一些我自己的监控面板配置经验。