使用儲存版本遷移 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 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 重新加密,你將使用 **儲存版本遷移**。

  • 建立一個名為 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 版本時,可以僅透過轉換 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)