使用存储版本迁移迁移 Kubernetes 对象

功能状态: Kubernetes v1.30 [alpha](默认禁用:false)

Kubernetes 依赖于 API 数据的积极重写,以支持与静态存储相关的一些维护活动。两个突出的例子是存储资源的带版本模式(即,给定资源的偏好存储模式从 v1 更改为 v2)和静态加密(即,根据数据应该如何加密的更改来重写旧数据)。

准备开始

安装 kubectl

你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以与你的集群通信。建议在至少有两个非充当控制平面主机的节点的集群上运行本教程。如果还没有集群,可以使用 minikube 创建一个,也可以使用这些 Kubernetes 游乐场之一

你的 Kubernetes 服务器版本必须等于或高于 v1.30。要检查版本,请输入 kubectl version

确保你的集群启用了 StorageVersionMigratorInformerResourceVersion 特性门控。你需要控制平面管理员权限才能进行更改。

通过将 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 服务器的其他参数。

上次修改时间:太平洋标准时间 2024 年 11 月 13 日上午 11:50:修复 EncryptionConfiguration 缩进 (d9298ddb3f)