存储版本
Kubernetes API 服务器在存储对象时,依赖于一个与 etcd 兼容的后端存储(通常就是 etcd 本身)。每个对象都使用该 API 类型的某个特定版本进行序列化,例如 ConfigMap 的 v1 表示形式。Kubernetes 使用术语存储版本(Storage Version) 来描述对象在你的集群 中是如何存储的。
官方文档参考
| 文档 | 语言 | 链接 |
|---|---|---|
| 存储版本(Storage Versions)概念页 | 中文 | https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/storage-version |
| Storage Versions 概念页(英文,用于补全迁移与静态加密细节) | 英文 | https://kubernetes.io/docs/concepts/overview/working-with-objects/storage-version/ |
关于链接路径的说明
存储版本中文页的实际路径为 /zh-cn/docs/concepts/overview/working-with-objects/storage-version(位于 working-with-objects 层级下,资源名为单数 storage-version);上表两个链接均为本次抓取验证可用的官方链接。
核心概念
- 自动转换:API 服务器负责转换每个 API 调用。例如你有一个 HorizontalPodAutoscaler,可以用其 API 的
v1和v2版本的任意组合与它交互,客户端看不到实际被序列化的版本。 - 与 API 版本无关:对象的(API)版本与存储版本完全独立。例如同一资源的
v1alpha1和v1beta1API 对象,只要两个对象之间存储版本没有被更新过,它们在存储中的编码就是相同的。 - 多存储版本:同一个 API 可能具有多个存储版本,API 服务器可以在所有已存储版本之间动态转换;但单个对象在任何时刻只能有一个存储版本。
- 为什么重要:存储版本把对象的 API 表示与存储后端中的实际二进制编码关联起来。当底层二进制编码变得重要时(例如静态加密、API 弃用),这个概念就非常关键。
存储版本与资源的映射
| 操作 | 存储版本的行为 |
|---|---|
| 写入(创建/更新) | 以当前活跃的存储版本存储对象 |
| 读取 | 把已存储的数据转换为对象的 API 表示 |
| 更新已有旧版本对象 | 写入时将对象转换为新的存储表示 |
| 一直不更新的旧对象 | 旧存储版本编码可以无限期存在 |
- 每个资源在任意时刻都只有一个活跃的存储版本,对对象的任何写入都会以该版本存储。
- 存储版本可以被更新,不同对象因而可以以不同版本存储;但单个对象在任何时刻只会以一种存储版本存储。
- 读操作不会改变对象的存储编码,只有写操作才会把对象迁移到新存储版本。
自定义资源的存储版本
自定义资源(CR)是动态定义的,其存储版本机制与内置类型不同:
- 内置对象的存储编码通常与 API 类型分开定义,已存储的对象充当"枢纽",具体资源版本只是对象模式中的一个字段;
- 对于自定义资源,必须将资源的某个版本设置为存储版本,该版本定义的模式(schema)会被用作资源在存储层的编码。
示例 CRD(crontabs):
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.example.com
spec:
group: example.com
# 该 CustomResourceDefinition 支持的版本列表
versions:
- name: v1beta1
served: true # served 表示该版本是否对外提供 API 服务
storage: true # 有且仅有一个版本必须标记为存储版本
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
- name: v1
served: true
storage: false # 非存储版本,仅提供 API 服务
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
time: # 注意:该字段不在存储版本 v1beta1 的 schema 中
type: string
conversion:
strategy: None
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
上例中 v1beta1 被用作存储版本:任何 crontabs 的创建或更新都会以 v1beta1 的对象模式存储。这意味着通过 v1 API 对象写入的 time 字段永远不会被存储,因为它不在存储版本的定义中。
不允许同时存在两个存储版本
把两个版本同时标记为存储版本是非法的——那意味着同时承认两种数据模式都是有效的存储方式。修改存储版本后,新创建或被更新的 CR 会立即使用新的存储版本;而读取/Watch 只是临时转换,不会改变已存储的编码。