解决红色集群状态:Elasticsearch 故障排查逐步指南

一份实用的 Elasticsearch 红色集群检查清单,涵盖未分配的主分片、分配解释、磁盘水位线和节点丢失。

解决红色集群状态:Elasticsearch 故障排查逐步指南

Elasticsearch 集群状态为红色意味着至少有一个主分片未分配。这是关键所在。某些数据可能不可用,针对受影响索引的搜索可能返回部分或失败的结果,并且对这些分片的写入无法正常进行。

黄色则不同:主分片已分配,但一个或多个副本未分配。黄色仍然值得关注,因为冗余性降低,但红色是事故。不要一开始就删除数据或手动重新路由分片。首先找出哪个主分片未分配以及 Elasticsearch 拒绝分配它的原因。

了解 Elasticsearch 集群健康

Elasticsearch 提供了一个集群健康 API,可以获取集群状态和分片分配的快照。此 API 是诊断健康问题的主要工具。

GET _cluster/health

此命令的输出将包含一个 status 字段,其值可以是 greenyellowred。它还提供有关活动分片和未分配分片数量的信息。

  • 绿色:所有主分片和副本分片都已分配并正常运行。
  • 黄色:所有主分片已分配,但某些副本分片未分配。
  • 红色:一个或多个主分片未分配,导致这些分片的数据不可用。

在事故发生时,使用更详细的健康检查调用:

GET _cluster/health?level=indices

然后列出未分配的分片:

GET _cat/shards?v&h=index,shard,prirep,state,unassigned.reason,node&s=state,index

红色/黄色状态的常见原因和故障排查步骤

当集群不是 green 时,就该进行调查了。以下是未分配分片的最常见原因以及解决方法:

1. 磁盘空间不足

Elasticsearch 有保护机制,防止因磁盘满导致数据损坏。如果节点磁盘空间不足,它将阻止新分片分配或现有分片恢复。

诊断:

  • 检查每个节点的磁盘使用情况。
  • 使用集群分配解释 API 了解分片未分配的原因。
GET _cluster/allocation/explain

此 API 将提供详细的原因说明,通常指向磁盘水位线。

解决方法:

  • 释放磁盘空间: 删除旧索引、将数据移动到其他层级或增加容量。在事故期间强制合并活动索引不是快速的磁盘空间修复方法,并且可能增加大量 I/O。
  • 增加更多磁盘空间: 增加节点的存储容量。
  • 配置磁盘水位线: 仅在当前值不适合您的环境时,调整 cluster.routing.allocation.disk.watermark.lowhighflood_stage。提高水位线可以争取时间,但也可能掩盖实际的容量问题。

2. 节点离开集群(节点驱逐)

节点可能因网络问题、崩溃或有意移除而离开集群。如果持有分片(尤其是主分片)的节点离开,这些分片将变为未分配。

诊断:

  • 检查集群日志,查找最近离开的节点。
  • 监控节点之间的网络连接。
  • 确保所有节点可以相互发现。检查 discovery.seed_hosts、传输连接和集群日志。不要将 cluster.initial_master_nodes 作为通用修复方法重新引入已形成的集群。

解决方法:

  • 重启节点: 如果节点崩溃或无响应,尝试重启。
  • 解决网络问题: 解决节点之间的任何网络连接问题。
  • 重新添加节点: 如果节点被有意移除,确保在重新加入集群之前正确配置。

3. 分片分配过滤和感知

配置不当的分片分配规则可能会阻止分片分配到可用节点。

诊断:

  • 检查您的 cluster.routing.allocation.* 设置,特别是 cluster.routing.allocation.includeexcluderequire 过滤器。
  • 如果使用区域或机架感知,检查 cluster.routing.allocation.awareness.attributes

解决方法:

  • 调整分配过滤器: 修改过滤器以允许分片分配到适当的节点。
  • 纠正感知属性: 确保节点正确标记了感知属性(如果使用),并且分配规则遵循这些属性。

4. 分配磁盘空间不足(索引创建后)

即使磁盘未满,如果 Elasticsearch 预测分配后磁盘将超过高水位线,它也可能阻止分片分配。这与磁盘水位线相关,但特别影响新分配。

诊断:

  • 在这里,_cluster/allocation/explain API 非常有用。
  • 检查可用空间与分片的预期大小。

解决方法:

  • 与一般磁盘空间问题类似:释放空间、增加更多存储或谨慎调整水位线。

5. 分片大小和节点容量

非常大的分片或大量分片可能会给节点资源(CPU、内存)带来压力并影响分配。此外,如果节点已达到分片限制(cluster.routing.allocation.total_shards_per_node),新分片将不会分配给它。

诊断:

  • 检查分片大小(GET _cat/shards?v)。
  • 监控节点资源利用率(CPU、内存)。
  • 检查 cluster.routing.allocation.total_shards_per_node 设置。

解决方法:

  • 减少分片压力: 对于未来的索引,调整滚动和分片计数,使分片落在可管理的大小范围内。对于现有索引,仅在集群足够稳定以处理工作负载后,使用重新索引、收缩或拆分。
  • 增加节点容量: 添加更强大的节点或具有更多内存/CPU 的节点。
  • 调整分片限制: 如果必要且有足够资源,增加 cluster.routing.allocation.total_shards_per_node

6. 主节点问题

不稳定的主节点可能导致分片分配问题。如果主节点不可用或无法履行职责,分片可能变为未分配。

诊断:

  • 检查集群日志中与主节点相关的错误或警告。
  • 确保有奇数个符合主节点条件的节点(通常为 3 或 5 个),以避免脑裂情况。
  • 验证符合主节点条件的节点可以选举主节点。

解决方法:

  • 稳定主节点: 确保符合主节点条件的节点健康、有足够资源且连接良好。
  • 检查引导历史: cluster.initial_master_nodes 仅用于首次集群形成。引导后,从节点配置中移除它,并通过日志、传输网络和投票配置来排查主节点不稳定问题。

使用 _cluster/allocation/explain 进行高级故障排查

_cluster/allocation/explain API 是了解特定分片未分配原因的最强大工具。

示例:

GET _cluster/allocation/explain
{
  "index": "my-index",
  "shard": 0,
  "primary": true
}

这将返回详细的 JSON 输出,解释为什么 my-index 的主分片 0 无法分配。查找 deciders 等字段,这些字段列出了未分配的原因(例如 DISK_THRESHOLDNODE_LEFTNO_VALID_SHARD_COPY)。

解决黄色集群状态

黄色状态意味着主分片已分配,但副本未分配。这主要影响数据冗余和容错能力。

常见原因:

  • 节点不足: 没有足够的节点来容纳索引所需的副本数量。
  • 分片分配过滤: 与红色状态类似,过滤器可能阻止副本分配。
  • 磁盘空间限制: 节点可能有足够空间容纳主分片,但不足以容纳副本,尤其是在磁盘水位线生效时。

解决方法:

  • 添加更多节点: 增加集群中的节点数量。
  • 调整副本数量: 如果容错能力对所有索引不重要,减少每个索引的副本数量(index.number_of_replicas)。
  • 检查分配设置: 确保副本分片允许分配到可用节点。

维护集群健康的最佳实践

  • 监控磁盘使用情况: 主动监控所有节点的磁盘空间并设置警报。
  • 合理调整集群规模: 确保有足够的节点和资源来应对数据量和查询负载。
  • 分片管理: 将分片大小保持在推荐范围内,避免过度分片。
  • 定期检查集群健康:GET _cluster/healthGET _cluster/allocation/explain 作为日常监控的一部分。
  • 测试更改: 在对分配设置或磁盘水位线进行重大更改之前,先在测试环境中进行测试。

一旦知道分配决策器,路径通常就很清晰。磁盘阈值意味着容量问题。NODE_LEFT 意味着恢复或替换缺失的节点。NO_VALID_SHARD_COPY 意味着可能需要快照恢复或使用 Elasticsearch 文档中记录的不安全恢复程序做出有意的数据丢失决策。最后一种情况应缓慢处理,首先检查备份,因为使集群脱离红色的命令也可能确认丢失的主分片的最新数据永久丢失。