2. etcd 架构与数据模型:Raft 共识算法、MVCC、键值存储、Watch 机制、租约
etcd 是一个高可用的分布式键值存储系统,其核心架构围绕 Raft 共识算法、MVCC(多版本并发控制)、键值存储引擎、Watch 机制 和 租约(Lease) 五大支柱构建。理解这些组件是掌握 etcd 准入策略与安全门禁的基础。
2.1 整体架构分层
etcd 的架构自底向上分为三层:
- 网络层:基于 gRPC 的 HTTP/2 通信,处理客户端请求与节点间 Raft 消息。
- 共识层(Raft):保证集群数据一致性与高可用,是分布式安全的基石。
- 存储层:包含 MVCC 键值存储、Watch 索引、租约管理,直接响应读写请求。
2.2 Raft 共识算法
Raft 是 etcd 分布式一致性的核心,通过 Leader 选举 和 日志复制 确保集群中所有节点数据最终一致。etcd 的准入策略必须与 Raft 的提交阶段协同工作。
| Raft 角色 | 职责 | 安全影响 |
|---|---|---|
| Leader | 处理所有客户端写入,管理日志复制 | 准入策略在 Leader 端执行,拒绝的请求不会进入 Raft 日志 |
| Follower | 被动复制日志,处理只读请求 | Follower 可配置线性化读,需向 Leader 确认提交索引 |
| Candidate | 选举阶段临时角色 | 选举期间集群不可写入,准入策略暂停执行 |
安全提示: 准入策略在 Raft 日志提交前执行。如果策略拒绝写入,该请求不会进入 Raft 日志,从而避免无效日志复制,降低集群负载。
2.3 MVCC 与键值存储
etcd 使用 MVCC(多版本并发控制) 管理键值对。每次写入生成一个新版本,旧版本保留一段时间用于历史查询和 Watch 事件回溯。
- Key-Value 存储:底层基于 BoltDB(现为 bbolt),键值对以
/namespace/key形式组织。 - 版本号(revision):全局单调递增的整数,标识每次写入操作。
- MVCC 工作流程:
- 客户端发起 Put 请求。
- etcd 分配新的全局 revision。
- 写入 BoltDB,同时更新内存中的 B-tree 索引。
- 触发关联的 Watch 事件。
2.4 Watch 机制
Watch 是 etcd 的核心观察者模式,客户端可以监听特定键或前缀的变化。Watch 事件基于 MVCC 版本号触发,保证事件不丢失、不重复。
| Watch 类型 | 触发条件 | 典型场景 |
|---|---|---|
| Key Watch | 单个键的 Put / Delete | 监听 Pod 状态变化 |
| Prefix Watch | 匹配前缀的所有键变化 | 监听 Namespace 下所有资源 |
| Revision Watch | 从指定 revision 开始的历史事件 | 断线重连后的事件回溯 |
安全风险: 大量 Watch 连接会消耗 etcd 内存。恶意客户端可创建大量 Watch 导致 OOM。准入策略应限制每个客户端的 Watch 数量。
2.5 租约(Lease)
租约是 etcd 实现 TTL(生存时间) 和 节点心跳 的机制。每个租约有一个过期时间,关联的键在租约过期后自动删除。
- 租约创建:客户端通过
LeaseGrant创建租约,指定 TTL。 - 租约续期:客户端定期发送
LeaseKeepAlive保持租约活跃。 - 键关联:Put 操作可指定租约 ID,键的生命周期与租约绑定。
- 租约过期:租约到期后,所有关联键被自动删除,触发 Delete Watch 事件。
Kubernetes 场景: Node 心跳使用租约实现。每个 Node 创建一个租约,定期续期。如果 Node 失联,租约过期,K8s 标记 Node 为 NotReady。准入策略可监控租约过期频率,识别异常节点。
2.6 数据模型总结
下表对比了 etcd 核心组件在安全门禁中的关注点:
| 组件 | 安全关注点 | 准入策略切入点 |
|---|---|---|
| Raft | 日志复制一致性,防止分裂脑 | 在日志提交前拦截非法写入 |
| MVCC | 版本爆炸导致存储膨胀 | 限制单个 key 的版本数量 |
| Watch | 连接数过多导致内存泄漏 | 限制每个客户端的 Watch 数量 |
| 租约 | 租约过期导致数据意外删除 | 验证租约 TTL 是否在合理范围 |