2. Kubernetes 存储版本机制:理解 API 版本、存储版本、内部版本的概念与关系
在 Kubernetes 中,资源对象(如 Deployment、Pod、CustomResource)的版本管理并非单一维度。为了支持 API 演进、向后兼容以及数据持久化,Kubernetes 引入了三个核心版本概念:API 版本、存储版本 和 内部版本。理解这三者的关系,是掌握存储版本漂移检测的前提。
2.1 三个核心版本的定义与职责
| 版本类型 | 定义 | 主要职责 | 示例 |
|---|---|---|---|
| API 版本 | 用户与 kubectl、客户端库交互时使用的版本,定义在资源清单的 apiVersion 字段中。 |
提供外部接口,支持多个版本共存(如 v1、v1beta1、v1alpha1),允许用户逐步迁移。 | apps/v1、batch/v1beta1 |
| 存储版本 | 资源对象在 etcd 中持久化存储时使用的版本。每个资源只能有一个存储版本。 | 决定 etcd 中数据的实际序列化格式(JSON 或 Protobuf),是数据持久化的唯一标准。 | 集群中 apps/v1 被标记为存储版本 |
| 内部版本 | Kubernetes API Server 在内存中处理资源对象时使用的通用版本,通常命名为 __internal。 |
作为所有外部 API 版本与存储版本之间的“枢纽”,负责版本间的无损转换。 | __internal(不对外暴露) |
关键理解: 内部版本是 Kubernetes 内部的“通用语言”。所有外部 API 版本在写入 etcd 前,都会先转换为内部版本,再转换为存储版本;读取时则反向操作。这种设计确保了即使外部 API 版本发生变化,etcd 中的数据格式也能保持稳定。
2.2 三者的关系与数据流
下图展示了用户请求从提交到持久化,再到读取的完整数据流,清晰呈现了三个版本之间的协作关系。
2.3 存储版本的特殊性与漂移风险
存储版本是 etcd 中数据的“真实来源”,其特殊性体现在:
- 唯一性: 每个资源类型(GroupVersionResource)只能有一个存储版本,由 API Server 启动时通过
--storage-versions或代码注册决定。 - 持久性: 一旦数据写入 etcd,其版本格式就固定下来,除非显式迁移。
- 升级敏感性: 集群升级时,如果旧存储版本被废弃,API Server 会自动将存储版本迁移到新版本,但迁移过程可能失败或遗留旧数据。
存储版本漂移的典型场景:
- 集群升级: 从 v1.20 升级到 v1.25,某些资源的存储版本从 v1beta1 变为 v1,但 etcd 中仍残留 v1beta1 格式的数据。
- API 废弃: 旧 API 版本被移除后,存储版本指向新版本,但旧版本数据未完成迁移。
- 自定义资源(CRD): CRD 的存储版本被修改后,已存在的自定义资源对象可能无法被正确读取。
2.4 版本转换的代码示例
以下代码展示了 Kubernetes API Server 内部如何通过内部版本进行转换。这是理解存储版本漂移检测机制的基础。
// 伪代码:API Server 的版本转换流程
// 1. 用户提交一个 apps/v1 的 Deployment
deploymentV1 := &appsv1.Deployment{...}
// 2. 转换为内部版本(__internal)
internalDeployment := &appsapi.Deployment{}
scheme.Convert(deploymentV1, internalDeployment, nil)
// 3. 从内部版本转换为存储版本(假设存储版本是 apps/v1)
storageDeployment := &appsv1.Deployment{}
scheme.Convert(internalDeployment, storageDeployment, nil)
// 4. 序列化并写入 etcd
etcdClient.Put("/registry/deployments/default/my-deployment", storageDeployment)
// 5. 读取时反向操作
// 从 etcd 读取存储版本数据
// 转换为内部版本
// 再转换为用户请求的 API 版本
2.5 版本关系总结表
| 维度 | API 版本 | 内部版本 | 存储版本 |
|---|---|---|---|
| 可见性 | 用户可见 | 仅 API Server 内部 | 仅 etcd 和 API Server |
| 数量 | 多个(v1, v1beta1, v1alpha1) | 每个资源类型一个 | 每个资源类型一个 |
| 变更频率 | 随 API 演进频繁变更 | 几乎不变 | 随集群升级或配置变更 |
| 数据格式 | JSON / YAML | Go 结构体(内存) | JSON / Protobuf(etcd) |
| 漂移风险 | 低(用户可控) | 无(内部固定) | 高(检测重点) |
学习要点: 存储版本漂移检测的核心,就是对比 etcd 中实际存储的版本与 API Server 当前期望的存储版本是否一致。如果发现不一致,Webhook 可以触发告警或自动修复流程,防止集群因版本不匹配而出现故障。