使用存储版本迁移迁移 Kubernetes 对象
Kubernetes v1.30 [alpha]
(默认禁用:false)Kubernetes 依赖于 API 数据的积极重写,以支持与静态存储相关的一些维护活动。两个突出的例子是存储资源的带版本模式(即,给定资源的偏好存储模式从 v1 更改为 v2)和静态加密(即,根据数据应该如何加密的更改来重写旧数据)。
准备开始
安装 kubectl
。
你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以与你的集群通信。建议在至少有两个非充当控制平面主机的节点的集群上运行本教程。如果还没有集群,可以使用 minikube 创建一个,也可以使用这些 Kubernetes 游乐场之一
你的 Kubernetes 服务器版本必须等于或高于 v1.30。要检查版本,请输入kubectl version
。确保你的集群启用了 StorageVersionMigrator
和 InformerResourceVersion
特性门控。你需要控制平面管理员权限才能进行更改。
通过将 API 服务器的运行时配置 storagemigration.k8s.io/v1alpha1
设置为 true
来启用存储版本迁移 REST API。有关如何执行此操作的更多信息,请阅读启用或禁用 Kubernetes API。
使用存储版本迁移重新加密 Kubernetes 密钥
首先,配置 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/v1alpha1 metadata: name: secrets-migration spec: resource: group: "" version: v1 resource: secrets
使用 *kubectl* 创建对象,如下所示
kubectl apply -f migrate-secret.yaml
通过检查 StorageVersionMigration 的
.status
监视 Secret 的迁移。成功的迁移应将其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 版本时,可以添加 v2 版本仅用于服务,并带有一个转换 Webhook。这可以实现更平稳的过渡,用户可以使用 v1 或 v2 模式创建 CR,并使用 Webhook 在它们之间执行必要的模式转换。在将 v2 设置为首选存储模式版本之前,请务必确保所有存储为 v1 的现有 CR 都迁移到 v2。这种迁移可以通过*存储版本迁移*来实现,从而将所有 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
创建一个名为
cr2.yaml
的 CR 资源文件,如下所示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
使用状态监视 Secret 的迁移。成功的迁移应将状态字段中的
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 服务器的其他参数。