误入集群的节点引发的shard unassigned线上故障

date
Jan 27, 2024
slug
误入集群的节点引发的shard unassigned线上故障
status
Published
tags
Tech
Elasticsearch
summary
背景是对线上的 es7 集群(这里简称为集群 A)进行动态扩容,A 集群配置 3个 node 节点,在进行节点重启时误重启了其他集群(这里简称为集群B)废弃的节点,导致 AB 两个集群不可用,red 状态。
type
Post
是否完成
是否完成
主题
技术
发布平台
博客
状态
完成
背景是对线上的 es7 集群(这里简称为集群 A)进行动态扩容,A 集群配置 3个 node 节点,在进行节点重启时误重启了其他集群(这里简称为集群B)废弃的节点,导致 AB 两个集群不可用,red 状态。

现象

  • AB 两个集群 red 状态
  • A 集群有节点 offline
  • B 集群节点都 online,但多个 index 的主副分片 unassigned

解决办法

这里先交代下最后的解决办法:
A 集群 对于 A 集群,找到正确的 es 安装地址,动态扩容后重启即可。
B 集群 而对于 B 集群就比较复杂些,着重解决 shard unassigned 问题。
  1. 检查哪些 index 的 shard 出现 unassigned 问题 可以通过命令:GET _cat/shards?h=index,shard,prirep,state,unassigned.reason定位到出现问题的 index。如果你平常是使用 kibana 来查询监控集群的,当集群 status=red 时,kibana 是无法连接到集群的,也就无法使用 Dev Tools。这里推荐你使用 Cerebro,一款提供对于 ElasticSearch 更加友好的可视化操作支持的工具。直接执行 cat apis
    1. notion image
  1. 三思而后行 要从出现问题的 index 角度出发,如果是无关紧要或者是已经下线不在使用的,可以直接删除;反之删除 index 操作要慎重。 根据 unassigned.reason 具体问题具体分析,根据官方的解释有如下:
  • INDEX_CREATED:由于创建索引的 API 导致未分配。
  • CLUSTER_RECOVERED :由于完全集群恢复导致未分配。
  • INDEX_REOPENED :由于打开 open 或关闭 close 一个索引导致未分配。
  • DANGLING_INDEX_IMPORTED :由于导入 dangling 索引的结果导致未分配。
  • NEW_INDEX_RESTORED :由于恢复到新索引导致未分配。
  • EXISTING_INDEX_RESTORED :由于恢复到已关闭的索引导致未分配。
  • REPLICA_ADDED:由于显式添加副本分片导致未分配。
  • ALLOCATION_FAILED :由于分片分配失败导致未分配。
  • NODE_LEFT :由于承载该分片的节点离开集群导致未分配。
  • REINITIALIZED :由于当分片从开始移动到初始化时导致未分配(例如,使用影子 shadow 副本分片)。
  • REROUTE_CANCELLED :作为显式取消重新路由命令的结果取消分配。
  • REALLOCATED_REPLICA :确定更好的副本位置被标定使用,导致现有的副本分配被取消,出现未分配。
    • 根据目前查询的结果来看,我是属于 DANGLING_INDEX_IMPORTED

我做了哪些尝试

❎ 由于出现故障,导致分配分片的 5 次(默认)重试机会用完了,所以不会再自动分配,需要进行 retry
POST /_cluster/reroute?retry_failed=true
❎ 调整 index 的副本数为 0
curl -XPUT 'localhost:9200/<INDEX_NAME>/_settings' -d '{"number_of_replicas": 0}'
❎ 调整 index 的刷新时间为 5m
curl -XPUT 'localhost:9200/<INDEX_NAME>/_settings' -d ' { "settings": { "index.unassigned.node_left.delayed_timeout": "5m" } }'
✅ 手动分配分片,将主分片分配(只丢失部分数据,出现问题的 index 均为不在使用的)
POST _cluster/reroute {"commands": [ { "allocate_stale_primary": { "index": "index_name", "shard": 4, "node": "node1", "accept_data_loss" : true } }]}

分析

搜罗下网上归纳的出现 unassigned 的主要原因,建议直接阅读原文:How to Resolve Unassigned Shards in Elasticsearch | Datadog

补充下

不同版本的 es 的 reroute 语法
ES2.x 的 reroute 命令:
curl -XPOST 'localhost:9200/_cluster/reroute' -d '{ "commands" : [ { "move" : { "index" : "test", "shard" : 0, "from_node" : "node1", "to_node" : "node2" } }, { "allocate" : { "index" : "test", "shard" : 1, "node" : "node3", "allow_primary":true (表示接受主分片数据丢失) } } ]}'
ES5.x 升级之后,已经把主分片的恢复和副本的恢复进行了区分,Cluster Reroute | Elasticsearch Reference [5.6] | Elastic
curl -XPOST 'localhost:9200/_cluster/reroute' -d '{ "commands" : [ { "move" : { "index" : "test", "shard" : 0, "from_node" : "node1", "to_node" : "node2" } }, { "allocate_replica" : { "index" : "test", "shard" : 1, "node" : "node3" } }, { "allocate_empty_primary": { "index" : "test", "shard" : 1, "node" : "node3", "accept_data_loss":true (接受数据丢失) } } ]}'
不同情况下手动分配分片的流程
  • red 情况下手动分配主分配操作流程
    • 先查询未分配的主分片原来是在哪个节点上 GET /order_orderlist/_shard_stores
    • 将主分片分配(只丢失部分数据)
      • POST _cluster/reroute { "commands": [ { "allocate_stale_primary": { "index": "index_name", "shard": 4, "node": "node1", "accept_data_loss" : true } } ]}
        如果数据不重要,可以不用放到原来的节点上,直接新建一个空分片替代
        POST _cluster/reroute { "commands": [ { "allocate_empty_primary": { "index": "test_11", "shard": 2, "node": "node0", "accept_data_loss" : true }} ]}
  • yellow 情况下手动分配副本分片操作:
    • POST /_cluster/reroute {"commands" :[ { "allocate_replica" : { "index" : "index_name", "shard" : 0, "node": "node1" } } ] }
      主分片的恢复用 allocate_empty_primary,而副本的恢复用 allocate_replica
    • [[2022-06-20]]
      • 补充:在 unassigned 的分片比较多的时候,可以使用脚本
      • #!/bin/bash for index in $(curl -s 'http://localhost:9200/_cat/shards' | grep UNASSIGNED | awk '{print $1}' | sort | uniq); do for shard in $(curl -s 'http://localhost:9200/_cat/shards' | grep UNASSIGNED | grep $index | awk '{print $2}' | sort | uniq); do echo $index $shard curl -XPOST 'localhost:9200/_cluster/reroute' -d "{ 'commands' : [ { 'allocate' : { 'index' : $index, 'shard' : $shard, 'node' : 'Master', 'allow_primary' : true } } ] }" sleep 5 done done
      • 可以参考的几篇文章:
        • 总结得最整的是 https://www.datadoghq.com/blog/elasticsearch-unassigned-shards/
        • 单独针对主 shard 出现 unassigned 的解决可以看
          • http://blog.kiyanpro.com/2016/03/06/elasticsearch/reroute-unassigned-shards/
          • https://t37.net/how-to-fix-your-elasticsearch-cluster-stuck-in-initializing-shards-mode.html
          • http://www.wklken.me/posts/2015/05/23/elasticsearch-issues.html
        • 单独针对副本 shard 出现 unassigned 的解决可以看
          • https://z0z0.me/recovering-unassigned-shards-on-elasticsearch/
          • https://dpatil1410.wordpress.com/2016/09/24/its-red-how-do-i-recover-unassigned-elasticsearch-shards/
    If you have any questions, please contact me.