2. etcd 架构与高可用原理

etcd 是云原生集群的“控制面数据库”,所有集群状态(Pod、Service、ConfigMap、Secret 等)都存储在 etcd 中。理解 etcd 的架构与高可用原理,是掌握集群升级故障域、设计多租户迁移恢复策略的基础。本章从 Raft 协议、节点角色、Leader 选举与故障切换三个核心维度展开。

2.1 Raft 协议简述

Raft 是一种易于理解的分布式一致性协议,etcd 使用 Raft 来保证数据在多个节点间强一致。Raft 将一致性问题分解为三个子问题:Leader 选举、日志复制、安全性。

核心原则:只要集群中超过半数节点(N/2 + 1)存活且正常通信,etcd 集群就能对外提供读写服务。这是 etcd 高可用的数学基础。
术语速记:Term(任期)——每次选举产生一个新 Leader 时,Term 递增;每个 Term 内最多只有一个 Leader。
Raft 协议核心流程 Raft 协议核心流程 ① Leader 选举 节点从 Follower 变为 Candidate,发起投票 获得多数票后成为 Leader Leader 选举 触发条件:心跳超时 ② 日志复制 Leader 接收客户端写请求 将日志条目复制到 Follower 多数节点写入后提交 日志复制 保证数据强一致 ③ 安全性 只有拥有最新日志的 节点才能成为 Leader 防止已提交日志被覆盖 安全性 防止日志回滚 Raft 保证:只要多数节点存活,集群始终可用且数据一致

2.2 etcd 集群节点角色

etcd 集群中的每个节点在任意时刻都处于以下三种角色之一:

角色 职责 状态特征 故障影响
Leader 处理所有客户端写请求;管理日志复制;定期发送心跳 唯一;拥有最新日志;处理读写 Leader 故障触发重新选举
Follower 被动接收 Leader 的日志复制;响应 Leader 心跳;处理只读请求(可配置) 多数节点处于此状态;被动同步 Follower 故障不影响写入,但降低读可用性
Candidate Leader 选举期间的临时角色;向其他节点发起投票请求 选举超时后进入;任期递增 选举期间集群短暂不可用(通常毫秒级)
关键约束:一个 Term 内最多只能有一个 Leader。如果两个节点同时成为 Candidate 且票数相同,则进入“split vote”状态,需要等待超时后重新选举。

2.3 Leader 选举机制

Leader 选举是 Raft 协议的核心,也是 etcd 高可用的关键保障。选举过程遵循以下步骤:

  1. 心跳超时触发:Follower 在选举超时时间(election timeout,默认 1000ms)内未收到 Leader 心跳,认为 Leader 已宕机。
  2. 转为 Candidate:Follower 增加当前 Term,转换为 Candidate,并向自己投票。
  3. 发起投票请求:Candidate 向集群中所有其他节点发送 RequestVote RPC,包含自己的 Term 和最新日志索引。
  4. 投票规则:每个节点在一个 Term 内只能投一票;只有日志至少与 Candidate 一样新的节点才会投票。
  5. 赢得选举:Candidate 获得超过半数(N/2 + 1)的投票后成为 Leader。
  6. 心跳宣告:新 Leader 立即发送心跳(AppendEntries RPC)给所有节点,重置选举超时计时器。
选举超时时间:etcd 默认 election-timeout 为 1000ms,实际值在 1000ms ~ 2000ms 之间随机化,防止多个 Follower 同时超时导致 split vote。
etcd Leader 选举流程 etcd Leader 选举流程 正常状态 Leader 发送心跳 Follower 重置超时 心跳超时 Follower 未收到心跳 选举超时触发 转为 Candidate Term 自增 投票给自己 发起投票 RequestVote RPC 赢得选举(获得多数票) 成为新 Leader,发送心跳宣告 选举失败 等待下一轮超时 选举期间集群不可写入,但只读请求仍可被 Follower 处理(需开启 --enable-pprof)

2.4 故障切换机制

etcd 的故障切换(Failover)机制确保在 Leader 或 Follower 节点故障时,集群能自动恢复服务。以下是不同故障场景下的切换行为:

故障场景 切换行为 影响时间 多租户迁移注意事项
Leader 宕机 Follower 检测到心跳超时 → 发起选举 → 新 Leader 产生 ~1-3 秒(选举超时 + 网络延迟) 控制面 API 短暂不可用,租户工作负载不受影响
Follower 宕机 Leader 停止向该 Follower 复制日志;集群降级但继续服务 无影响(只要多数节点存活) 不影响租户迁移,但需尽快恢复节点
网络分区 少数分区节点无法收到心跳,触发选举;多数分区保持服务 取决于分区恢复时间 避免跨 AZ 部署时网络抖动导致频繁选举
磁盘故障 节点无法写入 WAL,etcd 进程退出;集群自动剔除该节点 立即 需提前规划 etcd 数据盘监控与备份
最佳实践:生产环境 etcd 集群至少部署 3 个节点(奇数),分布在不同的可用区(AZ)。3 节点集群允许 1 个节点故障;5 节点集群允许 2 个节点故障。多租户场景下,建议使用 5 节点集群以容忍更多故障。

2.5 多租户场景下的高可用考量

在多租户集群中,etcd 的故障切换对租户迁移恢复有直接影响:

  • Leader 切换期间:kube-apiserver 无法写入 etcd,导致 Pod 创建、更新、删除等操作暂时失败。租户工作负载(已运行的 Pod)不受影响,但迁移操作(如 Pod 驱逐、重新调度)会阻塞。
  • Follower 故障:不影响写入,但读请求可能降级(如果开启 --enable-pprof 且读请求路由到 Follower)。租户迁移的读操作(如查询 Pod 状态)可能变慢。
  • 数据一致性:Raft 保证已提交的日志不会丢失。即使 Leader 切换,租户的配置数据(ConfigMap、Secret)也不会丢失。
迁移恢复策略:在 etcd 故障切换期间,应暂停主动的租户迁移操作,等待集群恢复稳定后再继续。建议在迁移脚本中增加 etcd 集群健康检查(etcdctl endpoint health)作为前置条件。
# 检查 etcd 集群健康状态
etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  endpoint health --cluster

# 输出示例(健康状态)
# https://10.0.1.1:2379 is healthy: successfully committed proposal: took = 2.345ms
# https://10.0.1.2:2379 is healthy: successfully committed proposal: took = 3.012ms
# https://10.0.1.3:2379 is healthy: successfully committed proposal: took = 1.987ms