本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
為 PersistentVolume 引入單 Pod 訪問模式
上個月釋出的 Kubernetes v1.22 引入了 PersistentVolumes 和 PersistentVolumeClaims 的新 ReadWriteOncePod 訪問模式。藉助此 Alpha 功能,Kubernetes 允許您將卷訪問許可權限制為叢集中的單個 Pod。
什麼是訪問模式以及它們為什麼重要?
在使用儲存時,有不同的方式來模擬儲存的使用方式。
例如,像網路檔案共享這樣的儲存系統可以有許多使用者同時讀取和寫入資料。在其他情況下,也許每個人都允許讀取資料但不允許寫入。對於高度敏感的資料,也許只允許一個使用者讀取和寫入資料,而其他人則不允許。
在 Kubernetes 世界中,訪問模式是您定義持久化儲存如何被使用的方式。這些訪問模式是 PersistentVolumes (PVs) 和 PersistentVolumeClaims (PVCs) 規範的一部分。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: shared-cache
spec:
accessModes:
- ReadWriteMany # Allow many nodes to access shared-cache simultaneously.
resources:
requests:
storage: 1Gi
在 v1.22 之前,Kubernetes 為 PV 和 PVC 提供了三種訪問模式
- ReadWriteOnce – 卷可以由單個節點以讀寫方式掛載
- ReadOnlyMany – 卷可以由多個節點以只讀方式掛載
- ReadWriteMany – 卷可以由多個節點以讀寫方式掛載
這些訪問模式由 Kubernetes 元件(如 kube-controller-manager
和 kubelet
)強制執行,以確保只有某些 Pod 被允許訪問給定的 PersistentVolume。
這種新的訪問模式是什麼,它是如何工作的?
Kubernetes v1.22 為 PV 和 PVC 引入了第四種訪問模式,您可以將其用於 CSI 卷
- ReadWriteOncePod – 卷可以由單個 Pod 以讀寫方式掛載
如果您建立一個使用 ReadWriteOncePod 訪問模式的 PVC 的 Pod,Kubernetes 會確保該 Pod 是整個叢集中唯一可以讀取或寫入該 PVC 的 Pod。
如果您建立另一個 Pod,並使用此訪問模式引用相同的 PVC,則該 Pod 將無法啟動,因為該 PVC 已經被另一個 Pod 使用。例如
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 1s default-scheduler 0/1 nodes are available: 1 node has pod using PersistentVolumeClaim with the same name and ReadWriteOncePod access mode.
這與 ReadWriteOnce 訪問模式有何不同?
ReadWriteOnce 訪問模式將卷訪問限制為單個*節點*,這意味著同一節點上的多個 Pod 可以從同一卷讀取和寫入。這對於某些應用程式來說可能是一個大問題,特別是如果它們需要最多一個寫入器來保證資料安全。
使用 ReadWriteOncePod,這些問題就不存在了。在您的 PVC 上設定訪問模式,Kubernetes 保證只有一個 Pod 具有訪問許可權。
我該如何使用它?
ReadWriteOncePod 訪問模式在 Kubernetes v1.22 中處於 Alpha 階段,並且僅支援 CSI 卷。作為第一步,您需要為 kube-apiserver
、kube-scheduler
和 kubelet
啟用 ReadWriteOncePod Feature Gate。您可以透過設定命令列引數來啟用該功能
--feature-gates="...,ReadWriteOncePod=true"
您還需要將以下 CSI 邊車更新到這些版本或更高版本
建立 PersistentVolumeClaim
為了將 ReadWriteOncePod 訪問模式用於您的 PV 和 PVC,您需要建立一個帶有該訪問模式的新 PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: single-writer-only
spec:
accessModes:
- ReadWriteOncePod # Allow only a single pod to access single-writer-only.
resources:
requests:
storage: 1Gi
如果您的儲存外掛支援動態製備,則將使用 ReadWriteOncePod 訪問模式建立新的 PersistentVolumes。
遷移現有 PersistentVolumes
如果您有現有的 PersistentVolumes,可以將其遷移以使用 ReadWriteOncePod。
在此示例中,我們已經有一個名為“cat-pictures-pvc”的 PersistentVolumeClaim,它繫結到“cat-pictures-pv”PersistentVolume,以及一個使用此 PersistentVolumeClaim 的“cat-pictures-writer”Deployment。
作為第一步,您需要編輯 PersistentVolume 的 spec.persistentVolumeReclaimPolicy
並將其設定為 Retain
。這可以確保當刪除相應的 PersistentVolumeClaim 時,您的 PersistentVolume 不會被刪除
kubectl patch pv cat-pictures-pv -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
接下來,您需要停止所有正在使用繫結到您要遷移的 PersistentVolume 的 PersistentVolumeClaim 的工作負載,然後刪除 PersistentVolumeClaim。
完成此操作後,您需要清除 PersistentVolume 的 spec.claimRef.uid
,以確保在重新建立時 PersistentVolumeClaims 可以繫結到它
kubectl scale --replicas=0 deployment cat-pictures-writer
kubectl delete pvc cat-pictures-pvc
kubectl patch pv cat-pictures-pv -p '{"spec":{"claimRef":{"uid":""}}}'
之後,您需要將 PersistentVolume 的訪問模式替換為 ReadWriteOncePod
kubectl patch pv cat-pictures-pv -p '{"spec":{"accessModes":["ReadWriteOncePod"]}}'
說明
ReadWriteOncePod 訪問模式不能與其他訪問模式結合使用。更新時請確保 ReadWriteOncePod 是 PersistentVolume 上的唯一訪問模式,否則請求將失敗。接下來,您需要修改 PersistentVolumeClaim,將 ReadWriteOncePod 設定為唯一的訪問模式。您還應該將 PersistentVolumeClaim 的 spec.volumeName
設定為 PersistentVolume 的名稱。
完成此操作後,您可以重新建立 PersistentVolumeClaim 並啟動您的工作負載
# IMPORTANT: Make sure to edit your PVC in cat-pictures-pvc.yaml before applying. You need to:
# - Set ReadWriteOncePod as the only access mode
# - Set spec.volumeName to "cat-pictures-pv"
kubectl apply -f cat-pictures-pvc.yaml
kubectl apply -f cat-pictures-writer-deployment.yaml
最後,如果您之前更改了 PersistentVolume 的 spec.persistentVolumeReclaimPolicy
,您可以將其改回 Delete
。
kubectl patch pv cat-pictures-pv -p '{"spec":{"persistentVolumeReclaimPolicy":"Delete"}}'
您可以閱讀配置 Pod 以使用 PersistentVolume 進行儲存以獲取有關使用 PersistentVolumes 和 PersistentVolumeClaims 的更多詳細資訊。
哪些卷外掛支援此功能?
唯一支援此功能的卷外掛是 CSI 驅動程式。SIG Storage 不計劃在樹內外掛中支援此功能,因為它們正在作為 CSI 遷移的一部分被棄用。對於喜歡使用舊版樹內卷 API 並啟用 CSI 遷移的使用者,可能會考慮對 Beta 版提供支援。
作為儲存供應商,我如何為我的 CSI 驅動程式新增對此訪問模式的支援?
ReadWriteOncePod 訪問模式開箱即用,無需對 CSI 驅動程式進行任何更新,但確實需要更新 CSI 邊車。話雖如此,如果您想及時瞭解 CSI 規範 (v1.5.0+) 的最新更改,請繼續閱讀。
CSI 規範中引入了兩種新的訪問模式,以消除舊版 SINGLE_NODE_WRITER
訪問模式的歧義。它們是 SINGLE_NODE_SINGLE_WRITER
和 SINGLE_NODE_MULTI_WRITER
。為了向邊車(如 external-provisioner)傳達您的驅動程式理解並接受這兩種新的 CSI 訪問模式,您的驅動程式還需要為 控制器服務和 節點服務宣傳 SINGLE_NODE_MULTI_WRITER
功能。
如果您想了解這些訪問模式和功能位背後的動機,還可以閱讀 KEP-2485(ReadWriteOncePod PersistentVolume 訪問模式)的CSI 規範更改、卷功能部分。
更新您的 CSI 驅動程式以使用新介面
作為第一步,您需要將驅動程式的 container-storage-interface
依賴項更新到 v1.5.0+,其中包含對這些新訪問模式和功能的支援。
接受新的 CSI 訪問模式
如果您的 CSI 驅動程式包含用於驗證請求的 CSI 訪問模式的邏輯,則可能需要更新。如果它目前接受 SINGLE_NODE_WRITER
,則應更新它以同時接受 SINGLE_NODE_SINGLE_WRITER
和 SINGLE_NODE_MULTI_WRITER
。
以 GCP PD CSI 驅動程式驗證邏輯為例,以下是其擴充套件方式
diff --git a/pkg/gce-pd-csi-driver/utils.go b/pkg/gce-pd-csi-driver/utils.go
index 281242c..b6c5229 100644
--- a/pkg/gce-pd-csi-driver/utils.go
+++ b/pkg/gce-pd-csi-driver/utils.go
@@ -123,6 +123,8 @@ func validateAccessMode(am *csi.VolumeCapability_AccessMode) error {
case csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY:
case csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY:
case csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER:
+ case csi.VolumeCapability_AccessMode_SINGLE_NODE_SINGLE_WRITER:
+ case csi.VolumeCapability_AccessMode_SINGLE_NODE_MULTI_WRITER:
default:
return fmt.Errorf("%v access mode is not supported for for PD", am.GetMode())
}
宣傳新的 CSI 控制器和節點服務功能
您的 CSI 驅動程式還需要在 ControllerGetCapabilities
和 NodeGetCapabilities
RPC 中返回新的 SINGLE_NODE_MULTI_WRITER
功能。
以 GCP PD CSI 驅動程式功能宣傳邏輯為例,以下是其擴充套件方式
diff --git a/pkg/gce-pd-csi-driver/gce-pd-driver.go b/pkg/gce-pd-csi-driver/gce-pd-driver.go
index 45903f3..0d7ea26 100644
--- a/pkg/gce-pd-csi-driver/gce-pd-driver.go
+++ b/pkg/gce-pd-csi-driver/gce-pd-driver.go
@@ -56,6 +56,8 @@ func (gceDriver *GCEDriver) SetupGCEDriver(name, vendorVersion string, extraVolu
csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY,
csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER,
+ csi.VolumeCapability_AccessMode_SINGLE_NODE_SINGLE_WRITER,
+ csi.VolumeCapability_AccessMode_SINGLE_NODE_MULTI_WRITER,
}
gceDriver.AddVolumeCapabilityAccessModes(vcam)
csc := []csi.ControllerServiceCapability_RPC_Type{
@@ -67,12 +69,14 @@ func (gceDriver *GCEDriver) SetupGCEDriver(name, vendorVersion string, extraVolu
csi.ControllerServiceCapability_RPC_EXPAND_VOLUME,
csi.ControllerServiceCapability_RPC_LIST_VOLUMES,
csi.ControllerServiceCapability_RPC_LIST_VOLUMES_PUBLISHED_NODES,
+ csi.ControllerServiceCapability_RPC_SINGLE_NODE_MULTI_WRITER,
}
gceDriver.AddControllerServiceCapabilities(csc)
ns := []csi.NodeServiceCapability_RPC_Type{
csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME,
csi.NodeServiceCapability_RPC_EXPAND_VOLUME,
csi.NodeServiceCapability_RPC_GET_VOLUME_STATS,
+ csi.NodeServiceCapability_RPC_SINGLE_NODE_MULTI_WRITER,
}
gceDriver.AddNodeServiceCapabilities(ns)
實現 NodePublishVolume
行為
CSI 規範概述了針對同一卷呼叫 NodePublishVolume
RPC 兩次以上但引數不同(例如目標路徑)時的預期行為。有關在驅動程式中實現時預期行為的更多詳細資訊,請參閱 CSI 規範中 NodePublishVolume 部分的第二個表格。
更新您的 CSI 邊車
部署 CSI 驅動程式時,您必須將以下 CSI 邊車更新到依賴於 CSI 規範 v1.5.0+ 和 Kubernetes v1.22 API 的版本。最低要求版本為
下一步是什麼?
作為此功能 Beta 畢業的一部分,SIG Storage 計劃更新 Kubernetes 排程器以支援與 ReadWriteOncePod 儲存相關的 Pod 搶佔。這意味著如果兩個 Pod 請求一個具有 ReadWriteOncePod 的 PersistentVolumeClaim,則優先順序最高的 Pod 將獲得對 PersistentVolumeClaim 的訪問許可權,而任何優先順序較低的 Pod 將從節點中搶佔,並且無法訪問 PersistentVolumeClaim。
我如何瞭解更多資訊?
請參閱 KEP-2485 以獲取有關 ReadWriteOncePod 訪問模式和 CSI 規範更改動機的更多詳細資訊。
我如何參與?
Kubernetes #csi Slack 頻道和任何標準 SIG Storage 通訊渠道都是聯絡 SIG Storage 和 CSI 團隊的好媒介。
特別感謝以下人員的富有洞察力的審查和設計考慮
- Abdullah Gharaibeh (ahg-g)
- Aldo Culquicondor (alculquicondor)
- Ben Swartzlander (bswartz)
- Deep Debroy (ddebroy)
- Hemant Kumar (gnufied)
- Humble Devassy Chirammal (humblec)
- James DeFelice (jdef)
- Jan Šafránek (jsafrane)
- Jing Xu (jingxu97)
- Jordan Liggitt (liggitt)
- Michelle Au (msau42)
- Saad Ali (saad-ali)
- Tim Hockin (thockin)
- Xing Yang (xing-yang)
如果您有興趣參與 CSI 或 Kubernetes 儲存系統的任何部分的設計和開發,請加入 Kubernetes 儲存特別興趣小組 (SIG)。我們正在快速發展,並始終歡迎新的貢獻者。