本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kubernetes v1.26:追溯性預設 StorageClass

Kubernetes v1.25 版本引入了一個 Alpha 功能,用於更改預設 StorageClass 分配給 PersistentVolumeClaim (PVC) 的方式。啟用該功能後,你不再需要先建立預設 StorageClass,然後再建立 PVC 來分配該類。此外,任何未分配 StorageClass 的 PVC 都可以稍後更新。此功能在 Kubernetes v1.26 中升級為 Beta。

你可以在 Kubernetes 文件中閱讀追溯性預設 StorageClass 分配以瞭解更多使用細節,或者繼續閱讀以瞭解 Kubernetes 專案為何進行此更改。

為何 StorageClass 分配需要改進

使用者可能已經熟悉一個類似的功能,該功能在建立時為新的 PVC 分配預設 StorageClass。這目前由准入控制器處理。

但是,如果在建立 PVC 時沒有定義預設的 StorageClass 會怎樣呢?使用者最終會得到一個永遠不會被分配類的 PVC。結果,不會有儲存被製備,PVC 會在這一點上“卡住”。通常,兩種主要場景可能導致“卡住”的 PVC 並引發後續問題。讓我們仔細看看每一種情況。

更改預設 StorageClass

啟用 Alpha 功能後,當管理員想要更改預設 StorageClass 時,有兩種選擇:

  1. 在移除與 PVC 關聯的舊預設 StorageClass 之前,建立一個新的 StorageClass 作為預設。這會導致在短時間記憶體在兩個預設值。此時,如果使用者建立一個 storageClassName 設定為 null(意味著使用預設 StorageClass)的 PersistentVolumeClaim,則會選擇並分配最新的預設 StorageClass 給此 PVC。

  2. 先移除舊的預設值,再建立一個新的預設 StorageClass。這會導致短時間內沒有預設值。隨後,如果使用者建立一個 storageClassName 設定為 null(意味著使用預設 StorageClass)的 PersistentVolumeClaim,該 PVC 將永遠處於 Pending 狀態。使用者必須透過刪除 PVC 並在預設 StorageClass 可用後重新建立它來解決此問題。

叢集安裝期間的資源排序

如果叢集安裝工具需要建立需要儲存的資源,例如映象倉庫,那麼很難正確地確定順序。這是因為任何需要儲存的 Pod 都依賴於預設 StorageClass 的存在,如果未定義,則無法建立。

發生了什麼變化

我們已經更改了 PersistentVolume (PV) 控制器,以便為任何 storageClassName 設定為 null 的未繫結 PersistentVolumeClaim 分配一個預設的 StorageClass。我們還修改了 API 伺服器中的 PersistentVolumeClaim 准入,以允許將值從未設定更改為實際的 StorageClass 名稱。

storageClassName 為 Null 與 storageClassName: "" - 有關係嗎?

在此功能引入之前,這些值在行為上是等效的。任何 storageClassName 設定為 null"" 的 PersistentVolumeClaim 都會繫結到一個 storageClassName 也設定為 null"" 的現有 PersistentVolume 資源。

啟用此新功能後,我們希望保持這種行為,但同時也能更新 StorageClass 名稱。考慮到這些限制,該功能改變了 null 的語義。如果存在預設 StorageClass,null 將轉換為“給我一個預設的”,而 "" 將意味著“給我一個也具有 "" StorageClass 名稱的 PersistentVolume”。在沒有 StorageClass 的情況下,行為將保持不變。

總結以上內容,我們改變了 null 的語義,使其行為取決於是否存在預設 StorageClass 的定義。

下表顯示了所有這些情況,以更好地描述 PVC 何時繫結以及其 StorageClass 何時更新。

追溯性預設 StorageClass 的 PVC 繫結行為
PVCstorageClassName = ""PVCstorageClassName= null
沒有預設類PVstorageClassName = ""繫結繫結
沒有storageClassName繫結繫結
有預設類PVstorageClassName = ""繫結類更新
沒有storageClassName繫結類更新

如何使用它

如果你想在 Alpha 階段測試該功能,你需要在 kube-controller-manager 和 kube-apiserver 中啟用相關的功能門控。使用 --feature-gates 命令列引數。

--feature-gates="...,RetroactiveDefaultStorageClass=true"

試駕

如果你想看到該功能實際執行,並驗證它在你的叢集中是否正常工作,可以嘗試以下操作:

  1. 定義一個基本的 PersistentVolumeClaim

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-1
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
    
  2. 在沒有預設 StorageClass 的情況下建立 PersistentVolumeClaim。PVC 不會製備或繫結(除非已存在一個合適的 PV),並將保持在 Pending 狀態。

    kubectl get pvc
    

    輸出類似於此

    NAME      STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pvc-1     Pending   
    
  3. 將一個 StorageClass 配置為預設。

    kubectl patch sc -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
    

    輸出類似於此

    storageclass.storage.k8s.io/my-storageclass patched
    
  4. 驗證 PersistentVolumeClaims 現在已正確製備,並已用新的預設 StorageClass 追溯性地更新。

    kubectl get pvc
    

    輸出類似於此

    NAME      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
    pvc-1     Bound    pvc-06a964ca-f997-4780-8627-b5c3bf5a87d8   1Gi        RWO            my-storageclass   87m
    

新指標

為了幫助你看到該功能按預期工作,我們還引入了一個新的 retroactive_storageclass_total 指標,用於顯示 PV 控制器嘗試更新 PersistentVolumeClaim 的次數,以及 retroactive_storageclass_errors_total 指標,用於顯示這些嘗試中有多少次失敗了。

參與進來

我們始終歡迎新的貢獻者,所以如果你想參與進來,可以加入我們的 Kubernetes 儲存特別興趣小組(SIG)。

如果你想分享反饋,可以在我們的公共 Slack 頻道上進行。

特別感謝所有提供出色審查、分享寶貴見解並幫助實現此功能的貢獻者(按字母順序排列):