Elasticsearch 常见分片分配失败故障排除

学习如何排除并解决常见的 Elasticsearch 分片分配失败。本指南涵盖识别未分配的分片、诊断磁盘空间错误、节点不可用和分配过滤等问题,并提供可操作的解决方案和最佳实践,以维护健康的 Elasticsearch 集群。

32 浏览量

Elasticsearch 分片分配常见失败故障排除

Elasticsearch 是一个强大的分布式搜索和分析引擎,它在很大程度上依赖于通过分片将数据分布到多个节点的能力。当这些分片分配失败时,可能导致数据不可用、搜索失败以及集群健康状况下降。了解分片分配失败的常见原因并知道如何诊断和解决它们,对于维护稳定且高性能的 Elasticsearch 环境至关重要。本文将指导您了解最常见的问题,并提供可行的步骤,使您的分片恢复到已分配状态。

本指南侧重于生产环境 Elasticsearch 的实际故障排除。我们将介绍如何识别未分配的分片,了解失败的常见原因(如磁盘空间、分配规则和节点问题),并提供清晰的步骤来高效地解决这些问题。通过掌握这些技巧,您可以最大限度地减少停机时间,并确保 Elasticsearch 集群的可靠性。

识别未分配的分片

故障排除的第一步是识别哪些分片未分配以及原因。Elasticsearch 提供了几种工具来实现这一点:

使用集群健康 API

_cluster/health API 提供集群状态的高级别概览。在响应中查找 unassigned_shards。非零值表示存在问题。

GET _cluster/health

响应示例片段:

{
  "cluster_name": "my-es-cluster",
  "status": "yellow",
  "timed_out": false,
  "number_of_nodes": 3,
  "number_of_data_nodes": 3,
  "active_primary_shards": 10,
  "active_shards": 20,
  "relocating_shards": 0,
  "initializing_shards": 1,
  "unassigned_shards": 1,
  "delayed_unassigned_shards": 0,
  "number_of_pending_tasks": 0,
  "max_length_search_concurrency": 1000,
  "max_length_search_size": 10000,
  "active_shards_percent_as_number": 95.45454545454545
}

在此示例中,"status": "yellow""unassigned_shards": 1 表明有一个分片未分配。red 状态意味着一个或多个主分片未分配,影响数据可用性。yellow 状态意味着副本分片未分配,但主分片已分配,因此您的数据仍可搜索,但并非完全冗余。

使用分配解释 API

为了深入了解特定分片未分配的原因,_cluster/allocation/explain API 非常有用。您可以提供分片详细信息,或者让它分析集群状态。

获取任何未分配分片的解释:

GET _cluster/allocation/explain

获取特定分片的解释(替换 index_nameshard_id):

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

常见原因和解决方案

多种因素可能导致分片未分配。以下是最常见的原因及解决方法:

1. 磁盘空间不足

这可以说是分片分配失败最常见的原因。当节点磁盘空间耗尽时,Elasticsearch 会阻止新分片分配到该节点,以避免数据损坏并确保稳定性。它还可能驱逐现有分片。

  • 症状: Allocation Explain API 通常会报告类似 "cannot allocate because disk usage [X%] exceeds the low watermark [Y%]""cannot allocate because disk usage [X%] exceeds the high watermark [Y%]" 的消息。
  • 诊断: 检查数据节点的磁盘使用情况。您可以使用 _cat/allocation API 进行快速概览:
    bash GET _cat/allocation?v
    查找磁盘使用率高的节点。
  • 解决方案:
    • 添加更多磁盘空间: 最直接的解决方案是为受影响的节点添加更多存储空间,或用更大的磁盘替换现有磁盘。
    • 删除未使用索引: 识别并删除消耗磁盘空间的旧索引或不必要的索引。
    • 调整水印: 您可以在 elasticsearch.yml 配置文件中或通过集群设置 API 动态调整磁盘使用率水印(cluster.routing.allocation.disk.watermark.lowcluster.routing.allocation.disk.watermark.highcluster.routing.allocation.disk.watermark.flood_stage)。但是,调整这些值时务必谨慎,因为它们旨在保护您的集群。在不增加容量的情况下降低它们可能会导致进一步的问题。
      json PUT _cluster/settings { "persistent": { "cluster.routing.allocation.disk.watermark.low": "85%", "cluster.routing.allocation.disk.watermark.high": "90%", "cluster.routing.allocation.disk.watermark.flood_stage": "95%" } }
    • 添加更多节点: 通过添加更多数据节点来扩展您的集群。这可以分散数据并减轻单个节点的负载。
    • 强制合并或删除旧数据: 如果您有时间序列数据,可以考虑在旧索引上使用 _forcemerge API 来减少段的数量(这可以释放磁盘空间),或者使用索引生命周期管理 (ILM) 来自动删除旧数据。

2. 节点不可用或正在重启

如果节点宕机、正在重启或遇到网络问题,则驻留在该节点上的任何分片都将变为未分配。如果为主分片,集群状态将变为红色。

  • 症状: Allocation Explain API 会指示由于节点不可用或因宕机而被标记为 (excluded) 而无法分配该分片。
  • 诊断: 使用 _cat/nodes API 检查节点的状​​态。确保所有预期的节点都已列出且运行正常。
    bash GET _cat/nodes?v
    检查受影响节点上的 Elasticsearch 日志,以获取任何错误或关机迹象。
  • 解决方案:
    • 重启节点: 如果节点宕机,请尝试重启 Elasticsearch 服务。
    • 解决网络问题: 确保节点可以与集群中的其他节点通信。
    • 检查日志: 检查特定节点的 Elasticsearch 日志以确定故障的根本原因(例如,内存不足、磁盘错误、JVM 问题)。
    • 增加 index.unassigned.node_left.delayed_timeout: 如果节点频繁加入和离开集群(例如,在滚动重启期间),您可能会看到副本分片暂时变为未分配。index.unassigned.node_left.delayed_timeout 设置(默认为 1 分钟)允许 Elasticsearch 在将离开节点的 [分片] 标记为未分配之前等待,为节点重新加入提供时间。如有必要,可以增加此值,但要注意对恢复时间的影响。

3. 分配过滤和感知规则

Elasticsearch 允许您使用各种分配规则(如节点属性和反亲和性)来控制分片的分配位置。如果这些规则阻止分配,分片可能会变为未分配。

  • 症状: Allocation Explain API 会报告特定属性的分配已禁用,或者根据配置的规则没有可用节点。
  • 诊断:
    • 检查索引设置中的 index.routing.allocation.require.*index.routing.allocation.include.*index.routing.allocation.exclude.*index.routing.allocation.total_shards_per_node
    • 检查集群设置中的 cluster.routing.allocation.enable(例如,allprimariesnew_primariesnone)。
    • 使用 GET _cat/nodeattrs?v 验证节点属性。
  • 解决方案:
    • 更新索引设置: 删除或调整限制性索引路由规则。例如,允许分配到任何节点:
      json PUT my-index/_settings { "index": { "routing": { "allocation": { "require": null, "include": null, "exclude": null } } } }
    • 更新集群设置: 如果分配已被禁用,请暂时启用它:
      json PUT _cluster/settings { "persistent": { "cluster.routing.allocation.enable": "all" } }
      请记住,如果此设置仅用于临时目的,请将其恢复。
    • 更新节点属性: 确保您的节点具有 elasticsearch.yml 中定义的预期属性(例如,node.attr.zone: us-east-1),并且这些属性与您的分配规则一致。更改 elasticsearch.yml 后,需要重启节点才能使更改生效。

4. 分片数据损坏(罕见)

在极少数情况下,分片数据可能会损坏,导致 Elasticsearch 无法启动或分配分片。这在底层磁盘问题上更为常见。

  • 症状: 日志可能显示与读取分片数据或索引损坏相关的错误。Allocation Explain API 可能不会给出明确的原因,或者可能指向读取错误。
  • 诊断: 仔细检查预期分片所在节点上的 Elasticsearch 日志。查找 I/O 错误或数据损坏消息。
  • 解决方案:
    • 从快照恢复: 最可靠的解决方案是从已知良好的快照恢复受影响的索引(或整个集群)。这就是定期备份至关重要的原因。
    • 强制删除分片(最后手段): 如果您无法从快照恢复,并且数据不重要或可以重新索引,您可能需要强制删除损坏的分片。这是一项高级操作,仅在您了解其影响时才应执行。您通常需要停止受影响的节点,手动删除分片数据目录,然后重启节点。这将导致该分片的数据丢失。 请查阅 Elasticsearch 文档以获取适合您版本的确切过程。

5. 迁移容量不足

当节点离开集群或出现磁盘空间问题时,Elasticsearch 会尝试将分片迁移到其他节点。如果没有足够合适的节点,或者集群已经负载过重,分片迁移可能会停滞,导致 initializing_shardsunassigned_shards

  • 症状: 分片长时间停留在 initializingrelocating 状态,或者新分片无法分配。
  • 诊断: 检查 _cat/shards_cat/allocation 以查看分片状态和磁盘使用情况。监控集群健康状况和节点的 CPU/IO 利用率。
  • 解决方案:
    • 添加更多节点: 通过添加更多数据节点来增加集群的容量。
    • 释放资源: 解决现有节点上的任何性能瓶颈(例如,高 CPU、磁盘 I/O 缓慢)。
    • 调整分片分配设置: 您可以调整 cluster.routing.allocation.node_concurrent_recoveries(节点上可并发恢复的分片数量)和 cluster.routing.allocation.node_concurrent_incoming_recoveries(可从另一个节点并发恢复的分片数量)等设置。但是,请谨慎操作,因为增加这些值可能会使集群承受更大的压力。

预防最佳实践

  • 监控磁盘空间: 主动监控所有数据节点的磁盘使用情况。设置警报,以便在磁盘使用率超过预定阈值(例如 80% 或 85%)时收到通知。
  • 实施索引生命周期管理 (ILM): 自动化时间序列数据的管理,包括滚动、收缩和删除旧索引。这有助于控制磁盘空间使用。
  • 定期快照: 确保您拥有稳健的备份策略,并定期自动备份数据快照。定期测试您的恢复过程。
  • 理解分配规则: 根据您的硬件、数据和可用性要求,仔细规划和配置分片分配规则。
  • 足够的硬件: 确保您的节点具有足够的 CPU、RAM 和 I/O 能力来处理工作负载和分片恢复过程。
  • 集群健康监控: 定期使用 _cluster/health API 检查您的集群健康状况,并使用 Kibana 的 Stack Monitoring 等工具进行可视化。

结论

Elasticsearch 中的分片分配失败可能是一个棘手的问题,但通过使用 Cluster Health API 和 Allocation Explain API 等工具系统地诊断问题,并理解磁盘空间、节点可用性和分配规则等常见原因,您可以有效地解决它们。主动监控和遵守最佳实践,例如定期备份和 ILM,是首先预防这些问题的关键,并确保一个稳定、健康的 Elasticsearch 集群。