解决集群不稳定的问题

编辑

解决集群不稳定的问题编辑

通常情况下,节点只有在故意关闭时才会离开集群。如果节点意外离开集群,则务必解决其原因。节点意外离开的集群是不稳定的,并且可能会造成多个问题。例如:

  • 集群运行状况可能为黄色或红色。
  • 某些分片将进行初始化,而其他分片可能会失败。
  • 搜索、索引和监控操作可能会失败,并在日志中报告异常。
  • .security 索引可能不可用,从而阻止对集群的访问。
  • 由于频繁的集群状态更新,主节点可能看起来很繁忙。

要对此状态下的集群进行故障排除,请首先确保集群具有稳定的主节点。接下来,在解决所有其他问题之前,请先关注意外离开集群的节点。在集群拥有稳定的主节点和稳定的节点成员资格之前,将无法解决其他问题。

诊断和统计信息在不稳定的集群中通常没有用。这些工具只能提供集群在单个时间点的状态视图。相反,请查看集群日志以了解随时间推移的行为模式。请特别关注来自当选主节点的日志。当节点离开集群时,当选主节点的日志将包含如下消息(为了便于阅读,添加了换行符):

[2022-03-21T11:02:35,513][INFO ][o.e.c.c.NodeLeftExecutor] [instance-0000000000]
    node-left: [{instance-0000000004}{bfcMDTiDRkietFb9v_di7w}{aNlyORLASam1ammv2DzYXA}{172.27.47.21}{172.27.47.21:19054}{m}]
    with reason [disconnected]

此消息表明,当选主节点 (instance-0000000000) 上的 NodeLeftExecutor 处理了一个 node-left 任务,标识了被移除的节点及其移除原因。当节点重新加入集群时,当选主节点的日志将包含如下消息(为了便于阅读,添加了换行符):

[2022-03-21T11:02:59,892][INFO ][o.e.c.c.NodeJoinExecutor] [instance-0000000000]
    node-join: [{instance-0000000004}{bfcMDTiDRkietFb9v_di7w}{UNw_RuazQCSBskWZV8ID_w}{172.27.47.21}{172.27.47.21:19054}{m}]
    with reason [joining after restart, removed [24s] ago with reason [disconnected]]

此消息表明,当选主节点 (instance-0000000000) 上的 NodeJoinExecutor 处理了一个 node-join 任务,标识了添加到集群中的节点以及该任务的原因。

其他节点可能会记录类似的消息,但报告的详细信息较少:

[2020-01-29T11:02:36,985][INFO ][o.e.c.s.ClusterApplierService]
    [instance-0000000001] removed {
        {instance-0000000004}{bfcMDTiDRkietFb9v_di7w}{aNlyORLASam1ammv2DzYXA}{172.27.47.21}{172.27.47.21:19054}{m}
        {tiebreaker-0000000003}{UNw_RuazQCSBskWZV8ID_w}{bltyVOQ-RNu20OQfTHSLtA}{172.27.161.154}{172.27.161.154:19251}{mv}
    }, term: 14, version: 1653415, reason: Publication{term=14, version=1653415}

这些消息对于故障排除并不是特别有用,因此请关注来自 NodeLeftExecutorNodeJoinExecutor 的消息,这些消息仅在当选主节点上发出,并且包含更多详细信息。如果您没有看到来自 NodeLeftExecutorNodeJoinExecutor 的消息,请检查:

  • 您正在查看当选主节点的日志。
  • 日志涵盖了正确的时间段。
  • 日志记录级别已启用为 INFO

每当节点开始或停止跟随当选主节点时,它们也会记录一条包含 master node changed 的消息。您可以使用这些消息来确定每个节点对主节点状态随时间推移的看法。

如果节点重新启动,它将离开集群,然后再次加入集群。当它重新加入时,NodeJoinExecutor 将记录它处理了一个 node-join 任务,表明该节点正在 重新启动后加入。如果节点意外重新启动,请查看该节点的日志以了解其关闭的原因。

受影响节点上的运行状况 API 也将提供有关情况的一些有用信息。

如果节点没有重新启动,那么您应该更仔细地查看其离开的原因。每个原因都有不同的故障排除步骤,如下所述。共有三种可能的原因:

  • disconnected:从主节点到被移除节点的连接已关闭。
  • lagging:主节点发布了集群状态更新,但被移除的节点未在允许的超时时间内应用它。默认情况下,此超时时间为 2 分钟。有关控制此机制的设置的信息,请参阅发现和集群形成设置
  • followers check retry count exceeded:主节点向被移除的节点发送了多次连续的运行状况检查。这些检查被拒绝或超时。默认情况下,每次运行状况检查在 10 秒后超时,Elasticsearch 在连续三次运行状况检查失败后移除该节点。有关控制此机制的设置的信息,请参阅发现和集群形成设置

诊断 disconnected 节点编辑

节点通常会在关闭时以 disconnected 的原因离开集群,但如果它们在没有重新启动的情况下重新加入集群,则说明存在其他问题。

Elasticsearch 旨在在相当可靠的网络上运行。它会在节点之间打开多个 TCP 连接,并希望这些连接永远保持打开状态。如果连接关闭,Elasticsearch 将尝试重新连接,因此即使受影响的节点短暂离开集群,偶尔出现的故障也应该对其操作的影响有限。相反,反复断开的连接将严重影响其运行。

从当选主节点到集群中每个其他节点的连接尤为重要。当选主节点从不主动关闭其到其他节点的出站连接。同样,一旦连接完全建立,节点也从不主动关闭其入站连接,除非该节点正在关闭。

如果您看到某个节点以 disconnected 的原因意外离开集群,则可能是 Elasticsearch 以外的其他原因导致连接关闭。常见原因是配置错误的防火墙,其超时时间设置不正确或存在其他与 Elasticsearch 不兼容的策略。这也可能是由一般的连接问题引起的,例如由于硬件故障或网络拥塞导致的丢包。如果您是高级用户,则可以通过配置以下记录器来获取有关网络异常的更多详细信息:

logger.org.elasticsearch.transport.TcpTransport: DEBUG
logger.org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport: DEBUG

在极端情况下,您可能需要使用 tcpdump 进行数据包捕获,以确定节点之间的消息是否被网络上的其他设备丢弃或拒绝。

诊断 lagging 节点编辑

Elasticsearch 需要每个节点都能相当快地处理集群状态更新。如果某个节点处理集群状态更新的时间过长,则可能会对集群造成损害。主节点将以 lagging 的原因移除这些节点。有关控制此机制的设置的信息,请参阅发现和集群形成设置

滞后通常是由被移除节点上的性能问题引起的。但是,节点也可能由于严重的网络延迟而滞后。要排除网络延迟,请确保 net.ipv4.tcp_retries2正确配置。包含 warn threshold 的日志消息可能会提供有关根本原因的更多信息。

如果您是高级用户,则可以通过配置以下记录器来获取有关节点在被移除时正在执行的操作的更多详细信息:

logger.org.elasticsearch.cluster.coordination.LagDetector: DEBUG

启用此记录器后,Elasticsearch 将尝试在故障节点上运行节点热点线程 API,并在当选主节点的日志中报告结果。结果将被压缩、编码并拆分为多个块,以避免截断:

[DEBUG][o.e.c.c.LagDetector      ] [master] hot threads from node [{node}{g3cCUaMDQJmQ2ZLtjr-3dg}{10.0.0.1:9300}] lagging at version [183619] despite commit of cluster state version [183620] [part 1]: H4sIAAAAAAAA/x...
[DEBUG][o.e.c.c.LagDetector      ] [master] hot threads from node [{node}{g3cCUaMDQJmQ2ZLtjr-3dg}{10.0.0.1:9300}] lagging at version [183619] despite commit of cluster state version [183620] [part 2]: p7x3w1hmOQVtuV...
[DEBUG][o.e.c.c.LagDetector      ] [master] hot threads from node [{node}{g3cCUaMDQJmQ2ZLtjr-3dg}{10.0.0.1:9300}] lagging at version [183619] despite commit of cluster state version [183620] [part 3]: v7uTboMGDbyOy+...
[DEBUG][o.e.c.c.LagDetector      ] [master] hot threads from node [{node}{g3cCUaMDQJmQ2ZLtjr-3dg}{10.0.0.1:9300}] lagging at version [183619] despite commit of cluster state version [183620] [part 4]: 4tse0RnPnLeDNN...
[DEBUG][o.e.c.c.LagDetector      ] [master] hot threads from node [{node}{g3cCUaMDQJmQ2ZLtjr-3dg}{10.0.0.1:9300}] lagging at version [183619] despite commit of cluster state version [183620] (gzip compressed, base64-encoded, and split into 4 parts on preceding log lines)

要重建输出,请对数据进行 base64 解码,并使用 gzip 对其进行解压缩。例如,在类 Unix 系统上:

cat lagdetector.log | sed -e 's/.*://' | base64 --decode | gzip --decompress

诊断 follower check retry count exceeded 节点编辑

节点有时会在关闭时以 follower check retry count exceeded 的原因离开集群,但如果它们在没有重新启动的情况下重新加入集群,则说明存在其他问题。

Elasticsearch 需要每个节点都能成功且相当快地响应网络消息。如果某个节点拒绝请求或根本没有响应,则可能会对集群造成损害。如果连续多次检查失败,则主节点将以 follower check retry count exceeded 的原因移除该节点,并在 node-left 消息中指示有多少次连续检查失败以及有多少次超时。有关控制此机制的设置的信息,请参阅发现和集群形成设置

超时和失败可能是由受影响节点上的网络延迟或性能问题引起的。确保 net.ipv4.tcp_retries2正确配置,以消除网络延迟作为此类不稳定性的可能原因。包含 warn threshold 的日志消息可能会提供有关不稳定性原因的更多线索。

如果最后一次检查因异常而失败,则会报告该异常,并且通常会指示需要解决的问题。如果有任何检查超时,请按如下方式缩小问题范围。

  • GC 暂停记录在 Elasticsearch 默认发出的 GC 日志中,通常也记录在主节点日志的 JvmMonitorService 中。使用这些日志来确认节点是否正在经历高堆使用率和长时间的 GC 暂停。如果是这样,高堆使用率故障排除指南中提供了一些进一步调查的建议,但通常您需要在堆使用率高的时候捕获堆转储,才能完全了解问题。
  • VM 暂停也会影响同一主机上的其他进程。VM 暂停通常还会导致系统时钟中断,Elasticsearch 会在其日志中报告这种情况。如果您发现其他进程在同一时间暂停,或者出现意外的时钟中断,请调查运行 Elasticsearch 的基础设施。
  • 数据包捕获将揭示系统级和网络级的故障,尤其是在当选主节点和故障节点同时捕获网络流量时。用于跟随者检查的连接不用于任何其他流量,因此即使使用了 TLS,也可以仅从流量模式中轻松识别它:几乎每秒钟都会有几百个字节来回发送,首先是主节点的请求,然后是跟随者的响应。您应该能够观察到此类连接上的任何重传、丢包或其他延迟。
  • 可以通过在相关日志消息之前的几秒钟内获取主 Elasticsearch 进程的堆栈转储(例如,使用 jstack)或分析跟踪(例如,使用 Java Flight Recorder)来识别特定线程可用的长时间等待。

    节点热点线程 API 有时会提供有用的信息,但请记住,此 API 还需要在集群中的所有节点上使用多个 transport_workergeneric 线程。该 API 可能会受到您要诊断的问题的影响。jstack 更可靠,因为它不需要任何 JVM 线程。

    参与发现和集群成员资格的线程主要是 transport_workercluster_coordination 线程,它们不应该长时间等待。Elasticsearch 日志中也可能有线程长时间等待的证据,特别是查看来自 org.elasticsearch.transport.InboundHandler 的警告日志。有关更多信息,请参阅网络线程模型

默认情况下,跟随者检查将在 30 秒后超时,因此如果节点离开是不可预测的,则每隔 15 秒捕获一次堆栈转储,以确保至少在一个正确的时间获取了一个堆栈转储。

诊断 ShardLockObtainFailedException 错误编辑

如果一个节点离开并重新加入集群,Elasticsearch 通常会关闭并重新初始化其分片。如果分片没有快速关闭,Elasticsearch 可能会因为 ShardLockObtainFailedException 而无法重新初始化它们。

要收集有关分片缓慢关闭原因的更多信息,请配置以下记录器

logger.org.elasticsearch.env.NodeEnvironment: DEBUG

启用此记录器后,Elasticsearch 会在遇到 ShardLockObtainFailedException 时尝试运行 节点热点线程 API。结果会被压缩、编码并分成多个块,以避免截断

[DEBUG][o.e.e.NodeEnvironment    ] [master] hot threads while failing to obtain shard lock for [index][0] [part 1]: H4sIAAAAAAAA/x...
[DEBUG][o.e.e.NodeEnvironment    ] [master] hot threads while failing to obtain shard lock for [index][0] [part 2]: p7x3w1hmOQVtuV...
[DEBUG][o.e.e.NodeEnvironment    ] [master] hot threads while failing to obtain shard lock for [index][0] [part 3]: v7uTboMGDbyOy+...
[DEBUG][o.e.e.NodeEnvironment    ] [master] hot threads while failing to obtain shard lock for [index][0] [part 4]: 4tse0RnPnLeDNN...
[DEBUG][o.e.e.NodeEnvironment    ] [master] hot threads while failing to obtain shard lock for [index][0] (gzip compressed, base64-encoded, and split into 4 parts on preceding log lines)

要重建输出,请对数据进行 base64 解码,并使用 gzip 对其进行解压缩。例如,在类 Unix 系统上:

cat shardlock.log | sed -e 's/.*://' | base64 --decode | gzip --decompress