ES常用排障命令

在日常运维 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,关键时刻能省下不少手敲长串命令的时间。

评论