理解 Elasticsearch 主节点选举和法定人数要求
Elasticsearch 是一个分布式系统,它依赖节点间的协调来维护集群状态的一致视图。这种协调的核心在于 主节点 (Master Node)。主节点是集群元数据的唯一真实来源,确保其稳定性和正确的选举对于集群的健康、可扩展性和弹性至关重要。
本文详细介绍了主节点的关键职责,解释了最新 Elasticsearch 版本(7.x+)中使用的现代选举流程,并阐明了法定人数(Quorum)这一基本概念——它是防止“脑裂”(split-brain)这一灾难性场景所必需的机制。
主节点的关键作用
虽然数据节点负责索引、搜索和存储数据的繁重工作,但主节点负责管理整个集群的结构和元数据。除非它同时被配置为数据节点,否则它通常不参与查询或索引操作。
主节点职责
- 集群状态管理: 主节点维护并发布 集群状态 (cluster state)——集群当前配置的蓝图,包括存在哪些索引、这些索引的映射和设置,以及每个分片的所在位置。
- 节点管理: 处理节点的加入和离开,并相应地更新集群状态。
- 索引管理: 创建、删除或更新索引。
- 分片分配: 决定主分片和副本分片应驻留在何处(初始分配和节点故障后的重新平衡)。
如果主节点发生故障,在成功选出新主节点之前,集群将无法执行管理任务或重新分配分片。
理解主节点选举和投票
在分布式系统中,每当当前主节点发生故障或变得不可达时,都需要一个选举过程。自 Elasticsearch 7.0 以来,选举机制得到了显著的简化和加强,主要是通过取消了复杂的 discovery.zen.minimum_master_nodes 设置,并引入了自管理的 投票配置 (Voting Configurations)。
选举流程 (Elasticsearch 7.x+)
主节点选举现在由主节点候选节点 (master-eligible nodes) 自动处理,这些节点在配置中使用 node.roles: [master, data] 或仅使用 node.roles: [master](用于专用主节点)来定义。
- 候选人发现: 主节点候选节点相互通信,以确定当前活动的投票成员集合。
- 法定人数检查: 节点检查它们是否能够达到 法定人数 (quorum)——即已知投票节点的大多数——以确保达成共识。
- 领导者选择: 如果建立了法定人数,则基于一个打破平局的机制(如集群状态 ID),排名最高的候选人将被提议为新主节点。
- 投票和确认: 该提议将被投票表决,如果被大多数接受,新主节点将接管控制权并发布新的集群状态。
初始集群引导 (Bootstrapping)
首次启动一个全新的集群时,Elasticsearch 需要知道哪些节点应参与初始投票配置。这是使用 cluster.initial_master_nodes 设置来处理的。此设置仅应在集群初始启动时使用一次。
# elasticsearch.yml 片段,用于初始设置
cluster.name: my-production-cluster
node.name: node-1
node.roles: [master, data]
# 列出用于初始引导的所有主节点候选节点的名称
cluster.initial_master_nodes: [node-1, node-2, node-3]
提示: 一旦集群运行稳定,您应该从所有节点的配置文件中移除或注释掉
cluster.initial_master_nodes设置,以避免节点稍后在混合状态下重启时可能出现的问题。
法定人数要求与脑裂预防
法定人数要求的根本原因在于保证任何时候只能选出一个领导者,从而防止 脑裂 (split-brain) 问题。
什么是脑裂?
当网络分区将集群分割成两个或多个隔离的段,并且每个段都认为自己是权威主节点时,就会发生脑裂。如果发生这种情况,不同段中的节点可能会独立地接受索引请求和分配分片,导致网络最终恢复连接时出现数据不一致和损坏。
法定人数规则(多数共识)
为了防止脑裂,Elasticsearch 强制执行多数共识规则,要求至少需要特定数量的投票节点对任何集群状态更改达成一致。这个最小值就是法定人数,计算公式如下:
$$\text{法定人数} = \lfloor (\text{投票节点数} / 2) \rfloor + 1$$
通过要求严格的多数票,如果网络发生分区,只有较大的那一部分(持有多数票的一方)才能达到法定人数并继续操作。无法选举主节点的一方将停止工作,等待网络连接恢复,从而避免向分区段写入数据。
| 投票主节点数 (N) | 所需法定人数 (N/2 + 1) |
|---|---|
| 3 | 2 |
| 5 | 3 |
| 7 | 4 |
最佳实践警告: 始终部署奇数个主节点候选节点(例如,三个或五个)。部署偶数个(例如四个)虽然提供了与前一个奇数个(三个)相同的容错能力,但会消耗更多资源。例如,一个 4 节点投票集群需要 3 票 (N/2+1),这意味着它只能容忍一次故障,与 3 节点集群相同,但多使用了一台服务器。
配置专用主节点
在生产环境中,特别是大型集群(20+ 数据节点),强烈建议使用专用主节点。这可以将资源密集型的搜索/索引任务与主节点至关重要的管理职责分离开来。
专用主节点配置示例
要在配置中将一个节点设置为主节点候选节点但不存储数据或运行摄取管道,请在 elasticsearch.yml 中使用以下角色:
# 节点 1:专用主节点
node.name: es-master-01
node.roles: [master]
# 禁用纯主节点的 HTTP/传输流量(可选,但良好的安全实践)
# http.enabled: false
# transport.bind_host: [专用主节点的私有IP]
专用数据节点配置示例
相反,应阻止专用数据节点参与主节点选举过程:
# 节点 4:专用数据节点
node.name: es-data-04
node.roles: [data]
# 注意:如果未指定角色,Elasticsearch 默认为 [master, data, ingest](8.0 之前的默认设置)
集群发现设置
所有节点都必须配置为使用 discovery.seed_hosts 设置来查找同一组主节点候选节点。此设置列出了 Elasticsearch 可以尝试联系以加入集群的其他节点的网络地址。
# 集群中所有节点的通用设置
discovery.seed_hosts: ["10.0.0.1:9300", "10.0.0.2:9300", "10.0.0.3:9300"]
此列表应包含主节点候选节点(es-master-01, es-master-02, es-master-03 等)的地址。
故障排除选举问题
如果集群未能选举出主节点,它通常会进入“红色”或“黄色”状态并记录持续的错误。常见原因包括:
| 问题 | 描述与解决方案 |
|---|---|
| 网络问题 | 由于防火墙规则、路由问题或高延迟,节点之间无法通信。确保节点之间 9200(HTTP)和 9300(传输)端口已打开。 |
| 配置不匹配 | cluster.name 不正确或 discovery.seed_hosts 未指向正确的主节点候选节点。验证所有节点使用相同的设置。 |
| 法定人数丢失 | 同时有太多主节点候选节点发生故障(例如,在 3 节点主节点设置中发生两次故障)。可能需要手动干预(例如,使用 api/cluster/decommission/voting_config_exclusions API)来强制将故障节点从投票列表中移除。 |
| 磁盘 I/O | 主节点的磁盘 I/O 饱和,阻止其快速发布集群状态,导致超时和重复选举。 |
检查投票配置
您可以使用集群 API 查看当前的投票配置:
GET /_cluster/state?filter_path=metadata.cluster_coordination.voting_config_excluding_deferred
此输出确认了哪些节点当前被计入法定人数,确保您的配置与您的容错目标相符。
总结
主节点选举过程是 Elasticsearch 集群弹性的支柱。通过理解主节点的职责并正确实施法定人数规则(在引导期间使用奇数的主节点候选节点并确保 cluster.initial_master_nodes 正确),管理员可以可靠地防止脑裂场景,并维护一个高可用的分布式系统。在生产环境中,务必使用专用主节点来隔离管理任务,并确保集群状态的可靠发布。