排查 Elasticsearch 红色或黄色集群健康状态

集群健康状态显示红色或黄色,表示一个或多个分片没有分配到节点。

  • 红色:集群中存在未分配的主分片,搜索和索引等操作可能因此失败。
  • 黄色:所有主分片都已分配,但有一些副本分片尚未分配。这会增加数据丢失风险,并可能降低集群性能。

健康状态为红色或黄色时,集群仍会尽可能处理搜索与索引请求,但可能推迟某些管理和清理活动,直到健康状态恢复为绿色。例如:

  • 某些索引生命周期管理(ILM)操作要求目标索引的健康状态为绿色。
  • Kibana 需要其依赖的底层系统索引为绿色才能加载,否则会返回 Kibana server is not ready yet 错误。

在许多情况下,集群会自动恢复为绿色。如果没有自动恢复,就必须手动解决遗留问题,让管理和清理活动能够继续。这段视频 演示了如何监控分配健康状态。

通过 AutoOps 检测和解决问题

AutoOps 是一种监控工具,可以实时检测 Elasticsearch 集群中的问题,并提供解决问题和改善性能的建议。请参阅 AutoOps 介绍。

诊断集群状态

检查集群状态

使用集群健康 API:

GET _cluster/health?filter_path=status,*_shards

健康集群的 status 为 green,unassigned_shards 为零。yellow 表示只有副本分片未分配;red 表示一个或多个主分片未分配。

提示:对于 Elastic Cloud Enterprise 和 Elastic Cloud Hosted 部署,也可以在 Elastic Cloud Console 或 ECE Cloud UI 中,通过部署的“Monitoring”页面检查健康状况。该页面提供健康问题、受影响范围与故障排查支持的详细信息。更多信息见 云部署健康状况。

查看未分配的分片

使用 cat shards API:

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

未分配分片的 state 为 UNASSIGNED。prirep 的值为 p 时表示主分片,为 r 时表示副本分片。

要了解分片为什么没有分配,以及必须采取什么操作才能让 Elasticsearch 分配它,请使用集群分配解释 API:

GET _cluster/allocation/explain?filter_path=index,node_allocation_decisions.node_name,node_allocation_decisions.deciders.*
{
  "index": "my-index",
  "shard": 0,
  "primary": false
}

常见响应示例见 使用集群分配 API 排查问题。

修复红色或黄色健康状态

分片可能因多种原因处于未分配状态。以下内容介绍最常见的原因及解决办法。

单节点集群

Elasticsearch 永远不会将副本分片分配到对应主分片所在的同一个节点上。单节点集群因此始终会显示黄色。若要变为绿色,必须将所有索引的 number_of_replicas 设为 0。只有在理解无副本运行的影响,即容错能力与恢复选择减少之后,才能这样做。

同样,如果副本数量等于或超过节点数量,就会有部分分片无法分配。

恢复丢失的节点

数据节点离开集群时,分片常常会变成未分配状态。可能的原因包括:

  • 手动重启节点会使集群暂时处于不健康状态,直到节点恢复。
  • 节点过载或故障可能暂时破坏集群健康状态。内存不足错误,或高强度搜索期间的高内存使用量,可能导致长时间垃圾回收(GC)暂停,进而触发这种情况。有关 JVM 的其他问题,见下文“降低 JVM 内存压力”。
  • 网络问题可能使节点无法可靠通信,导致分片不同步。检查日志中是否反复出现节点离开并重新加入集群的消息。

解决问题并恢复节点后,节点会重新加入集群。Elasticsearch 随后自动分配所有未分配的分片。

可以通过查看集群健康状态监控这一过程。未分配分片的数量应逐步减少,直到状态恢复为绿色。

为避免因暂时性问题浪费资源,Elasticsearch 默认将分配延迟一分钟。如果节点已恢复,而你不想等待延迟结束,可以不带参数调用集群 reroute API,启动分配过程。这个过程在后台异步执行。

POST _cluster/reroute

修正分配设置

错误的分配设置可能导致主分片无法分配,相关设置包括:

使用获取索引设置与获取集群设置 API,查看当前分配设置:

GET my-index/_settings?flat_settings=true&include_defaults=true
GET _cluster/settings?flat_settings=true&include_defaults=true

可以通过更新索引设置与更新集群设置 API 修改这些设置。

分配副本或减少副本数量

为防范硬件故障,Elasticsearch 不会把副本分配到对应主分片所在的节点上。如果没有其他可容纳副本的数据节点,它就会一直未分配。可以采用以下办法:

  • 在同一数据层中添加数据节点,用来承载副本。
  • 修改索引设置 index.number_of_replicas,减少每个主分片的副本数量。为了高可用性,建议每个主分片至少保留一个副本。
PUT _settings
{
  "index.number_of_replicas": 1
}

释放或增加磁盘空间

Elasticsearch 使用磁盘低水位阈值,确保数据节点有足够空间接收分片。默认情况下,不会将分片分配到磁盘使用率超过 85% 的节点。

通过 cat allocation API 检查节点当前的磁盘空间:

GET _cat/allocation?v=true&h=node,shards,disk.*

如果节点空间不足,可以选择:

  • 升级节点,增加磁盘容量。
  • 向集群添加更多节点。
  • 删除不再需要的索引以释放空间。使用 ILM 时,可以更新生命周期策略,采用可搜索快照或添加删除阶段。如果不再需要搜索这些数据,可以通过快照将它们存储到集群之外。
  • 如果索引不再写入数据,可使用 force merge API 或 ILM 的 force merge 操作,将它的段合并为更大的段。
POST my-index/_forcemerge

如果索引是只读的,可以使用 shrink index API 或 ILM 的 shrink 操作,减少其主分片数量。

POST my-index/_shrink/my-shrunken-index

如果节点磁盘容量很大,可以提高磁盘低水位阈值,或者将它设置为明确的字节值。

PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.disk.watermark.low": "90%",
    "cluster.routing.allocation.disk.watermark.high": "95%"
  }
}

重要:提高阈值通常只是临时解决办法。如果不释放磁盘空间,可能导致集群不稳定。

重新启用分片分配

在重启或其他集群维护期间,通常会禁用分片分配,以防节点暂时离开集群时触发连锁恢复。如果维护结束后没有重新启用,Elasticsearch 就无法分配分片。

使用集群设置 API 确认分配是否被禁用:

GET _cluster/settings?include_defaults=true&filter_path=*.cluster.routing.allocation.enable

如果未启用分配,响应会在 persistent 或 transient 层级显示对默认值的覆盖,例如:

{
  "persistent": {
    "cluster": {"routing": {"allocation": {"enable": "none" } } }
  },
  "defaults": {
    "cluster": {"routing": {"allocation": {"enable": "all" } } } }
}

注意:cluster.routing.allocation.enable 仅影响今后的分片分配,不会改变现有分配。因此,将它覆盖为 none 不会阻止现有数据摄入。但覆盖期间无法创建新索引,包括 ILM Rollover 触发创建的索引。

要重新启用分配,请重置集群设置 cluster.routing.allocation.enable:

PUT _cluster/settings
{
  "persistent" : {
    "cluster.routing.allocation.enable" : null
  }
}

重新启用后,集群会自动恢复分片分配、恢复和再平衡。可以使用集群健康 API 查看状态:

GET _cluster/health

这段视频演示了如何排查“no allocations are allowed”问题。

降低 JVM 内存压力

分片分配需要 JVM 堆内存。过高的 JVM 内存压力可能触发熔断器,使分配停止,分片因此保持未分配状态。请参阅 JVM 内存压力过高。

恢复丢失主分片的数据

如果包含主分片的节点丢失,Elasticsearch 通常可以利用另一个节点上的副本替换它。如果无法恢复节点,而且副本不存在或不可恢复,Allocation Explain 将报告 no_valid_shard_copy,此时必须选择以下方案之一:

  • 从快照恢复缺失数据。
  • 从原始数据源重新索引缺失数据。
  • 运行 Delete Index,在整个索引层面接受数据丢失。
  • 执行 Cluster Reroute 的 allocate_stale_primary 或 allocate_empty_primary 命令,并设置 accept_data_loss: true,在分片层面接受数据丢失。

警告:只有在节点已经不可能恢复时,才能使用下面的选项。它会分配一个空的主分片。如果原节点后来重新加入集群,Elasticsearch 会用这个较新的空分片数据覆盖原主分片,从而造成数据丢失。

POST _cluster/reroute
{
  "commands": [
    {
      "allocate_empty_primary": {
        "index": "my-index",
        "shard": 0,
        "node": "my-node",
        "accept_data_loss": "true"
      }
    }
  ]
}

这段视频演示了如何排查 no_valid_shard_copy。


原文:Red or yellow cluster health status。作者/维护者:Elastic 文档团队。本文为原文的中文译文;代码保留原文内容。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容