2. etcd 基础:架构、Raft 核心概念与 K8s 数据模型
etcd 是 Kubernetes 控制平面的基石,一个高可用的分布式键值存储系统。它使用 Raft 共识算法 保证数据强一致性,并作为 K8s 所有集群状态(Pod、Service、ConfigMap 等)的唯一数据源。理解 etcd 是掌握 K8s 存储与故障恢复的前提。
2.1 etcd 整体架构
etcd 采用 Client-Server 架构,Server 端通过 Raft 协议组成集群。每个 etcd 节点包含以下核心组件:
- HTTP/ gRPC Server:处理客户端读写请求、集群成员变更、Leader 选举等。
- Raft 状态机:实现 Raft 共识算法,负责日志复制、选举和持久化。
- WAL (Write-Ahead Log):顺序写入磁盘,记录所有状态变更,用于故障恢复。
- Snapshot:当 WAL 过大时,生成快照压缩日志,加速重启恢复。
- MVCC (Multi-Version Concurrency Control):支持并发读写,保留历史版本,用于 Watch 机制和事务。
- Backend (BoltDB):底层持久化存储引擎,以 B+ 树组织数据。
架构要点: 所有写请求必须由 Leader 处理,Follower 将请求转发给 Leader。读请求可由任意节点处理(默认线性一致性读需 Leader 确认)。
2.2 Raft 协议核心概念
Raft 是一种易于理解的分布式共识算法,etcd 使用它来保证集群中所有节点数据一致。Raft 将节点分为三种角色:
| 角色 | 职责 | 关键行为 |
|---|---|---|
| Leader | 处理所有写请求,管理日志复制 | 定期发送心跳(Heartbeat)给 Follower;负责日志提交 |
| Follower | 被动接收 Leader 的日志和心跳 | 如果超时未收到心跳,转换为 Candidate 发起选举 |
| Candidate | 选举过程中的临时角色 | 向其他节点请求投票,获得多数票后成为 Leader |
2.3 Raft 选举与日志复制流程
- Leader 选举:Follower 在选举超时(150-300ms 随机)后变为 Candidate,发起投票。获得超过半数(N/2+1)节点投票的 Candidate 成为新 Leader。
- 日志复制:Leader 接收客户端写请求,将日志条目追加到本地 WAL,然后并行发送 AppendEntries RPC 给所有 Follower。
- 日志提交:当 Leader 收到多数 Follower 的确认后,将日志条目标记为已提交(Committed),并应用到状态机,最后响应客户端。
- 安全性:Raft 保证只有拥有最新日志的节点才能成为 Leader,防止已提交数据被覆盖。
SRE 视角: etcd 集群通常部署 3 或 5 节点。3 节点集群容忍 1 节点故障,5 节点集群容忍 2 节点故障。选举超时和心跳间隔直接影响故障恢复速度。
2.4 etcd 在 Kubernetes 中的角色
Kubernetes 将 etcd 作为 控制平面的核心数据存储,所有 API 对象都持久化在 etcd 中。具体角色如下:
- 状态持久化:集群的期望状态(Spec)和当前状态(Status)都存储在 etcd 中。
- Watch 机制:API Server 通过 etcd 的 Watch 功能监听资源变化,驱动控制器(Controller)工作。
- 集群一致性:多个 API Server 实例通过 etcd 共享数据,保证集群状态一致。
- 故障恢复:etcd 的快照和 WAL 是灾难恢复的关键,定期备份 etcd 是 SRE 的必修课。
2.5 etcd 数据模型与 K8s 存储结构
etcd 内部使用 扁平的键值对 存储数据,但 Kubernetes 通过 前缀机制 构建了层次化的命名空间。K8s 所有资源都存储在 /registry 前缀下:
| etcd 键路径 | 对应 K8s 资源 | 示例 |
|---|---|---|
/registry/pods/<namespace>/<name> |
Pod | /registry/pods/default/nginx-pod |
/registry/services/<namespace>/<name> |
Service | /registry/services/kube-system/kube-dns |
/registry/configmaps/<namespace>/<name> |
ConfigMap | /registry/configmaps/default/app-config |
/registry/secrets/<namespace>/<name> |
Secret | /registry/secrets/default/tls-secret |
/registry/nodes/<name> |
Node | /registry/nodes/worker-1 |
/registry/clusterroles/<name> |
ClusterRole | /registry/clusterroles/admin |
SRE 警告: 不要直接使用
etcdctl 修改 K8s 数据,除非在灾难恢复场景。直接操作 etcd 可能导致集群状态不一致,引发不可预知的问题。始终通过 API Server 操作资源。
2.6 关键数据模型特性
- MVCC 版本控制:每个键值对都有
revision(全局版本号)和create_revision/mod_revision。Watch 基于 revision 实现增量变更推送。 - Lease 机制:etcd 支持租约(Lease),用于实现键的 TTL 自动过期。K8s 使用 Lease 实现 Node 心跳和 Leader 选举。
- 事务支持:etcd 提供 比较-交换(CAS) 事务,K8s 利用它实现乐观锁(resourceVersion 冲突检测)。
- Watch 流:客户端可以监听某个前缀或键的变化,K8s 的 Informer 机制正是基于此实现。
压测关注点: etcd 性能瓶颈通常出现在 写请求量 和 Watch 连接数。K8s 集群中大量 Pod 频繁更新 Status 或频繁创建/删除资源,会直接冲击 etcd 的写入吞吐和 WAL 写入延迟。