3. K8s 存储模型:API Server 与 etcd 的交互、资源对象的序列化与存储、存储版本管理

Kubernetes 的存储模型是理解集群数据一致性与安全性的基石。所有集群状态——从 Pod 定义到 Secret 内容——最终都持久化在 etcd 中。本章深入剖析 API Server 与 etcd 的交互机制、资源对象的序列化与存储路径,以及存储版本管理策略,为后续理解 etcd 准入策略如何拦截高风险变更奠定基础。

3.1 API Server 与 etcd 的交互架构

API Server 是 Kubernetes 控制面的唯一入口,也是 etcd 的唯一客户端。所有对集群状态的读写操作都必须经过 API Server 的认证、授权、准入控制与验证逻辑后,才会转换为对 etcd 的 gRPC 请求。

核心交互原则: API Server 不直接暴露 etcd 端口,所有 etcd 操作均通过封装的存储接口(Generic API Server 的 StorageBackend)完成,确保数据访问的可审计性与一致性。
API Server 与 etcd 交互架构 API Server 认证 → 授权 → 准入 → 验证 存储接口 (StorageBackend) etcd 集群 Key-Value 存储 Raft 一致性协议 gRPC (TLS) 存储路径分解 /registry/ 资源类型 命名空间 资源名称 示例:/registry/pods/default/my-nginx
安全提示: 生产环境中,etcd 应启用 TLS 双向认证,API Server 通过客户端证书与 etcd 建立连接。任何直接访问 etcd 端口的操作都应被审计和限制。

3.2 资源对象的序列化与存储

Kubernetes 资源对象在 API Server 内部以 Go 结构体表示,但在 etcd 中存储为序列化后的字节流。序列化过程涉及版本选择、编码格式转换与元数据注入。

3.2.1 序列化流程

  1. 内部版本转换: 用户提交的 API 版本(如 v1)被转换为 API Server 的内部版本(__internal),完成默认值注入与校验。
  2. 存储版本选择: 根据资源注册的存储版本(如 apps/v1),将内部版本转换为目标存储版本。
  3. 编码: 使用 protobuf(默认)或 json 格式序列化为字节数组。
  4. 元数据注入: 添加 Key、ResourceVersion、Revision 等存储元数据。
  5. 写入 etcd: 通过 gRPC Put 请求将序列化后的数据写入对应 Key。

3.2.2 存储格式对比

特性 Protobuf(默认) JSON(兼容)
序列化速度 快(二进制编码) 慢(文本解析)
存储空间 小(约 JSON 的 60%) 大(含冗余字段名)
可读性 不可直接读取 人类可读
版本兼容性 强(Schema 定义) 弱(字段名变更风险)
etcd 存储格式 application/vnd.kubernetes.protobuf application/json
运维注意: 直接使用 etcdctl get 查看存储内容时,Protobuf 编码的数据会显示为乱码。如需调试,应使用 kubectl get --raw 或通过 API Server 的转换接口查看可读版本。

3.3 存储版本管理

Kubernetes 通过存储版本(Storage Version)机制管理资源对象在 etcd 中的持久化格式。存储版本决定了数据在磁盘上的编码方式,并影响集群升级、回滚与数据迁移策略。

3.3.1 存储版本与 API 版本的关系

  • API 版本: 用户与 API Server 交互时使用的版本(如 v1、v1beta1),支持多个版本共存。
  • 存储版本: 资源对象在 etcd 中持久化时使用的版本,每个资源类型只能有一个存储版本。
  • 内部版本: API Server 内部统一使用的版本,用于跨版本转换与校验。

3.3.2 存储版本迁移

当集群升级时,存储版本可能发生变化。例如,从 Kubernetes 1.21 升级到 1.22 时,apps/v1beta1 被移除,存储版本自动迁移到 apps/v1。迁移过程由 API Server 的存储版本迁移控制器自动完成。

# 查看当前资源类型的存储版本
kubectl get --raw /openapi/v2 | jq '.paths | keys' | grep -E "apps/v1"

# 手动触发存储版本迁移(Kubernetes 1.24+)
kubectl apply -f - <<EOF
apiVersion: apiserverinternal.k8s.io/v1alpha1
kind: StorageVersionMigration
metadata:
  name: pods-migration
spec:
  resource:
    group: ""
    version: v1
    resource: pods
EOF

3.3.3 存储版本管理的关键操作

操作 触发条件 影响范围 风险等级
存储版本自动迁移 API Server 启动时检测到废弃版本 全集群该资源类型 中
手动存储版本迁移 管理员执行 StorageVersionMigration 指定资源类型 高
存储版本回滚 集群降级或数据恢复 全集群该资源类型 极高
存储版本锁定 通过 Feature Gate 控制 全局 低
安全关联: 存储版本迁移过程中,etcd 中的数据会被重新序列化并写入新 Key。如果迁移期间发生写入冲突或版本不匹配,可能导致数据损坏。etcd 准入策略可以在迁移前校验数据完整性,拦截格式异常的对象。

3.4 存储模型安全要点

  • 数据完整性: API Server 在写入 etcd 前会计算对象的 ResourceVersion,用于乐观锁控制,防止并发写入覆盖。
  • 审计日志: 所有对 etcd 的写操作都会记录在 API Server 审计日志中,包括请求来源、操作类型与修改内容。
  • 加密存储: 敏感资源(如 Secret)可通过 EncryptionConfiguration 在写入 etcd 前进行加密,密钥由 KMS 管理。
  • 存储版本一致性: 集群中所有 API Server 实例必须使用相同的存储版本配置,否则可能导致数据读取失败或版本转换错误。
最佳实践: 在集群升级前,使用 kubectl get --raw /openapi/v2 检查当前存储版本,确保目标版本支持所有已存储的资源对象。对于高风险变更(如存储版本迁移),建议先在测试集群验证,并启用 etcd 快照备份。