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

本地儲存:儲存容量跟蹤、分散式製備和通用臨時捲進入 Beta 階段

Kubernetes 中的“通用臨時卷”“儲存容量跟蹤”功能正在 Kubernetes 1.21 中升級到 Beta 版。結合 CSI external-provisioner 中的分散式供應支援,開發和部署在節點上本地管理儲存的容器儲存介面 (CSI) 驅動程式變得更加容易。

這篇部落格文章解釋了這些驅動程式以前的工作方式以及如何利用這些功能來簡化驅動程式。

我們正在解決的問題

有一些本地儲存驅動程式,例如用於傳統磁碟的TopoLVM和用於持久記憶體PMEM-CSI。它們在較舊的 Kubernetes 版本上也能正常工作,但實現這一點並不容易。

所需的中央元件

第一個問題是卷供應:它透過 Kubernetes 控制平面進行處理。某些元件必須響應PersistentVolumeClaims (PVC) 並建立卷。通常,這由CSI external-provisioner的中心部署和一個 CSI 驅動程式元件來處理,該元件連線到儲存後端。但是對於本地儲存,沒有這樣的後端。

TopoLVM 透過其不同的元件透過 Kubernetes API 伺服器建立和響應自定義資源來相互通訊。因此,儘管 TopoLVM 基於 CSI(一個獨立於特定容器編排器的標準),但 TopoLVM 僅在 Kubernetes 上執行。

PMEM-CSI 使用 gRPC 呼叫通訊建立了自己的儲存後端。保護這種通訊依賴於 TLS 證書,這使得驅動程式部署更加複雜。

通知 Pod 排程器容量資訊

下一個問題是排程。當卷獨立於 Pod 建立(“即時繫結”)時,CSI 驅動程式必須選擇一個節點,而無需瞭解任何有關將要使用它的 Pod 的資訊。拓撲資訊隨後強制這些 Pod 在建立卷的節點上執行。如果那裡其他資源(如 RAM 或 CPU)耗盡,Pod 將無法啟動。可以透過在 StorageClass 中配置卷建立應等待第一個使用卷的 Pod(`volumeBinding: WaitForFirstConsumer`)來避免這種情況。在這種模式下,Kubernetes 排程器根據其他約束試探性地選擇一個節點,然後要求 external-provisioner 建立一個卷,使其可以在那裡使用。如果本地儲存耗盡,provisioner 可以請求另一次排程輪次。但如果沒有可用容量的資訊,排程器可能總是選擇相同的不合適的節點。

TopoLVM 和 PMEM-CSI 都透過排程器擴充套件器解決了這個問題。這有效,但部署驅動程式時很難配置,因為 kube-scheduler 和驅動程式之間的通訊非常依賴於叢集的設定方式。

重新排程

本地儲存的一個常見用例是臨時空間。比持久卷更適合該用例的是臨時卷,它為 Pod 建立並隨 Pod 一起銷燬。支援 CSI 驅動程式臨時卷的初始 API(因此稱為CSI 臨時卷”設計用於輕量級卷,其中卷建立不太可能失敗。卷建立發生在 Pod 永久排程到節點之後,這與傳統的供應方式相反,傳統供應方式在將 Pod 排程到節點之前嘗試建立卷。必須修改 CSI 驅動程式以支援“CSI 臨時卷”,TopoLVM 和 PMEM-CSI 都已完成此操作。但由於 Kubernetes 中該功能的設計,如果節點上的儲存容量耗盡,Pod 可能會永久卡住。排程器擴充套件器試圖避免這種情況,但不能100%可靠。

Kubernetes 1.21 中的增強功能

分散式供應

從 Kubernetes 1.20 釋出的external-provisioner v2.1.0開始,供應可以由與 CSI 驅動程式一起部署在每個節點上的 external-provisioner 例項處理,然後它們協同工作以供應卷(“分散式供應”)。不再需要中央元件,因此至少對於供應而言,不再需要節點之間的通訊。

儲存容量跟蹤

排程器擴充套件器仍然需要某種方式來了解每個節點上的容量。當 PMEM-CSI 在 v0.9.0 中切換到分散式供應時,這是透過查詢本地驅動程式容器公開的指標資料來完成的。但對於使用者來說,完全消除排程器擴充套件器的需要更好,因為驅動程式部署變得更簡單。儲存容量跟蹤在 1.19 中引入並在 Kubernetes 1.21 中升級到 Beta 版,實現了這一點。它透過在`CSIStorageCapacity`物件中釋出容量資訊來工作。排程器本身隨後使用該資訊來篩選出不合適的節點。由於資訊可能不是完全最新的,Pod 仍然可能被分配到儲存不足的節點,只是可能性較小,並且一旦資訊重新整理,Pod 的下一次排程嘗試應該會更好。

通用臨時卷

因此,CSI 驅動程式仍然需要從錯誤的排程決策中恢復的能力,而對於“CSI 臨時卷”而言,這被證明是不可能實現的。通用臨時卷”是另一個在 1.21 中升級到 Beta 版的功能,它沒有這個限制。此功能添加了一個控制器,該控制器將建立和管理具有 Pod 生命週期的 PVC,因此正常的恢復機制也適用於它們。現有的儲存驅動程式將能夠處理這些 PVC,而無需任何新邏輯來處理這種新情況。

已知限制

通用臨時卷和儲存容量跟蹤都會增加 API 伺服器的負載。這是否是一個問題很大程度上取決於工作負載的型別,特別是多少 Pod 擁有卷以及這些卷需要多久建立和銷燬一次。

沒有嘗試對排程決策如何影響儲存容量進行建模。這是因為效果可能因儲存系統處理儲存的方式而異。結果是,多個帶有未繫結卷的 Pod 可能會被分配到同一個節點,即使只有足夠的容量用於一個 Pod。排程應該會恢復,但如果排程器對儲存瞭解更多,效率會更高。

由於儲存容量由正在執行的 CSI 驅動程式釋出,而叢集自動伸縮器需要有關尚未建立的節點的資訊,因此目前它不會為需要卷的 Pod 擴充套件叢集。目前有一個想法來提供這些資訊,但該領域還需要更多工作。

目前不支援分散式快照和調整大小。應該可以調整相應的 sidecar,並且 external-snapshotter 和 external-resizer 已經有跟蹤問題,只是需要一些志願者。

對於具有多個卷的 Pod,從錯誤的排程決策中恢復可能會失敗,特別是當這些卷是節點本地卷時:如果可以建立一個卷,然後另一個卷的儲存不足,則第一個卷將繼續存在並強制排程器將 Pod 放在該卷的節點上。有一個想法是如何處理這個問題,回滾卷的供應,但這仍處於非常早期的頭腦風暴階段,甚至還沒有合併到 KEP 中。目前,最好避免建立具有多個持久卷的 Pod。

啟用新功能和後續步驟

隨著該功能在 1.21 版本中進入 Beta 階段,無需額外操作即可啟用它。通用臨時卷也無需更改 CSI 驅動程式即可工作。有關更多資訊,請參閱文件和關於它的上一篇部落格文章。API 在 Alpha 和 Beta 之間沒有發生任何變化。

對於其他兩個功能,external-provisioner 文件解釋了 CSI 驅動程式開發人員必須如何更改其驅動程式的部署方式以支援儲存容量跟蹤分散式供應。這兩個功能是獨立的,因此只啟用其中一個也可以。

SIG Storage 希望聽取您使用這些新功能的反饋。您可以透過電子郵件Slack(頻道#sig-storage)以及定期 SIG 會議與我們聯絡。您的工作負載描述對於驗證設計決策、設定效能測試以及最終將這些功能推廣到 GA 將非常有幫助。

致謝

非常感謝為這些功能做出貢獻或提供反饋的社群成員,包括 SIG Scheduling、SIG Auth 以及當然還有 SIG Storage 的成員!