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 完全不可用。
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 的一致性,否则恢复后可能触发数据不一致或集群分裂。
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 工作流程:
- 客户端发起 Watch 请求,指定 Key 或前缀,以及起始 Revision。
- etcd 从 BoltDB 中读取 >= 起始 Revision 的历史事件,立即回放。
- etcd 在内存中维护 Watch 状态,监听后续写入操作。
- 当有新的 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