排查常见Elasticsearch集群脑裂场景

学习诊断和解决关键的Elasticsearch脑裂问题。本指南涵盖网络分区和错误仲裁配置等常见原因。探索实用的诊断步骤,包括网络检查和日志分析,并按照清晰、逐步的解决流程恢复集群稳定性。实施预防策略,保护您的Elasticsearch部署免受未来脑裂事件的影响。

排查常见Elasticsearch集群脑裂场景

脑裂是Elasticsearch中人们谈论的故障,因为它听起来很戏剧化,但更有用的实际问题更实际:集群的多个部分能否同时做出主节点级别的决策?现代Elasticsearch版本通过基于多数派的集群协调来防止这种情况。较旧的集群,尤其是7.0之前且discovery.zen.minimum_master_nodes设置不当的集群,更容易配置错误。

因此,本文区分了两种经常被混淆的情况。真正的脑裂意味着独立的分区可以各自选举或保留一个主节点。主节点选举中断意味着集群无法选举主节点,因为它没有多数派。前者存在集群状态冲突和数据不一致的风险。后者虽然痛苦,但通常是更安全的故障模式。

脑裂的表现

在健康的集群中,一个选举产生的主节点管理集群状态:索引创建、分片分配决策、映射、节点成员资格以及类似的元数据。数据节点可以处理读写操作,但集群仍然依赖于单一主节点的全局视图。

当网络分区或错误的发现设置让两组节点各自认为自己是真正的集群时,就会发生脑裂场景。一侧可能接受对某个索引的写入,而另一侧接受不同的写入。当连接恢复时,Elasticsearch无法像合并文本文件那样简单地合并两个冲突的历史记录。

在现代Elasticsearch中,如果一个分区没有多数派的主节点候选节点,它就不应该选举主节点。这意味着某些节点可能变得不可用,而不是形成一个竞争集群。这是您想要的行为。

版本很重要

对于Elasticsearch 6.x及更早版本,关键设置是:

discovery.zen.minimum_master_nodes: 2

规则是主节点候选节点的多数派:(N / 2) + 1,在加1之前向下取整进行整数除法。对于三个主节点候选节点,设置为2。对于五个,设置为3。在三节点集群中将其设置为1会使脑裂成为可能。

对于Elasticsearch 7.x及更高版本,discovery.zen.minimum_master_nodes已不存在。集群协调发生了变化,Elasticsearch管理投票配置。新集群仍然需要使用cluster.initial_master_nodes进行正确的引导,但该设置仅用于首次集群形成。集群形成后,将其从配置中移除。

不要通过添加旧的discovery.zen设置来“修复”现代集群。它们不再是控制平面。

常见原因

最常见的触发因素是主节点候选节点之间的网络分区。在云环境中,可能是安全组更改、错误的路由表、网络ACL、区域级别问题或阻止传输端口9300的防火墙规则。在裸机环境中,可能是交换机、VLAN、DNS、MTU或数据包丢失问题。

另一个原因是运行的主节点候选节点太少。两个主节点候选节点很尴尬,因为其中一个失败后没有明确的多数派。生产集群通常使用三个专用主节点候选节点,或者在小型部署中使用三个混合角色节点。

第三个原因是陈旧或重复使用的数据目录。如果您克隆VM或重用旧集群的磁盘,节点可能携带您不想要的集群元数据。这可能导致令人困惑的加入失败,在最坏的情况下,意外形成一个单独的集群。

最后,在压力下手动恢复可能会使问题变得更糟。在您知道哪个分区是权威之前,重启随机节点、擦除数据路径或强制不安全分配,可能会将可恢复的事件转变为数据丢失。

事件期间的初步检查

首先询问每个可达节点它的看法:

curl -s "http://NODE:9200/_cat/master?v"
curl -s "http://NODE:9200/_cat/nodes?v&h=ip,name,roles,master,node.role"
curl -s "http://NODE:9200/_cluster/health?pretty"

如果可能,对多个节点运行这些命令。如果不同节点报告不同的主节点或不同的节点成员资格,您可能正在查看一个分区集群或孤立节点。

检查主节点候选节点上的日志,查找有关选举、加入、断开连接和发布失败的消息。有用的搜索词包括master not discoveredelected-as-masternode-leftnode-joinpublicationconnect_transport_exceptionhandshake

然后测试传输连接,而不仅仅是HTTP:

nc -vz node-1.example.internal 9300
nc -vz node-2.example.internal 9300
nc -vz node-3.example.internal 9300

在节点之间运行这些测试。负载均衡器或堡垒机访问HTTP端口9200几乎不能告诉您Elasticsearch节点是否可以通过9300形成集群。

检查发现和引导配置

在Elasticsearch 7.x及更高版本上,检查这些设置:

cluster.name: my-cluster
discovery.seed_hosts:
  - node-1:9300
  - node-2:9300
  - node-3:9300

仅适用于全新集群:

cluster.initial_master_nodes:
  - node-1
  - node-2
  - node-3

引导名称必须与node.name匹配。集群形成后,从所有节点中移除cluster.initial_master_nodes

在Elasticsearch 6.x及更早版本上,检查:

discovery.zen.minimum_master_nodes: 2

对于三个主节点候选节点的集群。同时确认所有主节点候选节点具有一致的发现主机和集群名称。

恢复原则

如果您怀疑真正的脑裂,在您知道哪个分区是权威之前,停止通过集群API进行更改。最安全的恢复通常遵循以下顺序:

  1. 保留证据:从每个分区收集日志、节点列表、主节点视图和索引健康状态。
  2. 恢复网络连接或有意隔离错误的一侧。
  3. 根据多数派、最新有效数据和业务影响选择权威分区。
  4. 停止不应继续作为独立分区的节点上的Elasticsearch。
  5. 一次一个地重新加入节点,并验证它们加入了权威集群。
  6. 如果任何主分片历史丢失或不一致,从快照恢复丢失的数据。

不要将删除事务日志目录作为常规的脑裂修复方法。这是危险的建议。事务日志是Elasticsearch恢复的一部分。手动删除数据路径下的文件可能导致数据丢失,只有在获得Elastic支持针对特定版本的指导,或者您已接受损失并有重建计划时,才应执行此操作。

如果两个分区独立接受写入,可能没有完美的自动合并。您可能需要从快照恢复、从源系统重新索引、重放应用程序日志,或选择一侧的数据作为权威。

一个实际示例

想象一个跨三个私有子网的三节点集群。防火墙更改意外阻止了节点1与节点2和3之间的传输流量。节点2和3仍然可以看到彼此,因此它们保留或选举了一个主节点。节点1看不到多数派。在现代、正确配置的集群中,节点1不应自行形成一个竞争主节点。使用节点1的客户端可能会失败,但集群避免了冲突的主节点。

现在想象一个旧的6.x集群,有三个主节点候选节点和discovery.zen.minimum_master_nodes: 1。节点1可以选举自己,而节点2和3选举另一个主节点。这是经典的脑裂风险。修复不仅仅是重新连接网络。您还需要纠正仲裁配置,并决定如何处理在错误一侧接受的任何写入。

预防

对于中小型集群,使用三个主节点候选节点。对于较大的集群,使它们成为专用主节点,以便搜索和索引负载不会干扰集群协调。

将主节点候选节点放在可靠、低数据包丢失的网络上。跨区域分布节点有助于提高可用性,但前提是区域之间的网络可靠且仲裁设计仍然合理。

监控主节点变更。计划维护期间的主节点选举是正常的。正常流量期间的频繁选举是警告信号。

监控传输连接,而不仅仅是HTTP正常运行时间。如果传输流量被阻止,节点可以响应9200但仍然无法正确参与集群。

定期进行快照并测试恢复。副本不能保护您免受严重事件期间的错误删除、数据损坏或冲突写入的影响。

小心引导设置。在现代集群上,cluster.initial_master_nodes不是日常发现设置。用它来创建新集群,然后将其移除。

最好的脑裂恢复是您永远不需要的那种:基于多数派的主节点资格、正确的版本特定发现设置、简单的网络规则以及经过测试的快照计划。

如何区分脑裂和正常选举

主节点选举不一定是脑裂。在滚动重启、网络波动或主节点故障期间,Elasticsearch可能会选举新的主节点。如果集群保持一个权威主节点,并且旧主节点退出,这是正常的分布式系统行为。

警告信号是不同节点的不同视图。如果节点A报告自己是主节点,而节点B报告节点C是主节点,请停下来调查。如果两组节点在断开连接时都接受集群状态更改,那么您面临的情况比短暂的选举严重得多。

还要观察客户端行为。固定在孤立节点上的客户端可能会看到故障,即使多数派一侧是健康的。这并不意味着多数派集群已损坏。这可能意味着您的客户端连接策略或负载均衡器仍在将流量发送到无法参与的节点。

负载均衡器和客户端路由

Elasticsearch传输发现与客户端HTTP路由不同。不要将主节点发现放在通用HTTP负载均衡器后面,并期望它解决集群成员资格问题。节点之间需要传输连接。

对于客户端,使用多个HTTP端点或能够快速移除不健康节点的负载均衡器。失去主节点的节点可能仍会短暂监听进程,但它不是写入的好目标。健康检查应该比“端口9200已打开”更有意义。

一个实用的HTTP健康检查可能会在本地查询集群健康,并拒绝没有发现主节点的节点。具体方法取决于您的客户端和基础设施,但原则很简单:不要继续向孤立节点发送写入。

事件后清理

集群稳定后,比较索引健康、文档计数和应用程序级别的权威来源计数。如果写入有可能落在不同分区上,仅凭Elasticsearch健康无法证明数据在语义上是正确的。

审查时间线。哪个节点首先失去连接?事件发生前哪个节点是主节点?客户端是否继续写入?快照是否是最新的?警报是否在用户注意到之前触发?这些细节决定了您是需要仅网络修复还是数据协调计划。

对于较旧的集群,安排版本和发现设置工作。如果您仍在运行依赖于discovery.zen.minimum_master_nodes的版本,请确保它今天正确,然后规划升级路径。脑裂预防不是一次性的运行手册步骤;它是集群生命周期管理的一部分。

恐慌期间应避免的配置更改

不要更改cluster.name以使节点加入。这会造成不同的集群身份问题。

不要擦除数据路径,除非您有意丢弃节点的本地分片副本,并确认集群在其他地方有有效副本或可用快照。

不要将cluster.initial_master_nodes重新添加到现有的现代集群作为常规重启修复。该设置用于初始引导,而不是常规发现。

不要在旧集群上降低类似仲裁的保护措施以恢复可用性。使少数派分区可写可能感觉像是进展,但这正是冲突主节点成为可能的方式。

为棘手的故障域设计

当没有单一基础设施事件可以同时移除两个节点时,三个主节点候选节点效果最佳。在三区域云环境中,每个区域一个主节点候选节点是常见模式。在两区域环境中,放置更困难,因为一个区域可能包含两个投票。如果该较大区域失败,剩余的一个投票无法安全地选举主节点。这不是Elasticsearch脆弱;这是多数派数学。

不要通过添加偶数个投票节点而不考虑故障模式来解决这个问题。四个主节点候选节点仍然需要多数派,而二对二的分区无法安全地选择一侧。在某些设计中,专用的仅投票节点可以提供帮助,但原则保持不变:集群需要可靠的多数派来做出集群状态决策。

将其写在架构说明中。在中断期间,人们经常问为什么幸存的节点或幸存的区域不能继续提供写入服务。答案应该在事件发生前就明确:在没有多数派的情况下接受写入有冲突历史的风险。