在日常运维 Elasticsearch (ES) 集群时,难免会遇到节点脱离、分片未分配、集群状态发黄发红等各种各样的异常情况。掌握一套常用且高效的排障命令,可以快速定位和解决大部分问题。
这里总结了一些我们在实战中最常敲的 ES 排障 API,习惯上我们都是通过 curl 配合 jq 工具在 Linux 终端下直接执行。
假设 ES 的 API 地址为
127.0.0.1:9200,如开启了认证请在 curl 中加入-u user:pass。
1. 查核心:集群当前状态
排障第一步永远是看集群健康度。
# 查看集群健康状态 (green / yellow / red)
curl -s -X GET "127.0.0.1:9200/_cluster/health?pretty"
# 极简模式看状态
curl -s -X GET "127.0.0.1:9200/_cat/health?v"
说明:
- green:所有主分片和副本分片都正常。
- yellow:主分片正常,但有副本分片未分配(通常是单节点测试,或者节点数不满足副本数)。
- red:存在主分片未分配,有数据不可用,此时必须马上介入。
2. 查节点:谁拖了后腿
# 查看所有节点的概况(包含堆内存使用率、CPU、负载等)
curl -s -X GET "127.0.0.1:9200/_cat/nodes?v&h=ip,name,heap.percent,ram.percent,cpu,load_1m,node.role"
# 查看节点积压的任务(Pending Tasks,通常在 Master 节点负载高时出现)
curl -s -X GET "127.0.0.1:9200/_cluster/pending_tasks?pretty"
3. 查分片:Unassigned 原因定位
如果集群发红或发黄,一定是分片出了问题。找到未分配的分片并询问 ES 为什么不分配它。
# 列出所有状态异常的分片 (UNASSIGNED)
curl -s -X GET "127.0.0.1:9200/_cat/shards?v" | grep UNASSIGNED
# 询问 ES 为什么这个分片没有被分配 (重点命令)
# 替换里面的 <index_name> 和 <shard_id>
curl -s -X GET "127.0.0.1:9200/_cluster/allocation/explain?pretty" -H 'Content-Type: application/json' -d'{
"index": "<index_name>",
"shard": <shard_id>,
"primary": true
}'
执行解释 API 后,仔细看 deciders 里的 explanation 字段,ES 会用大白话告诉你为什么不能分配(比如磁盘满了、节点离开了、超过最大重试次数等)。
如果是因为超过了最大重试次数(allocate_stale_primary 等),可以通过下面命令手动重试:
# 强制集群重新尝试分配所有 unassigned 的分片
curl -s -X POST "127.0.0.1:9200/_cluster/reroute?retry_failed=true"
4. 查资源:磁盘与索引占用
很多时候集群红了是因为某个节点的磁盘使用率超过了水位线(默认 85% / 90% / 95%)。
# 查看各个节点的磁盘剩余容量和分片数
curl -s -X GET "127.0.0.1:9200/_cat/allocation?v"
# 查看哪些索引占用的空间最大,按大小排序
curl -s -X GET "127.0.0.1:9200/_cat/indices?v&s=store.size:desc"
5. 查性能:热点线程和任务队列
如果发现节点 CPU 狂飙,或者请求一直超时,我们需要揪出是哪个线程或者查询在捣鬼。
# 抓取当前集群中最耗费 CPU 的热点线程 (类似 top -H)
curl -s -X GET "127.0.0.1:9200/_nodes/hot_threads"
# 查看 ES 内部各个线程池的运行情况,重点看 active 和 rejected
# 如果 rejected 大于 0 且持续增加,说明并发请求超过了 ES 的处理能力
curl -s -X GET "127.0.0.1:9200/_cat/thread_pool?v&h=id,name,active,queue,rejected,completed"
6. 紧急救火:干掉吃内存的查询
如果你定位到了某个查询导致集群濒临 OOM,可以查看当前正在运行的 Task 并取消它。
# 列出运行时间最长的 Task
curl -s -X GET "127.0.0.1:9200/_tasks?detailed=true&pretty"
# 取消指定 Task (记录上一步拿到 node_id:task_id)
curl -s -X POST "127.0.0.1:9200/_tasks/<task_id>/_cancel"
总结
ES 的排障本质上就是顺藤摸瓜:看集群状态 -> 找异常节点 -> 查异常分片/看资源瓶颈 -> 具体原因分析。建议把常用的排障别名写进 .bashrc,关键时刻能省下不少手敲长串命令的时间。