To use this feature, you (or a cluster administrator) will need to enable the StorageVersionMigrator feature gate for all relevant components in your cluster.
See Enable Or Disable Feature Gates for more information.
Kubernetes 依赖主动重写的 API 数据来支持与静态存储相关的一些维护活动。 两个著名的例子是已存储资源的版本化模式(即针对给定资源的首选存储模式从 v1 更改为 v2) 和静态加密(即基于数据加密方式的变化来重写过时的数据)。
运行存储版本迁移可以确保某个 Resource 的所有对象都已从过期的存储版本完成迁移。 执行存储迁移的要求是确保此 Resource 具有整数的资源版本号。 所有 Kubernetes 内置 Resource 以及 CRD 都需确保满足这一要求; 但如果不满足,迁移将会失败,例如使用聚合 API 的情况。
安装 kubectl。
你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与你的集群通信。 建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:
你的 Kubernetes 服务器版本必须不低于版本 v1.30.要获知版本信息,请输入 kubectl version.
确保你的集群启用了 StorageVersionMigrator
特性门控。
你需要有控制平面管理员权限才能执行此项变更。
在 API 服务器上将运行时配置 storagemigration.k8s.io/v1beta1 设为 true,启用存储版本迁移 REST API。
有关如何执行此操作的更多信息,请阅读启用或禁用 Kubernetes API。
首先配置 KMS 驱动, 以便使用如下加密配置来加密 etcd 中的静态数据。
kind: EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
确保通过将 --encryption-provider-config-automatic-reload 设置为 true,允许自动重新加载加密配置文件。
使用 kubectl 创建 Secret。
kubectl create secret generic my-secret --from-literal=key1=supersecret
验证该
Secret 对象的序列化数据带有前缀 k8s:enc:aescbc:v1:key1。
按照以下方式更新加密配置文件,以轮换加密密钥。
kind: EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key2
secret: c2VjcmV0IGlzIHNlY3VyZSwgaXMgaXQ/
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
要确保之前创建的 Secret my-secret 使用新密钥 key2 进行重新加密,你将使用存储版本迁移。
创建以下名为 migrate-secret.yaml 的 StorageVersionMigration 清单:
kind: StorageVersionMigration
apiVersion: storagemigration.k8s.io/v1beta1
metadata:
name: secrets-migration
spec:
resource:
group: ""
resource: secrets
使用以下 kubectl 命令创建对象:
kubectl apply -f migrate-secret.yaml
通过检查 StorageVersionMigration 的 .status 来监控 Secret 的迁移。
成功的迁移应将其 Succeeded 状况设置为 true。
获取 StorageVersionMigration 对象的方式如下:
kubectl wait --for=condition=Succeeded storageversionmigration.storagemigration.k8s.io/secrets-migration
输出类似于:
kind: StorageVersionMigration
apiVersion: storagemigration.k8s.io/v1beta1
metadata:
name: secrets-migration
uid: 628f6922-a9cb-4514-b076-12d3c178967c
resourceVersion: "90"
creationTimestamp: "2024-03-12T20:29:45Z"
spec:
resource:
group: ""
resource: secrets
status:
conditions:
- type: Running
status: "False"
lastUpdateTime: "2024-03-12T20:29:46Z"
reason: StorageVersionMigrationInProgress
- type: Succeeded
status: "True"
lastUpdateTime: "2024-03-12T20:29:46Z"
reason: StorageVersionMigrationSucceeded
resourceVersion: "84"
k8s:enc:aescbc:v1:key2。考虑这样一种情况: 用户创建了 CustomResourceDefinition (CRD) 来提供自定义资源 (CR),并将其设置为首选的存储模式。 当需要引入 CRD 的 v2 版本时,只需提供转换 Webhook 就可以为 v2 版本提供服务。 基于转换 Webhook 的方式能够实现更平滑的过渡,用户可以使用 v1 或 v2 模式创建 CR,并通过合适的 Webhook 执行必要的模式转换。 在将 v2 设置为首选的存储模式版本之前,重要的是要确保将当前已存储为 v1 的所有 CR 已被迁移到 v2。 这种迁移可以通过使用存储版本迁移将所有 CR 从 v1 迁移到 v2 来达成。
如下针对名为 test-crd.yaml 的 CRD 创建一个清单:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: selfierequests.example.com
spec:
group: example.com
names:
plural: selfierequests
singular: selfierequest
kind: SelfieRequest
listKind: SelfieRequestList
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
hostPort:
type: string
conversion:
strategy: Webhook
webhook:
clientConfig:
url: "https://127.0.0.1:9443/crdconvert"
caBundle: <CABundle info>
conversionReviewVersions:
- v1
- v2
此时存储的版本应当是 v1,运行以下命令来确认这一点:
kubectl get crd selfierequests.example.com -o jsonpath='{.spec.versions[?(@.storage==true)].name}'
使用 kubectl 创建 CRD:
kubectl apply -f test-crd.yaml
为 testcrd 示例创建一个清单。命名为 cr1.yaml 并使用以下内容:
apiVersion: example.com/v1
kind: SelfieRequest
metadata:
name: cr1
namespace: default
使用 kubectl 创建 CR:
kubectl apply -f cr1.yaml
通过从 etcd 获取对象来验证 CR 是否以 v1 格式被写入和存储。
ETCDCTL_API=3 etcdctl get /kubernetes.io/example.com/testcrds/default/cr1 [...] | hexdump -C
其中 [...] 包含连接到 etcd 服务器的额外参数。
如下更新 CRD test-crd.yaml,将 v2 版本设置为 served 和 storage,并将 v1 设置为仅 served:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: selfierequests.example.com
spec:
group: example.com
names:
plural: selfierequests
singular: selfierequest
kind: SelfieRequest
listKind: SelfieRequestList
scope: Namespaced
versions:
- name: v2
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
hostPort:
type: string
conversion:
strategy: Webhook
webhook:
clientConfig:
url: "https://127.0.0.1:9443/crdconvert"
caBundle: <CABundle info>
conversionReviewVersions:
- v1
- v2
现在存储的版本应是 v2,运行以下命令来确认这一点:
kubectl get crd selfierequests.example.com -o jsonpath='{.spec.versions[?(@.storage==true)].name}'
使用 kubectl 更新 CRD:
kubectl apply -f test-crd.yaml
如下创建名为 cr2.yaml 的 CR 资源文件:
apiVersion: example.com/v2
kind: SelfieRequest
metadata:
name: cr2
namespace: default
使用 kubectl 创建 CR:
kubectl apply -f cr2.yaml
通过从 etcd 获取对象来验证 CR 是否以 v2 格式被写入和存储。
ETCDCTL_API=3 etcdctl get /kubernetes.io/example.com/testcrds/default/cr2 [...] | hexdump -C
其中 [...] 包含连接到 etcd 服务器的额外参数。
如下创建名为 migrate-crd.yaml 的 StorageVersionMigration 清单:
kind: StorageVersionMigration
apiVersion: storagemigration.k8s.io/v1beta1
metadata:
name: crdsvm
spec:
resource:
group: example.com
resource: SelfieRequest
使用如下 kubectl 命令创建此对象:
kubectl apply -f migrate-crd.yaml
使用 status 监控 Secret 的迁移。
若迁移成功,应在 status 字段中将 Succeeded 状况设置为 "True"。
获取迁移资源的方式如下:
kubectl get storageversionmigration.storagemigration.k8s.io/crdsvm -o yaml
输出类似于:
kind: StorageVersionMigration
apiVersion: storagemigration.k8s.io/v1beta1
metadata:
name: crdsvm
uid: 13062fe4-32d7-47cc-9528-5067fa0c6ac8
resourceVersion: "111"
creationTimestamp: "2024-03-12T22:40:01Z"
spec:
resource:
group: example.com
resource: testcrds
status:
conditions:
- type: Running
status: "False"
lastUpdateTime: "2024-03-12T22:40:03Z"
reason: StorageVersionMigrationInProgress
- type: Succeeded
status: "True"
lastUpdateTime: "2024-03-12T22:40:03Z"
reason: StorageVersionMigrationSucceeded
resourceVersion: "106"
通过从 etcd 获取对象来验证之前创建的 cr1 是否现在以 v2 格式被写入和存储。
ETCDCTL_API=3 etcdctl get /kubernetes.io/example.com/testcrds/default/cr1 [...] | hexdump -C
其中 [...] 包含连接到 etcd 服务器的额外参数。