使用存储版本迁移迁移 Kubernetes 对象
Kubernetes v1.30 [alpha]
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 创建一个密钥。
kubectl create secret generic my-secret --from-literal=key1=supersecret
验证 该密钥对象的序列化数据是否以
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==
为了确保之前创建的密钥
my-secert
使用新密钥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
通过检查
.status
中的 StorageVersionMigration 来监控密钥的迁移。成功的迁移应将其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"
验证 存储的密钥现在是否以
k8s:enc:aescbc:v1:key2
为前缀。
更新 CRD 的首选存储模式
考虑以下情况:创建一个 自定义资源定义 (CRD) 来提供自定义资源 (CR),并将其设置为首选存储模式。当需要引入 CRD 的 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
使用状态监控密钥的迁移。成功的迁移应在状态字段中将
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"
验证之前创建的 cr1 现在是否以 v2 形式写入和存储,方法是从 etcd 获取对象。
ETCDCTL_API=3 etcdctl get /kubernetes.io/stable.example.com/testcrds/default/cr1 [...] | hexdump -C
其中
[...]
包含连接到 etcd 服务器的附加参数。