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 的唯一客户端代理,所有状态变更必须经过 API Server 的认证、授权、准入控制和验证。

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 作为中间层的完整数据流转:

API Server 与 etcd 交互流程 kubectl / 客户端 kubelet / scheduler kube-apiserver 认证 → 授权 → 准入 → 验证 etcd 键值存储 / Raft REST (JSON/PB) gRPC / v3 API Watch 事件推送 交互要点说明: 1. 所有组件通过 API Server 的 REST API 操作资源,不直接访问 etcd。 2. API Server 内部经过认证、授权、准入控制(Admission Controller)后, 将资源对象序列化为 JSON 或 Protobuf 格式写入 etcd。 3. etcd 通过 Watch 机制将变更事件推送给 API Server,进而通知其他组件。 4. 数据一致性由 etcd 的 Raft 共识算法保证,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 中的存储层次:

K8s 资源对象在 etcd 中的存储结构 /registry /pods/ /deployments/ /services/ /configmaps/ default/ kube-system/ default/ kube-system/ nginx-pod-xxx coredns kubernetes kube-proxy Key 结构: /registry/<资源类型>/<namespace>/<资源名称> → Value: 完整资源对象(Protobuf/JSON)

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 创建事件后尝试调度)。

重要:etcd 的持久化是集群数据安全的最后一道防线。如果 etcd 数据损坏或丢失,且没有有效备份,整个集群将无法恢复。因此,etcd 的定期备份是 K8s 运维中不可跳过的关键步骤。

以下表格总结了 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 .
注意:直接操作 etcd 属于高危操作,建议仅在集群故障或数据恢复场景下使用。日常运维应通过 kubectl 和 API Server 进行。