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。
2.2 etcd 集群节点角色
etcd 集群中的每个节点在任意时刻都处于以下三种角色之一:
| 角色 | 职责 | 状态特征 | 故障影响 |
|---|---|---|---|
| Leader | 处理所有客户端写请求;管理日志复制;定期发送心跳 | 唯一;拥有最新日志;处理读写 | Leader 故障触发重新选举 |
| Follower | 被动接收 Leader 的日志复制;响应 Leader 心跳;处理只读请求(可配置) | 多数节点处于此状态;被动同步 | Follower 故障不影响写入,但降低读可用性 |
| Candidate | Leader 选举期间的临时角色;向其他节点发起投票请求 | 选举超时后进入;任期递增 | 选举期间集群短暂不可用(通常毫秒级) |
关键约束:一个 Term 内最多只能有一个 Leader。如果两个节点同时成为 Candidate 且票数相同,则进入“split vote”状态,需要等待超时后重新选举。
2.3 Leader 选举机制
Leader 选举是 Raft 协议的核心,也是 etcd 高可用的关键保障。选举过程遵循以下步骤:
- 心跳超时触发:Follower 在选举超时时间(election timeout,默认 1000ms)内未收到 Leader 心跳,认为 Leader 已宕机。
- 转为 Candidate:Follower 增加当前 Term,转换为 Candidate,并向自己投票。
- 发起投票请求:Candidate 向集群中所有其他节点发送 RequestVote RPC,包含自己的 Term 和最新日志索引。
- 投票规则:每个节点在一个 Term 内只能投一票;只有日志至少与 Candidate 一样新的节点才会投票。
- 赢得选举:Candidate 获得超过半数(N/2 + 1)的投票后成为 Leader。
- 心跳宣告:新 Leader 立即发送心跳(AppendEntries RPC)给所有节点,重置选举超时计时器。
选举超时时间:etcd 默认 election-timeout 为 1000ms,实际值在 1000ms ~ 2000ms 之间随机化,防止多个 Follower 同时超时导致 split vote。
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