本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
Kubernetes 的本地持久捲進入 Beta 階段
Kubernetes 1.10 中的 本地持久卷 beta 功能使得在有狀態應用(StatefulSets)中利用本地磁碟成為可能。您可以將直接連線的本地磁碟指定為持久卷(PersistentVolumes),並在有狀態應用中使用它們,就像之前僅支援遠端卷型別的持久卷宣告(PersistentVolumeClaim)物件一樣。
持久儲存對於執行有狀態應用至關重要,Kubernetes 透過 StatefulSets、PersistentVolumeClaims 和 PersistentVolumes 支援這些工作負載。這些原語很好地支援了遠端卷型別,即卷可以從叢集中的任何節點訪問,但不支援本地卷,即卷只能從特定節點訪問。隨著在 Kubernetes 中執行更多工作負載的需求增加,在複製的有狀態工作負載中使用本地快速 SSD 的需求也隨之增加。
解決 hostPath 的挑戰
以前透過 hostPath 卷訪問本地儲存的機制存在許多挑戰。hostPath 卷在大規模生產中使用起來很困難:操作員需要在使用 hostPath 卷時關心本地磁碟管理、拓撲和單個 Pod 的排程,並且無法使用許多 Kubernetes 功能(如 StatefulSets)。現有使用遠端卷的 Helm Charts 無法輕鬆移植到使用 hostPath 卷。本地持久卷功能旨在解決 hostPath 卷的可移植性、磁碟記賬和排程挑戰。
免責宣告
在詳細介紹如何使用本地持久卷之前,請注意,本地卷不適用於大多數應用程式。使用本地儲存會將您的應用程式繫結到特定節點,從而使您的應用程式更難排程。如果該節點或本地捲髮生故障並變得不可訪問,那麼該 Pod 也將變得不可訪問。此外,許多雲提供商不為本地儲存提供廣泛的資料永續性保證,因此在某些情況下您可能會丟失所有資料。
由於這些原因,大多數應用程式應繼續使用高可用、遠端可訪問、持久的儲存。
合適的工作負載
適用於本地儲存的一些用例包括
- 利用資料引力實現快速處理的資料集快取
- 在多個節點上分片或複製資料的分散式儲存系統。示例包括 Cassandra 等分散式資料儲存,或 Gluster 或 Ceph 等分散式檔案系統。
合適的工作負載能夠容忍節點故障、資料不可用和資料丟失。它們為叢集的其餘部分提供關鍵的、對延遲敏感的基礎設施服務,並且應比其他工作負載以更高的優先順序執行。
啟用更智慧的排程和卷繫結
管理員必須為本地持久卷啟用更智慧的排程。在為本地持久卷建立任何 PersistentVolumeClaims 之前,必須建立一個 StorageClass,並將 volumeBindingMode 設定為“WaitForFirstConsumer”
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
此設定告訴 PersistentVolume 控制器不要立即繫結 PersistentVolumeClaim。相反,系統會等待需要使用卷的 Pod 被排程。然後排程程式會選擇一個合適的本地 PersistentVolume 進行繫結,同時考慮到 Pod 的其他排程約束和策略。這確保了初始卷繫結與任何 Pod 資源要求、選擇器、親和性和反親和性策略等相容。
請注意,動態預配在 beta 版中不受支援。所有本地 PersistentVolumes 都必須靜態建立。
建立本地持久卷
對於這個最初的 beta 版,本地磁碟必須首先由管理員在本地節點上進行預分割槽、格式化和掛載。共享檔案系統上的目錄也受支援,但必須在使用前建立。
設定本地卷後,您可以為其建立 PersistentVolume。在此示例中,本地卷掛載在節點“my-node”上的“/mnt/disks/vol1”
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-local-pv
spec:
capacity:
storage: 500Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /mnt/disks/vol1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- my-node
請注意,PersistentVolume 物件中有一個新的 nodeAffinity 欄位:這就是 Kubernetes 排程程式理解此 PersistentVolume 與特定節點繫結的方式。nodeAffinity 是本地 PersistentVolumes 的必填欄位。
當像這樣手動建立本地卷時,唯一受支援的 persistentVolumeReclaimPolicy 是“Retain”。當 PersistentVolume 從 PersistentVolumeClaim 釋放時,管理員必須手動清理並重新設定本地卷才能重複使用。
本地卷建立和刪除自動化
手動建立和清理本地卷是一項繁重的管理負擔,因此我們編寫了一個簡單的本地卷管理器來自動化其中一些部分。它可以在 external-storage 倉庫 中作為可選程式提供,您可以將其部署到叢集中,包括如何執行它的說明和示例部署規範。
要使用它,本地卷仍必須首先由管理員在本地節點上設定和掛載。管理員需要將本地卷掛載到本地卷管理器識別的可配置“發現目錄”中。共享檔案系統上的目錄受支援,但它們必須繫結掛載到發現目錄中。
此本地卷管理器監視發現目錄,查詢任何新的掛載點。管理器會為檢測到的任何新掛載點建立具有適當 storageClassName、路徑、nodeAffinity 和容量的 PersistentVolume 物件。這些 PersistentVolume 物件最終可以被 PersistentVolumeClaims 宣告,然後掛載到 Pod 中。
Pod 使用完卷並刪除其 PersistentVolumeClaim 後,本地卷管理器會透過刪除所有檔案來清理本地掛載,然後刪除 PersistentVolume 物件。這會觸發發現週期:為該卷建立一個新的 PersistentVolume,並可以被新的 PersistentVolumeClaim 重複使用。
一旦管理員最初設定了本地卷掛載,此本地卷管理器就會接管 PersistentVolume 生命週期的其餘部分,無需進一步的管理員干預。
在 Pod 中使用本地卷
經過所有管理員工作後,使用者如何實際將本地卷掛載到他們的 Pod 中?幸運的是,從使用者的角度來看,本地卷可以以與任何其他 PersistentVolume 型別完全相同的方式請求:透過 PersistentVolumeClaim。只需在 PersistentVolumeClaim 物件中指定本地卷的適當 StorageClassName,系統就會處理其餘部分!
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: example-local-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage
resources:
requests:
storage: 500Gi
或者在 StatefulSet 中作為 volumeClaimTemplate
kind: StatefulSet
...
volumeClaimTemplates:
- metadata:
name: example-local-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage
resources:
requests:
storage: 500Gi
文件
Kubernetes 網站提供了 本地持久卷 的完整文件。
未來增強
本地持久卷 beta 功能遠未完成。一些正在開發中的顯著增強包括
- 從 1.10 開始,本地原始塊卷作為 alpha 功能提供。這對於需要直接訪問塊裝置並管理自己的資料格式的工作負載非常有用。
- 使用 LVM 的本地捲動態預配正在設計中,alpha 實現將在未來的版本中釋出。這將消除當前管理員預分割槽、格式化和掛載本地卷的需求,只要工作負載的效能要求能夠容忍共享磁碟。
互補功能
Pod 優先順序和搶佔 是另一個與本地持久卷互補的 Kubernetes 功能。當您的應用程式使用本地儲存時,它必須排程到本地卷所在的特定節點。您可以為本地儲存工作負載設定高優先順序,以便如果該節點空間不足以執行您的工作負載,Kubernetes 可以搶佔低優先順序工作負載為其騰出空間。
Pod 驅逐預算 對於必須保持仲裁的工作負載也非常重要。為您的工作負載設定驅逐預算可確保其不會因自願驅逐事件(例如升級期間的節點排空)而低於仲裁。
Pod 親和性和反親和性 可確保您的工作負載要麼共同定位,要麼分佈在不同的故障域中。如果單個節點上有多個本地持久卷可用,則最好指定 Pod 反親和性策略以將工作負載分佈在不同節點上。請注意,如果您希望多個 Pod 共享相同的本地持久卷,則無需指定 Pod 親和性策略。排程程式瞭解本地持久卷的本地性約束,並將您的 Pod 排程到正確的節點。
參與進來
如果您對該功能有反饋或有興趣參與設計和開發,請加入 Kubernetes 儲存特別興趣小組 (SIG)。我們正在迅速發展,並始終歡迎新的貢獻者。
特別感謝來自多家公司(包括 Cheng Xing (verult)、David Zhu (davidz627)、Deyuan Deng (ddysher)、Dhiraj Hedge (dhirajh)、Ian Chakeres (ianchakeres)、Jan Šafránek (jsafrane)、Matthew Wong (wongma7)、Michelle Au (msau42)、Serguei Bezverkhi (sbezverk) 和 Yuquan Ren (nickrenren))的所有貢獻者,他們幫助將此功能推向 beta 階段。