2. etcd 架构速览:Raft 共识算法、MVCC 存储、Watch 机制、Lease 机制

etcd 是 Kubernetes 控制平面的唯一状态存储,其架构设计直接决定了集群的可靠性、一致性与响应性能。在生产排障中,理解 etcd 的四大核心机制——Raft 共识算法、MVCC 存储、Watch 机制、Lease 机制——是定位发布流水线异常的关键前提。本节从架构视角速览这四大组件,为后续日志关联与根因分析打下基础。

2.1 整体架构分层

etcd 内部可划分为三层:

  • 网络层:基于 gRPC 的客户端-服务器通信与节点间 Raft 消息传递。
  • 共识层:Raft 算法实现,负责日志复制、领导者选举与集群成员变更。
  • 存储层:基于 BoltDB(底层 B+ 树)的 MVCC 键值存储,配合 Watch 与 Lease 提供分布式协调原语。
排障提示: 发布流水线异常时,首先判断故障发生在哪一层——网络层超时、共识层分裂、还是存储层写入延迟?分层定位能大幅缩小根因范围。
etcd 三层架构与核心机制 网络层(gRPC) 客户端请求 / 节点间 Raft 消息 / 心跳与选举 共识层(Raft 算法) 领导者选举 · 日志复制 · 安全性保证 核心:多数派写入(N/2+1) 存储层(MVCC + BoltDB) MVCC 存储 多版本 · 快照隔离 Watch 机制 事件推送 · 增量感知 Lease 机制 心跳保活 · 超时淘汰 BoltDB B+ 树持久化

2.2 Raft 共识算法

Raft 是 etcd 保证强一致性的核心。它将共识问题分解为三个子问题:领导者选举、日志复制、安全性。

子问题 核心机制 异常场景(发布流水线相关)
领导者选举 基于随机超时(150~300ms)的选举触发;获得多数票的节点成为 Leader 网络分区导致频繁选举 → 写入延迟飙升 → 发布超时
日志复制 Leader 将日志条目并行复制到 Follower;多数派确认后提交 磁盘 I/O 抖动导致 Follower 追加慢 → 提交延迟 → 发布卡顿
安全性 只有拥有最新已提交日志的节点才能当选 Leader;日志条目一旦提交永不丢失 旧 Leader 恢复后尝试覆盖新日志 → 日志冲突 → 集群拒绝服务
关键指标: 发布流水线异常时,优先检查 etcd_server_leader_changes_seen_total 和 etcd_disk_wal_fsync_duration_seconds。Leader 频繁切换是 Raft 层故障的典型信号。

2.3 MVCC 存储

etcd 采用多版本并发控制(MVCC)实现快照隔离。每次写操作不覆盖旧值,而是生成一个新版本号(revision)。

  • 键值存储:每个键维护一个版本链,读操作可指定版本号读取历史数据。
  • 压缩(Compaction):定期回收旧版本,防止存储无限增长。压缩后历史版本不可读。
  • 事务支持:基于 revision 的比较-交换(CAS)操作,实现乐观锁。
# 查看当前集群的 revision 状态
etcdctl endpoint status --write-out=table

# 手动压缩到指定 revision(生产慎用)
etcdctl compact 123456
排障陷阱: 发布流水线中如果出现 "mvcc: database space exceeded" 错误,说明 etcd 存储空间耗尽。此时需要立即执行碎片整理(defrag)或调整自动压缩参数,否则集群将进入只读模式。

2.4 Watch 机制

Watch 是 etcd 实现事件驱动架构的核心。客户端可以监听某个键或某个前缀,当键值发生变化时,etcd 通过 gRPC 流实时推送事件。

Watch 类型 行为 K8s 使用场景
单键 Watch 监听单个键的 Put/Delete 事件 监听特定 ConfigMap 变更
前缀 Watch 监听某个前缀下的所有键变更 监听 /registry/pods/ 下所有 Pod 变化
创建式 Watch(Create) 仅监听键被创建的事件 监听新 Service 注册
排障要点: 当发布流水线出现 "too many watchers" 或 watch 响应延迟时,检查 etcd_debugging_mvcc_watcher_total 指标。大量无效或重复的 watch 会消耗 etcd 内存与 CPU,导致关键事件推送延迟。

2.5 Lease 机制

Lease(租约)是 etcd 提供的分布式心跳与超时淘汰机制。Kubernetes 大量使用 Lease 实现节点心跳、Leader 选举和临时状态管理。

  • 创建 Lease:指定 TTL(生存时间),etcd 保证在 TTL 内 Lease 有效。
  • 续约(KeepAlive):客户端定期发送心跳刷新 Lease,防止过期。
  • 绑定键值:将键与 Lease 关联,Lease 过期时自动删除关联键。
# 创建一个 TTL=60s 的 Lease
etcdctl lease grant 60

# 将 key 绑定到 Lease
etcdctl put --lease=694d6e6e6e6e6e6e /mykey myvalue

# 手动续约
etcdctl lease keep-alive 694d6e6e6e6e6e6e
发布流水线异常案例: 当 K8s 节点心跳 Lease 过期(通常 TTL=40s),kube-controller-manager 会标记节点为 NotReady,导致 Pod 被驱逐。排查时检查 etcd_lease_ttl_seconds 与 etcd_lease_expired_total 指标,确认是否存在 Lease 续约失败。
Lease 生命周期与 Watch 事件流 K8s 组件 kubelet / controller etcd 集群 Lease 管理 Watch 推送 观察者 scheduler / controller ① 创建 Lease (TTL=40s) ② 定期续约 (KeepAlive) ③ 绑定键值 (关联 Lease) ④ Watch 事件推送 Lease 过期 TTL 耗尽 / 续约失败 自动删除关联键 触发 Delete Watch 事件 ⑤ 通知观察者

2.6 四大机制协同关系

在发布流水线场景中,四大机制并非孤立运行,而是紧密协作:

  1. Raft 保证所有节点上的 MVCC 写入日志一致。
  2. MVCC 为每个写入生成唯一 revision,Watch 基于 revision 实现增量推送。
  3. Watch 将键值变更实时推送给 K8s 控制器,驱动发布流程状态转换。
  4. Lease 管理临时资源生命周期,过期时触发 Watch 删除事件,实现自动清理。
根因定位口诀: 写入看 Raft(日志复制延迟),读取看 MVCC(压缩与空间),事件看 Watch(推送积压),存活看 Lease(续约超时)。四者交叉验证,即可锁定发布异常根因。