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)完成,确保数据访问的可审计性与一致性。
安全提示: 生产环境中,etcd 应启用 TLS 双向认证,API Server 通过客户端证书与 etcd 建立连接。任何直接访问 etcd 端口的操作都应被审计和限制。
3.2 资源对象的序列化与存储
Kubernetes 资源对象在 API Server 内部以 Go 结构体表示,但在 etcd 中存储为序列化后的字节流。序列化过程涉及版本选择、编码格式转换与元数据注入。
3.2.1 序列化流程
- 内部版本转换: 用户提交的 API 版本(如
v1)被转换为 API Server 的内部版本(__internal),完成默认值注入与校验。 - 存储版本选择: 根据资源注册的存储版本(如
apps/v1),将内部版本转换为目标存储版本。 - 编码: 使用
protobuf(默认)或json格式序列化为字节数组。 - 元数据注入: 添加
Key、ResourceVersion、Revision等存储元数据。 - 写入 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 快照备份。