2. etcd 核心原理:Raft 共识算法、etcd 架构、数据存储模型、Watch 机制

etcd 是云原生架构中关键的一致性键值存储系统,也是 Kubernetes 控制平面的数据底座。理解 etcd 的核心原理,是制定灾备策略、排查 RPO 异常的前提。本章从 Raft 共识算法、系统架构、数据存储模型和 Watch 机制四个维度展开。

2.1 Raft 共识算法

Raft 是一种易于理解的一致性算法,通过 Leader 选举、日志复制 和 安全性 三个子问题保证集群在部分节点故障时仍能对外提供强一致服务。etcd 使用 Raft 作为其共识引擎。

核心概念: Raft 将时间划分为连续的 Term(任期),每个 Term 最多只有一个 Leader。所有写请求必须经过 Leader,Leader 将操作封装为 Log Entry 并复制到多数节点(Quorum)后提交。
Quorum 计算: 对于 N 节点集群,Quorum = ⌊N/2⌋ + 1。3 节点集群容忍 1 节点故障,5 节点集群容忍 2 节点故障。灾备场景下,Quorum 丢失将导致 etcd 完全不可用。
Raft 日志复制流程 Leader (Term 3) Follower 1 Follower 2 ① Client → Leader (Propose) → ② Leader 追加 Log Entry → ③ 并行复制到 Follower ④ 收到多数节点确认 → ⑤ Leader 提交 Entry → ⑥ 通知 Follower 提交 → ⑦ 返回 Client 故障节点 多数节点存活 → 集群仍可提交

2.2 etcd 架构

etcd 采用分层模块化设计,从上到下依次为:API 层、Raft 层、存储层 和 持久化层。各层职责清晰,协同工作。

层级 核心组件 职责说明
API 层 gRPC Server / HTTP Gateway 接收客户端请求,认证鉴权,协议转换
Raft 层 Raft Node / Transport Leader 选举、日志复制、成员变更
存储层 MVCC / Backend / KV Store 多版本并发控制、事务处理、索引维护
持久化层 WAL / Snapshot / BoltDB 预写日志、快照管理、数据落盘
灾备关注点: Raft 层依赖多数节点存活,持久化层依赖 WAL 完整性。备份时必须确保 WAL 和 Snapshot 的一致性,否则恢复后可能触发数据不一致或集群分裂。
etcd 分层架构 API 层:gRPC Server / HTTP Gateway 认证鉴权 · 请求路由 · 协议转换 Raft 层:共识引擎 Leader 选举 · 日志复制 · 成员变更 存储层:MVCC / Backend / KV Store 多版本并发控制 · 事务 · B+ 树索引 持久化层:WAL / Snapshot / BoltDB 预写日志 · 快照管理 · 数据落盘 写请求:API → Raft → 存储 → WAL 落盘 → 返回确认

2.3 数据存储模型

etcd 的数据存储模型基于 MVCC(多版本并发控制) 和 BoltDB(嵌入式 B+ 树数据库)。每个 Key 的每次修改都会生成一个新版本,旧版本数据在压缩(Compact)前保留。

关键数据结构:
  • KeyValue: 存储键值对及元数据(CreateRevision、ModRevision、Version、Lease)。
  • Revision: 全局单调递增的版本号,用于 MVCC 和 Watch 机制。
  • Event: 表示一次数据变更,包含 Type(PUT/DELETE)和 KeyValue。
字段 类型 说明
Key []byte 存储的键,支持前缀扫描
Value []byte 存储的值,最大 1.5 MiB
CreateRevision int64 Key 创建时的全局 Revision
ModRevision int64 Key 最后一次修改时的全局 Revision
Version int64 Key 被修改的次数(从 1 开始)
Lease int64 关联的租约 ID(用于 TTL 自动过期)
备份影响: 未压缩的历史版本会占用大量磁盘空间。灾备恢复时,如果备份包含大量旧版本,恢复后的 etcd 可能因数据量过大导致性能下降。建议在备份前执行 etcdctl compact 和 etcdctl defrag。
# 查看当前 Revision
etcdctl endpoint status --write-out=table

# 压缩所有历史版本到指定 Revision
etcdctl compact $(etcdctl endpoint status --write-out=json | jq -r '.[].Status.header.revision')

# 碎片整理(释放 BoltDB 空间)
etcdctl defrag

2.4 Watch 机制

Watch 是 etcd 实现事件驱动架构的核心能力。客户端可以监听一个 Key 或 Key 前缀,当数据发生变化时,etcd 通过 gRPC 流推送 Event 给客户端。Watch 机制基于 MVCC 的 Revision 实现。

Watch 工作流程:
  1. 客户端发起 Watch 请求,指定 Key 或前缀,以及起始 Revision。
  2. etcd 从 BoltDB 中读取 >= 起始 Revision 的历史事件,立即回放。
  3. etcd 在内存中维护 Watch 状态,监听后续写入操作。
  4. 当有新的 PUT/DELETE 操作提交时,etcd 生成 Event 并推送给所有匹配的 Watch 客户端。
Watch 类型 说明 典型场景
Key Watch 监听单个 Key 的变化 服务发现、配置更新
Prefix Watch 监听某个前缀下的所有 Key Kubernetes 资源监听(如 /registry/pods/)
WithProgressNotify 定期发送进度通知,防止连接超时 长时间 Watch 场景
灾备与 Watch 的关联: 备份恢复后,所有 Watch 连接会断开。客户端需要重新建立 Watch,并指定恢复时的最新 Revision,否则可能丢失恢复期间的数据变更。这是灾备演练中常见的 RPO 偏差来源。
# 使用 etcdctl 测试 Watch
# 终端 1:监听 /foo 前缀
etcdctl watch /foo --prefix

# 终端 2:写入数据
etcdctl put /foo/bar "hello"
etcdctl put /foo/baz "world"

# 终端 1 输出:
# PUT
# /foo/bar
# hello
# PUT
# /foo/baz
# world
Watch 事件推送流程 Client etcd Server BoltDB ① Watch(Key, Rev) ② 读取历史事件 ③ 新写入提交 ④ 推送 Event Watch 保证事件顺序:按 Revision 递增推送,不丢不重 恢复后需重新 Watch,指定最新 Revision 避免遗漏