使用存储版本迁移来迁移 Kubernetes 对象
Kubernetes v1.30 [alpha]
(默认启用: false)Kubernetes 依赖于主动重写 API 数据,以支持一些与静态存储相关的维护活动。两个突出的例子是存储资源的带版本模式(即,给定资源的优选存储模式从 v1 变更为 v2)和静态加密(即,基于数据应如何加密的变化来重写旧数据)。
开始之前
安装 kubectl
。
你需要有一个 Kubernetes 集群,并且 kubectl 命令行工具已被配置为与你的集群通信。建议在至少有两个不充当控制平面主机的节点的集群上运行本教程。如果你没有集群,可以使用 minikube 创建一个,或者使用这些 Kubernetes playground 之一
你的 Kubernetes 服务器版本必须是 v1.30 或更高版本。要检查版本,输入 kubectl version
。
确保你的集群启用了 StorageVersionMigrator
和 InformerResourceVersion
Feature Gate。你需要控制平面管理员权限来进行此更改。
通过将 API 服务器的运行时配置 storagemigration.k8s.io/v1alpha1
设置为 true
来启用存储版本迁移 REST API。有关如何执行此操作的更多信息,请参阅启用或禁用 Kubernetes API。
使用存储版本迁移重新加密 Kubernetes Secret
首先,配置 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
重新加密,你将使用 Storage Version Migration。创建名为
migrate-secret.yaml
的 StorageVersionMigration 清单,内容如下kind: StorageVersionMigration apiVersion: storagemigration.k8s.io/v1alpha1 metadata: name: secrets-migration spec: resource: group: "" version: v1 resource: secrets
使用 kubectl 创建对象,命令如下
kubectl apply -f migrate-secret.yaml
通过检查 StorageVersionMigration 的
.status
来监控 Secrets 的迁移。成功的迁移应将其Succeeded
条件设置为 true。获取 StorageVersionMigration 对象的命令如下kubectl get storageversionmigration.storagemigration.k8s.io/secrets-migration -o yaml
输出类似于
kind: StorageVersionMigration apiVersion: storagemigration.k8s.io/v1alpha1 metadata: name: secrets-migration uid: 628f6922-a9cb-4514-b076-12d3c178967c resourceVersion: "90" creationTimestamp: "2024-03-12T20:29:45Z" spec: resource: group: "" version: v1 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"
验证存储的 Secret 现在是否以
k8s:enc:aescbc:v1:key2
为前缀。
更新 CRD 的优选存储模式
考虑一种场景,创建了 CustomResourceDefinition (CRD) 来提供自定义资源 (CR),并将其设置为优选存储模式。当需要引入 CRD 的 v2 版本时,可以通过转换 Webhook 仅添加用于提供服务。这使得用户可以使用 v1 或 v2 模式创建 CR,从而实现更平滑的过渡,并通过 Webhook 在它们之间执行必要的模式转换。在将 v2 设置为优选存储模式版本之前,确保所有存储为 v1 的现有 CR 都迁移到 v2 非常重要。可以通过 Storage Version Migration 将所有 CR 从 v1 迁移到 v2 来实现此迁移。
创建 CRD 清单文件,命名为
test-crd.yaml
,内容如下apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: selfierequests.stable.example.com spec: group: stable.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
使用 kubectl 创建 CRD
kubectl apply -f test-crd.yaml
为示例 testcrd 创建清单文件。将清单命名为
cr1.yaml
并使用这些内容apiVersion: stable.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/stable.example.com/testcrds/default/cr1 [...] | hexdump -C
其中
[...]
包含连接到 etcd 服务器的额外参数。更新 CRD
test-crd.yaml
以包含用于服务和存储的 v2 版本,以及仅用于服务的 v1 版本,内容如下apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: selfierequests.stable.example.com spec: group: stable.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
使用 kubectl 更新 CRD
kubectl apply -f test-crd.yaml
创建 CR 资源文件,命名为
cr2.yaml
,内容如下apiVersion: stable.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/stable.example.com/testcrds/default/cr2 [...] | hexdump -C
其中
[...]
包含连接到 etcd 服务器的额外参数。创建名为
migrate-crd.yaml
的 StorageVersionMigration 清单,内容如下kind: StorageVersionMigration apiVersion: storagemigration.k8s.io/v1alpha1 metadata: name: crdsvm spec: resource: group: stable.example.com version: v1 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/v1alpha1 metadata: name: crdsvm uid: 13062fe4-32d7-47cc-9528-5067fa0c6ac8 resourceVersion: "111" creationTimestamp: "2024-03-12T22:40:01Z" spec: resource: group: stable.example.com version: v1 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/stable.example.com/testcrds/default/cr1 [...] | hexdump -C
其中
[...]
包含连接到 etcd 服务器的额外参数。