1. etcd 概述:etcd 在 K8s 中的核心作用、Raft 一致性算法简介、etcd 数据模型与键值存储原理

1.1 etcd 在 Kubernetes 中的核心作用

etcd 是一个分布式、强一致性的键值存储系统,是 Kubernetes 集群的“大脑”与“状态仓库”。Kubernetes 将所有集群的配置数据、运行时状态、元数据全部存储在 etcd 中,任何对集群状态的变更都必须先写入 etcd,再由各组件通过 Watch 机制感知并执行。

核心定位:etcd 是 Kubernetes 集群中唯一的有状态数据存储层,其可用性与数据完整性直接决定集群的存亡。

etcd 在 K8s 中存储的关键数据包括:

数据类别 存储内容 示例 Key 路径
集群元数据 节点信息、命名空间、资源配额 /registry/nodes/
工作负载 Pod、Deployment、Service、ConfigMap、Secret /registry/pods/
访问控制 RBAC 规则、ServiceAccount、ClusterRole /registry/serviceaccounts/
网络与存储 NetworkPolicy、PV、PVC、StorageClass /registry/persistentvolumes/
集群事件 Events(默认保留 1 小时) /registry/events/

Kubernetes 控制面组件(kube-apiserver、kube-controller-manager、kube-scheduler)均通过 API Server 与 etcd 交互,架构关系如下:

Kubernetes 控制面与 etcd 交互架构 kube-apiserver etcd 集群 (3/5/7 节点) kube-controller-manager kube-scheduler 说明: 所有组件仅通过 API Server 读写 etcd;API Server 是 etcd 的唯一客户端。 Controller Manager 和 Scheduler 通过 API Server 的 Watch 机制感知状态变化。

1.2 Raft 一致性算法简介

etcd 使用 Raft 共识算法 来保证分布式环境下的数据一致性与高可用。Raft 将分布式一致性问题分解为三个子问题:领导者选举(Leader Election)、日志复制(Log Replication)、安全性(Safety)。

Raft 核心角色

角色 职责 状态转换条件
Leader(领导者) 处理所有客户端请求,向 Follower 复制日志 获得多数节点投票
Follower(跟随者) 被动接收 Leader 的日志复制和心跳 启动时默认状态;Leader 失联后转为 Candidate
Candidate(候选者) 发起选举,请求其他节点投票 选举超时后发起;获得多数票后转为 Leader

Raft 工作流程

  1. 领导者选举:Follower 在选举超时(150~300ms 随机)内未收到 Leader 心跳,转为 Candidate 并发起选举;获得超过半数(N/2+1)节点投票后成为新 Leader。
  2. 日志复制:Leader 接收客户端写请求,将操作封装为日志条目,并行发送 AppendEntries RPC 给所有 Follower;当多数节点确认写入后,该条目进入 committed 状态并应用到状态机。
  3. 安全性:Raft 保证只有拥有最新已提交日志的节点才能成为 Leader,且 Leader 不会覆盖已提交的日志条目。
关键指标:etcd 集群推荐奇数节点(3、5、7),容忍故障节点数为 (N-1)/2。3 节点集群最多容忍 1 个节点故障,5 节点集群最多容忍 2 个节点故障。
Raft 日志复制流程(3 节点集群) Leader Follower 1 Follower 2 客户端写请求 1. 写请求 2. AppendEntries 2. AppendEntries 3. 确认 3. 确认 日志复制关键步骤: 1. 客户端将写请求发送给 Leader。 2. Leader 将日志条目通过 AppendEntries RPC 并行发送给所有 Follower。 3. 当 Leader 收到多数(≥2/3)Follower 的确认后,该日志条目进入 committed 状态。 4. Leader 向客户端返回成功,并在下一次心跳中通知 Follower 提交该条目。

1.3 etcd 数据模型与键值存储原理

数据模型

etcd 采用 多版本并发控制(MVCC) 的键值存储模型,每个键对应多个历史版本。数据以 B+ 树 结构组织,支持高效的范围查询和前缀扫描。

概念 说明 示例
Key 字节数组,支持任意二进制数据,通常使用路径式命名 /registry/pods/default/nginx-xxx
Value 字节数组,存储序列化后的 Kubernetes 对象(Protobuf 或 JSON) {"apiVersion":"v1","kind":"Pod",...}
Revision 全局单调递增的版本号,每次写操作递增 123456
Lease 租约机制,用于键的自动过期(TTL) K8s Event 默认 1 小时过期
Watch 基于 Revision 的增量变更推送机制 API Server 监听 Pod 变化

键值存储原理

etcd 的存储引擎分为三层:

  1. API 层:处理 gRPC 请求,进行认证、鉴权、请求校验。
  2. Raft 层:保证日志复制与一致性,将写请求转化为 Raft 日志条目。
  3. 存储层(BoltDB):基于 BoltDB(现为 bbolt)的嵌入式数据库,以 B+ 树持久化键值数据。
运维注意:etcd 默认保留所有历史版本(compaction 前),历史版本过多会导致存储膨胀和性能下降。需定期执行 etcd compact 和 etcd defrag 来回收空间。
etcd 存储引擎分层架构 API 层(gRPC Server) Raft 一致性层 存储层(bbolt / B+ 树) 数据流向: 客户端写请求 → API 层(认证/鉴权)→ Raft 层(日志复制/共识)→ 存储层(B+ 树持久化)

MVCC 与版本管理

etcd 的 MVCC 机制通过 全局 Revision 实现:

  • 每次写操作(Put/Delete)都会生成一个新的 Revision,全局递增。
  • 每个键的多个版本按 Revision 排序存储,支持按版本读取历史数据。
  • Watch 机制基于 Revision 实现增量推送:客户端携带上次收到的 Revision,etcd 返回该 Revision 之后的所有变更。
关键命令示例:
# 写入键值
etcdctl put /registry/pods/default/nginx '{"kind":"Pod"}'

# 按版本读取
etcdctl get --rev=100 /registry/pods/default/nginx

# 压缩历史版本(保留最近 1000 个版本)
etcdctl compact 1000

# 碎片整理(回收磁盘空间)
etcdctl defrag