Elasticsearch 分片分配问题:原因与解决方案

通过分配解释、磁盘检查、节点过滤和安全恢复步骤诊断 Elasticsearch 分片分配问题。

Elasticsearch 分片分配问题:原因与解决方案

Elasticsearch 分片分配问题通常表现为集群健康状态为黄色或红色。黄色表示主分片已分配,但至少一个副本未分配。红色表示至少一个主分片未分配,因此某些数据可能不可用,直到您恢复它。

本指南将向您展示如何查找分配阻塞器、读取 Allocation Explain API 的输出,并选择风险最小的修复方案。目标是在不加剧数据丢失的情况下恢复分配。

理解分片状态和集群健康

分片是 Elasticsearch 跨数据节点放置的单位。它们可以处于几种状态:

  • STARTED:分片处于活动状态并正在处理请求。
  • RELOCATING:分片正在从一个节点移动到另一个节点。
  • INITIALIZING:分片正在创建或恢复。
  • UNASSIGNED:分片存在于集群元数据中,但未分配到任何节点。

集群健康状态遵循这些分片状态:

  • Green:所有主分片和副本分片都已分配。
  • Yellow:所有主分片都已分配,但一个或多个副本未分配。
  • Red:一个或多个主分片未分配。搜索可能会返回部分结果或对受影响的索引失败,并且对这些索引的写入可能会失败。

分片分配失败的常见原因

Elasticsearch 在放置分片之前使用分配决策器。单个 NO 决策可能会使分片保持未分配状态。

磁盘水位线

磁盘压力是最常见的原因之一。Elasticsearch 使用磁盘水位线来避免填满节点。一旦节点超过低水位线或高水位线,分配决策就会变得更加严格。在洪水水位线阶段,Elasticsearch 可以向受影响的索引添加只读块,以保护节点免于磁盘耗尽。

设置 常见默认值 效果
cluster.routing.allocation.disk.watermark.low 85% 避免将额外的分片分配到超过此阈值的节点。
cluster.routing.allocation.disk.watermark.high 90% 尝试将分片移走,并避免将分片放置在该节点上。
cluster.routing.allocation.disk.watermark.flood_stage 95% 可以阻止对受影响索引的写入。

在更改任何内容之前,请确认集群的实际设置:

GET /_cluster/settings?include_defaults=true&filter_path=**.disk.watermark*

然后检查节点磁盘使用情况:

GET /_cat/allocation?v&h=node,disk.used_percent,disk.avail,disk.total,shards

释放空间、添加磁盘、添加数据节点、删除旧索引或减少副本压力。如果设置了洪水阶段块,请在修复磁盘压力后仅将其删除:

PUT /my_index/_settings
{
  "index.blocks.read_only_allow_delete": null
}

节点角色和分配过滤器

索引分片仅分配到具有数据角色和匹配分配过滤器的节点。如果您将节点属性用于热/暖层、机架、区域或存储类型,则拼写错误可能会导致分片搁浅。

例如,具有 index.routing.allocation.require.box_type: high_io 的索引将仅分配到配置了 node.attr.box_type: high_io 的节点。

检查索引过滤器和节点属性:

GET /my_index/_settings?filter_path=*.settings.index.routing.allocation
GET /_cat/nodeattrs?v
GET /_cat/nodes?v&h=name,roles,disk.used_percent

修复索引设置或添加合格的数据节点。不要随意在多区域集群中移除分配感知;它可能会将分片的所有副本放置在同一个故障域中。

缺少主分片

如果主分片未分配,则持有活动主分片的节点可能已消失,索引可能刚刚恢复,或者分配规则可能正在阻止每个符合条件的节点。在 Allocation Explain API 告诉您 Elasticsearch 无法分配分片的原因之前,不要假设数据已丢失。

常见场景包括:

  • 持有唯一良好主分片副本的节点崩溃。
  • 分配过滤器排除了所有可以托管主分片的数据节点。
  • 快照恢复或索引创建正在等待符合条件的节点。
  • 存在过时的分片副本,但 Elasticsearch 不会在没有明确接受数据丢失的情况下提升它。

首先尝试恢复丢失的节点、恢复快照或修复分配阻塞器。仅当您了解哪个副本已过时或您已接受该分片的数据丢失时,才使用强制主分配。

分片限制

每个节点的分片限制也可能阻止分配。常见设置包括 index.routing.allocation.total_shards_per_nodecluster.routing.allocation.total_shards_per_node

检查这些限制:

GET /_cluster/settings?include_defaults=true&filter_path=**.total_shards_per_node
GET /my_index/_settings?filter_path=*.settings.index.routing.allocation.total_shards_per_node

添加节点、减少副本数量、合并小索引或谨慎提高相关限制。每个节点分片过多可能会增加堆压力并减慢集群状态操作。

使用 Allocation Explain API 进行诊断

Allocation Explain API 是回答“为什么这个分片没有分配?”的最佳工具。

GET /_cluster/allocation/explain?pretty
{
  "index": "my_data",
  "shard": 0,
  "primary": true
}

要让 Elasticsearch 选择一个当前未分配的分片,请在没有请求体的情况下调用 API:

GET /_cluster/allocation/explain?pretty

首先阅读这些字段:

  • can_allocate:高级答案。
  • allocate_explanation:通俗易懂的摘要。
  • node_allocation_decisions:每个节点的决策。
  • deciders:返回 NOTHROTTLE 的确切规则。

NO 决策是阻塞器。THROTTLE 决策通常意味着 Elasticsearch 可以分配分片,但正在限制并发恢复工作。

安全故障排除顺序

从宽泛开始,然后缩小范围。

1. 检查集群健康和未分配的分片

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

查看 unassigned.reason。诸如 NODE_LEFTINDEX_CREATEDCLUSTER_RECOVEREDALLOCATION_FAILED 之类的值会告诉您下一步该看哪里。

2. 检查磁盘和节点资格

GET /_cat/allocation?v&h=node,disk.used_percent,disk.avail,disk.total
GET /_cat/nodes?v&h=name,roles,heap.percent,ram.percent,cpu,disk.used_percent

如果节点接近高水位线,请在更改分配设置之前修复磁盘压力。

3. 运行 Allocation Explain

使用受影响的索引、分片编号和主/副本标志。输出应命名阻止分配的名称、节点条件或决策器。

4. 在了解原因之前避免有风险的重新路由

手动重新路由命令适用于特定的恢复情况。它们不是磁盘压力、错误过滤器或过多副本的通用修复方法。

如果过时的主副本是唯一可行的恢复路径,则命令如下所示:

POST /_cluster/reroute
{
  "commands": [
    {
      "allocate_stale_primary": {
        "index": "index_name",
        "shard": 0,
        "node": "node_name_with_stale_copy",
        "accept_data_loss": true
      }
    }
  ]
}

accept_data_loss: true 是必需的,这是有原因的。只有在检查了快照、尝试恢复丢失的节点并确认哪个节点持有过时副本之后,才使用它。

5. 单独处理黄色健康状态

如果只有副本未分配,集群仍然可以服务主数据。首先修复底层资源约束。添加数据节点、清理磁盘或更正分配过滤器通常可以让 Elasticsearch 自动分配副本。

如果您必须暂时在没有副本的情况下运行,请减少受影响索引的副本数量:

PUT /my_index/_settings
{
  "index.number_of_replicas": 0
}

这可以使健康状态变为绿色,因为 Elasticsearch 不再期望该索引有副本。它也会降低可用性,因此在您添加容量或修复分配后,请将副本设置回所需的值。

预防分配问题

  • 在节点超过高磁盘水位线之前发出警报。
  • 为您的副本数量和分配感知规则保留足够的数据节点。
  • 使用适合您的堆、数据量和恢复目标的分片计数。
  • 审查索引模板,以便新索引不会继承错误的副本计数或分配过滤器。
  • 在事件发生之前测试节点替换和快照恢复步骤。

要点

您最安全的路径很简单:识别未分配的分片,运行 Allocation Explain,修复返回 NO 的决策器,并避免强制分配,除非您已接受数据丢失的权衡。