3、K8s与etcd的关系:API Server如何与etcd交互、K8s资源对象在etcd中的存储结构、集群状态持久化原理
3.1 核心交互链路:API Server ↔ etcd
Kubernetes 集群中,只有 kube-apiserver(API Server) 具备直接读写 etcd 的权限。其他组件(kubelet、scheduler、controller-manager、kubectl)均通过 API Server 的 RESTful 接口间接操作集群数据。这种架构设计保证了数据访问的一致性与安全性。
API Server 与 etcd 的交互采用 Watch + List + Apply 模式:
- List:客户端首次连接或重新同步时,API Server 向 etcd 发起全量 List 请求,获取某类资源的所有对象。
- Watch:API Server 在 etcd 上建立长连接 Watch,监听资源变更事件(Create/Update/Delete)。
- Apply:当用户提交资源变更时,API Server 将对象序列化为 JSON/Protobuf 后写入 etcd,并返回响应。
以下交互流程图展示了 API Server 作为中间层的完整数据流转:
3.2 K8s 资源对象在 etcd 中的存储结构
etcd 是一个分布式键值存储,Kubernetes 将所有资源对象以 层级 Key-Value 的形式组织在 etcd 中。存储路径遵循固定的命名空间结构:
| etcd Key 前缀 | 对应 K8s 资源 | 说明 |
|---|---|---|
/registry/pods/<namespace>/<name> |
Pod | 每个 Pod 对应一个独立 Key |
/registry/deployments/<namespace>/<name> |
Deployment | 包含 ReplicaSet 模板等嵌套数据 |
/registry/services/<namespace>/<name> |
Service | ClusterIP、端口映射等 |
/registry/configmaps/<namespace>/<name> |
ConfigMap | 键值对配置数据 |
/registry/secrets/<namespace>/<name> |
Secret | Base64 编码的敏感数据 |
/registry/nodes/<name> |
Node | 集群级别资源,无 namespace |
/registry/clusterroles/<name> |
ClusterRole | 集群级别 RBAC 资源 |
/registry/events/<namespace>/<uid> |
Event | 事件记录,TTL 过期后自动清理 |
每个 Key 对应的 Value 是资源对象的 完整序列化表示,默认使用 Protobuf(二进制)格式,也可通过 API Server 配置切换为 JSON。Value 中包含资源的完整元数据(metadata)、规格(spec)和状态(status)。
- etcd 中不存储“集群”概念,所有资源通过 Key 前缀区分类型。
- 相同类型的资源按 namespace 分组,集群级别资源(Node、ClusterRole)直接放在类型前缀下。
- 每个资源对象在 etcd 中是一个独立的 Key,不存在“表”或“集合”的概念。
- etcd 的 Key 空间是扁平的,Kubernetes 通过前缀模拟出层级结构。
以下结构图展示了 K8s 资源在 etcd 中的存储层次:
3.3 集群状态持久化原理
Kubernetes 集群的“状态”由 etcd 中存储的所有资源对象共同定义。持久化机制围绕以下三个核心设计展开:
3.3.1 全量快照 + 增量日志
etcd 内部使用 WAL(Write-Ahead Log) 记录所有写操作,并定期生成 快照(Snapshot)。快照是某一时刻 etcd 数据的完整副本,WAL 则记录快照之后的所有增量变更。恢复时,先加载快照,再回放 WAL 日志,即可还原到最新状态。
3.3.2 资源版本号(resourceVersion)
每个资源对象在 etcd 中都有一个全局递增的 resourceVersion。该版本号用于:
- 乐观并发控制:更新操作携带 resourceVersion,etcd 比较版本号,若已被修改则拒绝写入,避免冲突。
- Watch 断点续传:客户端断开后,使用上次收到的 resourceVersion 重新发起 Watch,etcd 从该版本号之后的事件开始推送。
3.3.3 事件驱动状态同步
API Server 通过 etcd 的 Watch 机制监听资源变更,并将事件分发给集群内其他组件。组件根据事件更新本地缓存或触发相应操作(如调度器收到 Pod 创建事件后尝试调度)。
以下表格总结了 API Server 与 etcd 交互中的关键概念:
| 概念 | 作用 | 与 etcd 的关系 |
|---|---|---|
| resourceVersion | 全局递增版本号,用于并发控制和 Watch 断点 | etcd 的 mod_revision 直接映射为 resourceVersion |
| Watch | 长连接监听资源变更事件 | API Server 通过 etcd v3 Watch API 实现 |
| List | 全量获取某类资源 | API Server 对 etcd 执行范围查询(Range Request) |
| 乐观锁 | 防止并发写冲突 | etcd 比较 resourceVersion,不一致则返回失败 |
| TTL / Lease | 自动清理过期资源(如 Event、Lease) | etcd 的 Lease 机制实现自动过期删除 |
3.4 实践:查看 etcd 中的 K8s 数据
运维人员可以通过 etcdctl 工具直接查看 etcd 中存储的 K8s 资源数据,用于故障排查或数据验证:
# 列出所有 Pod 的 Key(需指定 etcd 端点与证书)
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/pods/ --prefix --keys-only
# 获取某个 Pod 的完整数据(JSON 格式)
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/pods/default/nginx-pod-7f8b9c --print-value-only | jq .