Elasticsearch 集群在运行的过程中,由于各种原因,经常会出现健康问题。比较直观的是:kibana监控、head插件监控显示集群非绿色(红色或者黄色)。
遇到这种情况不要慌,本文给出基础集群故障排查及修复指南,希望对你有所帮助。1、集群健康状态的解读
- 黄色状态:表示所有主分片均已分配,但有一个或多个副本分片未分配。如果集群中的某个节点发生故障,则在修复该节点之前,某些数据可能不可用;
- 红色状态:表示存在一个或多个主分片未分配,因此某些数据不可用。在集群启动期间,伴随着主分片的分配过程,这可能会短暂发生。
索引级别状态由最坏的分片状态控制。集群状态由最差索引状态控制。解释一下:我们通常说集群状态变红了,实际上集群中某个索引出了问题,更精确的说,是某个索引上的某个分片出了问题。集群处于黄色状态,索引仍在工作,并且数据也全部可以被索引、搜索,只是速度和可靠性可能达不到预期。当前出问题的副本分片可能:丢失、损坏或存在其他问题;或者集群可能处于移动或重建副本分片的过程中。我们要做的工作是:手动或者自动重新处理这些可能出问题的副本分片以实现集群恢复绿色状态。集群处于红色状态,代表-一个或多个索引缺少主分片,即无法索引、搜索或提供数据。健康状态基于每个分片的,假设集群中有50个分片,其中一个主分片出问题,其所在索引状态是红色,整个集群也都会变成红色。我们要做的工作是:手动查找或修复这些未分配的主分片,否则一旦索引数据丢失,只能从快照或原始源数据中重新创建索引。2、定位红色或黄色的索引
2.1 第一步:确定你所知道的主要问题。
例如节点宕机、磁盘空间(磁盘使用逼近或超过警戒水位线:85%、90%、甚至95%的磁盘使用率)问题等,这些问题很可能会造成集群状态的变化。这些外部明显的问题便于我们追溯问题、“对症下药”形成解决方案。有时你只需要耐心等待,因为系统通常会通过移动数据来进行自我修复。举例1:重新启动会经历集群由红色变为黄色、黄色变为绿色。举例2:一个节点的主分片出了问题,系统会将副本分片升级为主分片,然后重新创建新副本,但这需要几分钟到更长的时间,具体取决于:分片数量、大小,集群负载,磁盘速度等。但是,除非明确系统正在修复,否则你不能仅指望系统自身修复这一招。有时情况确实是主分片或者副本分片出了问题,这也是为什么要了解历史记录的原因。日志和慢日志都有助于辅助排查历史记录。如果你是集群运维人员,当集群出故障之后,你看到或者监控到是集群健康状态的变化,你还能看到日志,大致知道业务层面在做什么操作导致,但是,还是强烈建议你结合你的判定结果和开发人员进行业务层面的确认和推敲,以辅助定位问题所在。2.2 第二步:确定哪些索引有问题,多少索引有问题。
_cat API 可以通过返回结果告诉我们这一点:
GET _cat/indices?v&health=red
GET _cat/indices?v&health=yellow
GET _cat/indices?v&health=green
由此我们可以了解到我们遇到了多少问题,这很可能与上述最近发生的事件有关。
我们还需要此截图列表,以便我们可以更深入地研究每个索引。2.3 第三步:查看有问题的分片以及原因。
这与索引列表有关,但是索引列表只会告诉你哪些索引存在问题,现在还需要我们根据索引列表形成问题列表。
GET /_cat/shards?v&h=n,index,shard,prirep,state,sto,sc,unassigned.reason,unassigned.details&s=sto,index
只提示一个字段的含义:unassigned.reason 未分配分片的原因,返回值包括:- ALLOCATION_FAILED:由于分片分配失败而未分配。
- CLUSTER_RECOVERED:由于集群恢复而未分配。
- DANGLING_INDEX_IMPORTED:由于导入了悬空索引导致未分配。
- EXISTING_INDEX_RESTORED:由于恢复为已关闭的索引导致未分配。
- INDEX_CREATED:由于API创建索引而未分配。
- INDEX_REOPENED:由于打开已关闭索引而未分配。
- NEW_INDEX_RESTORED:由于恢复到新索引而未分配。
- NODE_LEFT:由于托管的节点离开集群而未分配。
- REALLOCATED_REPLICA:确定了更好的副本位置,并导致现有副本分配被取消。
- REINITIALIZED:当分片从开始移动回初始化,导致未分配。
- REPLICA_ADDED:由于显式添加副本而未分配。
- REROUTE_CANCELLED:由于显式取消重新路由命令而未分配。
通过未分配列原因unassigned.reason似乎是已经够详细了,但是有时候我们需要更多细节,特别是如果我们有节点路由或其他更复杂的问题。2.4 进一步定位未分配的原因
为此,我们可以要求集群进一步返回给定分片的当前分配情况和逻辑。需要结合 2.3 返回结果对下面的 _cluster/allocation/explain API 参数进行修改。GET /_cluster/allocation/explain
{
"index": "my_index_003",
"shard": 0,
"primary": false
}
返回的结果也一目了然,在下面的 explanation 指出:分片不能再分配到相同的节点,是因为:该节点上已经有对应的主分片上了。
有集群基础认知的同学肯定都知道:主分片和副本分片要分配到不同的集群节点上。这个问题的根源也逐步明朗:我是单节点集群,但是为新建的索引 my_index_003 设置了副本分片,导致了副本分片无法分配,分片呈现黄色。这将使你对情况有更详细的了解,接下来的操作取决于你在那里找到原因。- 分片数限制 ——每个节点的分片数量过多,在创建新索引或删除某些节点且系统找不到它们的位置时很常见;
- JVM或内存限制——一些版本在内存不足时可以限制分片分配;
- 路由或分配规则——通用高可用云云或大型复杂系统会遇到;
- 崩溃或严重问题——可能会出现更多问题,每个问题都需要特别注意或解决,或者在许多情况下,需要重新导入数据解决。
2.5 对症下药,解决问题。
第一类:等待并让 Elasticsearch 集群自行修复。删除所有副本,针对场景:也许你无法修复副本或手动移动或分配它。在这种情况下,只要拥有主分片(健康状态为黄色,而不是红色),就可以始终使用以下命令将副本数设置为0,等待一分钟,然后再设置为1或任意你业务场景需要设置的值。PUT my_index_003/_settings
{
"index": {
"number_of_replicas": 0
}
}
第三类:手动分配分片,借助 reroute API。POST /_cluster/reroute
{
"commands": [
{
"move": {
"index": "test", "shard": 0,
"from_node": "node1", "to_node": "node2"
}
},
{
"allocate_replica": {
"index": "test", "shard": 1,
"node": "node3"
}
}
]
}
共做了:move 移动分片 和 allocate_replica 分配副本两个操作。许多高可用或复杂的系统使用路由或分配规则来控制分片分配,随着情况的变化,这会创建无法分配的分片。这个时候,explain API 有助于排查问题。3、小结
之前也写过集群红色、黄色修复方案的文章,这次的更系统化一些,更偏方法论。本篇的脉络参考翻译了:https://www.elkman.io/blog/elasticsearch-index-red-yellow-why。集群健康状态的维护是一项大工程,实际业务实战中遇到的问题远比我列的复杂,但我们要具备化繁为简的能力,一步步把问题拆解,大问题变成小问题,4、加餐-讨论
大家稍安勿躁,面包会有的,在一步步筹备筹划中,时间都待定......大家对本公众号内容有好的意见或者建议,也欢迎留言讨论,置顶留言会有神秘奖励。加微信:elastic6(仅有少量坑位了),和 BAT 大佬一起精进 Elastic 技术!