持久化卷
本文件描述 Kubernetes 中的持久化卷。建議您熟悉卷、儲存類別和卷屬性類別。
簡介
管理儲存與管理運算執行個體是不同的問題。PersistentVolume 子系統為使用者和管理員提供 API,將儲存如何提供的詳細資訊,從其使用方式中抽象化出來。為此,我們引入了兩個新的 API 資源:PersistentVolume 和 PersistentVolumeClaim。
PersistentVolume (PV) 是叢集中的一塊儲存空間,由管理員佈建,或使用儲存類別動態佈建。它就像節點一樣,是叢集中的一種資源。PV 是類似於 Volume 的卷外掛程式,但其生命週期獨立於任何使用該 PV 的個別 Pod。此 API 物件捕捉了儲存實作的詳細資訊,無論是 NFS、iSCSI 還是雲端供應商特定的儲存系統。
PersistentVolumeClaim (PVC) 是使用者對儲存空間的請求。它與 Pod 類似。Pod 消耗節點資源,而 PVC 消耗 PV 資源。Pod 可以請求特定等級的資源(CPU 和記憶體)。Claim 可以請求特定的大小和存取模式(例如,它們可以掛載為 ReadWriteOnce、ReadOnlyMany、ReadWriteMany 或 ReadWriteOncePod,請參閱 AccessModes)。
雖然 PersistentVolumeClaim 允許使用者使用抽象的儲存資源,但使用者通常需要具有不同屬性的 PersistentVolume,例如效能,以解決不同的問題。叢集管理員需要能夠提供各種 PersistentVolume,它們在大小和存取模式以外的方面有所不同,而無需向使用者公開這些卷是如何實作的細節。對於這些需求,有 StorageClass 資源。
請參閱包含可運作範例的詳細逐步解說。
卷和請求的生命週期
PV 是叢集中的資源。PVC 是對這些資源的請求,也充當資源的請求檢查。PV 和 PVC 之間的互動遵循此生命週期
佈建
PV 可以透過兩種方式佈建:靜態或動態。
靜態
叢集管理員建立許多 PV。它們攜帶真實儲存的詳細資訊,供叢集使用者使用。它們存在於 Kubernetes API 中,可供使用。
動態
當管理員建立的靜態 PV 都無法符合使用者的 PersistentVolumeClaim 時,叢集可能會嘗試為 PVC 動態佈建卷。此佈建基於 StorageClass:PVC 必須請求儲存類別,且管理員必須已建立並設定該類別以進行動態佈建。請求類別 ""
的請求實際上會為自己停用動態佈建。
若要啟用基於儲存類別的動態儲存佈建,叢集管理員需要在 API 伺服器上啟用 DefaultStorageClass
准入控制器。例如,可以透過確保 DefaultStorageClass
在 API 伺服器元件的 --enable-admission-plugins
標誌的逗號分隔的有序值列表中。有關 API 伺服器命令列標誌的更多資訊,請查看 kube-apiserver 文件。
繫結
使用者建立 PersistentVolumeClaim,或者在動態佈建的情況下,已建立 PersistentVolumeClaim,其中請求了特定的儲存量和特定的存取模式。控制平面的控制迴圈會監看新的 PVC,尋找符合的 PV(如果可能),並將它們綁定在一起。如果為新的 PVC 動態佈建了 PV,則迴圈將始終將該 PV 綁定到 PVC。否則,使用者將始終獲得至少他們所要求的,但卷可能超出所請求的量。一旦綁定,PersistentVolumeClaim 綁定是獨佔的,無論它們是如何綁定的。PVC 到 PV 的綁定是一對一的映射,使用 ClaimRef,它是 PersistentVolume 和 PersistentVolumeClaim 之間的雙向綁定。
如果不存在符合的卷,請求將無限期地保持未綁定狀態。當符合的卷可用時,請求將被綁定。例如,佈建了許多 50Gi PV 的叢集將不符合請求 100Gi 的 PVC。當向叢集新增 100Gi PV 時,PVC 可以被綁定。
使用中
Pod 將請求用作卷。叢集檢查請求以尋找綁定的卷,並為 Pod 掛載該卷。對於支援多種存取模式的卷,使用者在使用其請求作為 Pod 中的卷時,指定所需的模式。
一旦使用者擁有請求並且該請求被綁定,綁定的 PV 就屬於使用者,只要他們需要它。使用者排程 Pod 並透過在 Pod 的 volumes
區段中包含 persistentVolumeClaim
區段來存取他們請求的 PV。有關此的更多詳細資訊,請參閱 將請求用作卷。
使用中儲存物件保護
使用中儲存物件保護功能的目的是確保 Pod 正在使用的 PersistentVolumeClaim (PVC) 和綁定到 PVC 的 PersistentVolume (PV) 不會從系統中移除,因為這可能會導致資料遺失。
注意
當存在使用 PVC 的 Pod 物件時,PVC 處於 Pod 的使用中狀態。如果使用者刪除 Pod 正在使用的 PVC,則 PVC 不會立即移除。PVC 的移除將延遲到 PVC 不再被任何 Pod 主動使用為止。此外,如果管理員刪除綁定到 PVC 的 PV,則 PV 不會立即移除。PV 的移除將延遲到 PV 不再綁定到 PVC 為止。
您可以查看 PVC 的狀態為 Terminating
且 Finalizers
列表包含 kubernetes.io/pvc-protection
時,PVC 受到保護
kubectl describe pvc hostpath
Name: hostpath
Namespace: default
StorageClass: example-hostpath
Status: Terminating
Volume:
Labels: <none>
Annotations: volume.beta.kubernetes.io/storage-class=example-hostpath
volume.beta.kubernetes.io/storage-provisioner=example.com/hostpath
Finalizers: [kubernetes.io/pvc-protection]
...
您可以查看 PV 的狀態為 Terminating
且 Finalizers
列表也包含 kubernetes.io/pv-protection
時,PV 受到保護
kubectl describe pv task-pv-volume
Name: task-pv-volume
Labels: type=local
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass: standard
Status: Terminating
Claim:
Reclaim Policy: Delete
Access Modes: RWO
Capacity: 1Gi
Message:
Source:
Type: HostPath (bare host directory volume)
Path: /tmp/data
HostPathType:
Events: <none>
回收
當使用者完成使用他們的卷時,他們可以從 API 中刪除 PVC 物件,這允許回收資源。PersistentVolume 的回收策略告訴叢集在卷從其請求釋放後該如何處理。目前,卷可以選擇保留 (Retained)、回收 (Recycled) 或刪除 (Deleted)。
保留
Retain
回收策略允許手動回收資源。當 PersistentVolumeClaim 被刪除時,PersistentVolume 仍然存在,並且卷被視為「已釋放」。但是它還不能用於另一個請求,因為先前的請求者的資料仍然留在卷上。管理員可以使用以下步驟手動回收卷。
- 刪除 PersistentVolume。在 PV 刪除後,外部基礎架構中關聯的儲存資產仍然存在。
- 相應地手動清理關聯儲存資產上的資料。
- 手動刪除關聯的儲存資產。
如果您想重複使用相同的儲存資產,請使用相同的儲存資產定義建立新的 PersistentVolume。
刪除
對於支援 Delete
回收策略的卷外掛程式,刪除會從 Kubernetes 中移除 PersistentVolume 物件,以及外部基礎架構中關聯的儲存資產。動態佈建的卷繼承其 StorageClass 的回收策略,預設為 Delete
。管理員應根據使用者的期望設定 StorageClass;否則,必須在建立 PV 後編輯或修補它。請參閱變更 PersistentVolume 的回收策略。
回收
警告
Recycle
回收策略已棄用。相反地,建議的方法是使用動態佈建。如果底層卷外掛程式支援,Recycle
回收策略會在卷上執行基本清除 (rm -rf /thevolume/*
),並使其再次可用於新的請求。
但是,管理員可以使用 Kubernetes 控制器管理員命令列引數設定自訂回收器 Pod 範本,如參考資料中所述。自訂回收器 Pod 範本必須包含 volumes
規範,如下例所示
apiVersion: v1
kind: Pod
metadata:
name: pv-recycler
namespace: default
spec:
restartPolicy: Never
volumes:
- name: vol
hostPath:
path: /any/path/it/will/be/replaced
containers:
- name: pv-recycler
image: "registry.k8s.io/busybox"
command: ["/bin/sh", "-c", "test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/* && test -z \"$(ls -A /scrub)\" || exit 1"]
volumeMounts:
- name: vol
mountPath: /scrub
但是,在自訂回收器 Pod 範本的 volumes
部分中指定的特定路徑將被替換為正在回收的卷的特定路徑。
PersistentVolume 刪除保護 Finalizer
Kubernetes v1.31 [beta]
(預設啟用:true)可以在 PersistentVolume 上新增 Finalizer,以確保具有 Delete
回收策略的 PersistentVolume 僅在後端儲存被刪除後才被刪除。
Finalizer external-provisioner.volume.kubernetes.io/finalizer
(在 v1.31 中引入) 會新增到動態佈建和靜態佈建的 CSI 卷。
Finalizer kubernetes.io/pv-controller
(在 v1.31 中引入) 會新增到動態佈建的內建外掛程式卷,並跳過靜態佈建的內建外掛程式卷。
以下是動態佈建的內建外掛程式卷的範例
kubectl describe pv pvc-74a498d6-3929-47e8-8c02-078c1ece4d78
Name: pvc-74a498d6-3929-47e8-8c02-078c1ece4d78
Labels: <none>
Annotations: kubernetes.io/createdby: vsphere-volume-dynamic-provisioner
pv.kubernetes.io/bound-by-controller: yes
pv.kubernetes.io/provisioned-by: kubernetes.io/vsphere-volume
Finalizers: [kubernetes.io/pv-protection kubernetes.io/pv-controller]
StorageClass: vcp-sc
Status: Bound
Claim: default/vcp-pvc-1
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 1Gi
Node Affinity: <none>
Message:
Source:
Type: vSphereVolume (a Persistent Disk resource in vSphere)
VolumePath: [vsanDatastore] d49c4a62-166f-ce12-c464-020077ba5d46/kubernetes-dynamic-pvc-74a498d6-3929-47e8-8c02-078c1ece4d78.vmdk
FSType: ext4
StoragePolicyName: vSAN Default Storage Policy
Events: <none>
Finalizer external-provisioner.volume.kubernetes.io/finalizer
會新增到 CSI 卷。以下是一個範例
Name: pvc-2f0bab97-85a8-4552-8044-eb8be45cf48d
Labels: <none>
Annotations: pv.kubernetes.io/provisioned-by: csi.vsphere.vmware.com
Finalizers: [kubernetes.io/pv-protection external-provisioner.volume.kubernetes.io/finalizer]
StorageClass: fast
Status: Bound
Claim: demo-app/nginx-logs
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 200Mi
Node Affinity: <none>
Message:
Source:
Type: CSI (a Container Storage Interface (CSI) volume source)
Driver: csi.vsphere.vmware.com
FSType: ext4
VolumeHandle: 44830fa8-79b4-406b-8b58-621ba25353fd
ReadOnly: false
VolumeAttributes: storage.kubernetes.io/csiProvisionerIdentity=1648442357185-8081-csi.vsphere.vmware.com
type=vSphere CNS Block Volume
Events: <none>
當針對特定的內建卷外掛程式啟用 CSIMigration{provider}
功能旗標時,kubernetes.io/pv-controller
finalizer 會被 external-provisioner.volume.kubernetes.io/finalizer
finalizer 取代。
Finalizer 確保 PV 物件僅在卷從儲存後端刪除後才被移除,前提是 PV 的回收策略為 Delete
。這也確保了無論 PV 和 PVC 的刪除順序如何,卷都會從儲存後端刪除。
保留 PersistentVolume
控制平面可以將 PersistentVolumeClaim 綁定到叢集中符合的 PersistentVolume。但是,如果您希望 PVC 綁定到特定的 PV,則需要預先綁定它們。
透過在 PersistentVolumeClaim 中指定 PersistentVolume,您可以宣告該特定 PV 和 PVC 之間的綁定。如果 PersistentVolume 存在且尚未透過其 claimRef
欄位保留 PersistentVolumeClaim,則 PersistentVolume 和 PersistentVolumeClaim 將被綁定。
綁定發生時,不論某些卷符合條件如何,包括節點親和性。控制平面仍然檢查儲存類別、存取模式和請求的儲存大小是否有效。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: foo-pvc
namespace: foo
spec:
storageClassName: "" # Empty string must be explicitly set otherwise default StorageClass will be set
volumeName: foo-pv
...
此方法不保證任何對 PersistentVolume 的綁定權限。如果其他 PersistentVolumeClaim 可以使用您指定的 PV,您首先需要保留該儲存卷。在 PV 的 claimRef
欄位中指定相關的 PersistentVolumeClaim,以便其他 PVC 無法綁定到它。
apiVersion: v1
kind: PersistentVolume
metadata:
name: foo-pv
spec:
storageClassName: ""
claimRef:
name: foo-pvc
namespace: foo
...
如果您想使用將其 persistentVolumeReclaimPolicy
設定為 Retain
的 PersistentVolume,包括您正在重複使用現有 PV 的情況,這非常有用。
擴展 PersistentVolumeClaim
Kubernetes v1.24 [stable]
預設啟用對擴展 PersistentVolumeClaim (PVC) 的支援。您可以擴展以下類型的卷
- azureFile (已棄用)
- csi
- flexVolume (已棄用)
- rbd (已棄用)
- portworxVolume (已棄用)
只有在其儲存類別的 allowVolumeExpansion
欄位設定為 true 時,您才能擴展 PVC。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: example-vol-default
provisioner: vendor-name.example/magicstorage
parameters:
resturl: "http://192.168.10.100:8080"
restuser: ""
secretNamespace: ""
secretName: ""
allowVolumeExpansion: true
若要為 PVC 請求更大的卷,請編輯 PVC 物件並指定更大的大小。這會觸發支援底層 PersistentVolume 的卷的擴展。永遠不會建立新的 PersistentVolume 來滿足請求。而是調整現有卷的大小。
警告
直接編輯 PersistentVolume 的大小可能會阻止自動調整該卷的大小。如果您編輯 PersistentVolume 的容量,然後編輯符合的 PersistentVolumeClaim 的.spec
以使 PersistentVolumeClaim 的大小與 PersistentVolume 相符,則不會發生儲存大小調整。Kubernetes 控制平面將看到兩個資源的期望狀態都符合,並得出結論,底層卷大小已手動增加,並且不需要調整大小。CSI 卷擴展
Kubernetes v1.24 [stable]
預設啟用對擴展 CSI 卷的支援,但它也需要特定的 CSI 驅動程式來支援卷擴展。有關更多資訊,請參閱特定 CSI 驅動程式的文件。
調整包含檔案系統的卷大小
只有當檔案系統是 XFS、Ext3 或 Ext4 時,您才能調整包含檔案系統的卷大小。
當卷包含檔案系統時,只有當新的 Pod 在 ReadWrite
模式下使用 PersistentVolumeClaim 時,才會調整檔案系統的大小。檔案系統擴展會在 Pod 啟動時或 Pod 正在執行且底層檔案系統支援線上擴展時完成。
如果驅動程式配置了 RequiresFSResize
功能為 true
,則 FlexVolume(自 Kubernetes v1.23 起已棄用)允許調整大小。FlexVolume 可以在 Pod 重新啟動時調整大小。
調整使用中 PersistentVolumeClaim 的大小
Kubernetes v1.24 [stable]
在這種情況下,您無需刪除並重新建立正在使用現有 PVC 的 Pod 或部署。任何使用中的 PVC 在其檔案系統擴展後,都會立即對其 Pod 可用。此功能對未被 Pod 或部署使用的 PVC 沒有影響。您必須建立使用 PVC 的 Pod,然後擴展才能完成。
與其他卷類型類似 - FlexVolume 卷也可以在使用中的 Pod 擴展。
注意
只有當底層驅動程式支援調整大小時,FlexVolume 才能調整大小。從擴展卷時的失敗中復原
如果使用者指定的新大小太大,無法被底層儲存系統滿足,則 PVC 的擴展將持續重試,直到使用者或叢集管理員採取某些動作。這可能是不希望發生的,因此 Kubernetes 提供了以下從此類失敗中復原的方法。
如果擴展底層儲存失敗,則叢集管理員可以手動復原 Persistent Volume Claim (PVC) 狀態並取消大小調整請求。否則,控制器將持續重試大小調整請求,而無需管理員介入。
- 將綁定到 PersistentVolumeClaim (PVC) 的 PersistentVolume (PV) 標記為
Retain
回收策略。 - 刪除 PVC。由於 PV 具有
Retain
回收策略 - 當我們重新建立 PVC 時,我們不會遺失任何資料。 - 從 PV 規範中刪除
claimRef
條目,以便新的 PVC 可以綁定到它。這應該使 PVAvailable
。 - 使用小於 PV 的大小重新建立 PVC,並將 PVC 的
volumeName
欄位設定為 PV 的名稱。這應該將新的 PVC 綁定到現有的 PV。 - 不要忘記還原 PV 的回收策略。
Kubernetes v1.23 [alpha]
(預設啟用:false)注意
使用者從失敗的 PVC 擴展中復原 (RecoverVolumeExpansionFailure
) 自 Kubernetes 1.32 起作為 Beta 功能提供,並且應該預設啟用。有關更多資訊,請參閱功能閘道文件。當使用 RecoverVolumeExpansionFailure
功能時,如果 PVC 的擴展失敗,您可以使用小於先前請求的值重試擴展。若要請求使用較小的建議大小進行新的擴展嘗試,請編輯該 PVC 的 .spec.resources
,並選擇小於您先前嘗試的值。如果由於容量限制而導致擴展到較高的值失敗,這非常有用。如果發生這種情況,或者您懷疑可能發生這種情況,您可以透過指定在底層儲存供應商的容量限制內的大小來重試擴展。您可以透過監看 PVC 上的 .status.allocatedResourceStatuses
和事件來監控大小調整操作的狀態。
請注意,雖然您可以指定小於先前請求的儲存量,但新值仍然必須高於 .status.capacity
。Kubernetes 不支援將 PVC 縮小到小於其目前大小。
Persistent Volume 的類型
PersistentVolume 類型以外掛程式的形式實作。Kubernetes 目前支援以下外掛程式
csi
- 容器儲存介面 (CSI)fc
- 光纖通道 (FC) 儲存hostPath
- HostPath 卷(僅用於單節點測試;在多節點叢集中將無法運作;請考慮改用local
卷)iscsi
- iSCSI (IP 上的 SCSI) 儲存local
- 掛載在節點上的本機儲存裝置。nfs
- 網路檔案系統 (NFS) 儲存
以下 PersistentVolume 類型已棄用但仍然可用。如果您正在使用這些卷類型,除了 flexVolume
、cephfs
和 rbd
之外,請安裝相應的 CSI 驅動程式。
awsElasticBlockStore
- AWS 彈性區塊儲存 (EBS) (從 v1.23 開始,預設啟用移轉)azureDisk
- Azure 磁碟 (從 v1.23 開始,預設啟用移轉)azureFile
- Azure 檔案 (從 v1.24 開始,預設啟用移轉)cinder
- Cinder (OpenStack 區塊儲存) (從 v1.21 開始,預設啟用移轉)flexVolume
- FlexVolume (從 v1.23 開始已棄用,沒有移轉計畫,也沒有移除支援的計畫)gcePersistentDisk
- GCE 永久磁碟 (從 v1.23 開始,預設啟用移轉)portworxVolume
- Portworx 卷 (從 v1.31 開始,預設啟用移轉)vsphereVolume
- vSphere VMDK 卷 (從 v1.25 開始,預設啟用移轉)
舊版本的 Kubernetes 也支援以下內建 PersistentVolume 類型
cephfs
(從 v1.31 開始不可用)flocker
- Flocker 儲存。(從 v1.25 開始不可用)photonPersistentDisk
- Photon 控制器永久磁碟。(從 v1.15 開始不可用)quobyte
- Quobyte 卷。(從 v1.25 開始不可用)rbd
- Rados 區塊裝置 (RBD) 卷 (從 v1.31 開始不可用)scaleIO
- ScaleIO 卷。(從 v1.21 開始不可用)storageos
- StorageOS 卷。(從 v1.25 開始不可用)
持久化卷
每個 PV 都包含 spec 和 status,分別是卷的規範和狀態。PersistentVolume 物件的名稱必須是有效的 DNS 子網域名稱。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2
注意
在叢集中使用 PersistentVolume 可能需要與卷類型相關的輔助程式。在此範例中,PersistentVolume 的類型為 NFS,並且需要輔助程式 /sbin/mount.nfs 來支援掛載 NFS 檔案系統。容量
通常,PV 將具有特定的儲存容量。這是使用 PV 的 capacity
屬性設定的,該屬性是 Quantity 值。
目前,儲存大小是唯一可以設定或請求的資源。未來的屬性可能包括 IOPS、輸送量等。
卷模式
Kubernetes v1.18 [stable]
Kubernetes 支援 PersistentVolume 的兩種 volumeModes
:Filesystem
和 Block
。
volumeMode
是一個可選的 API 參數。當省略 volumeMode
參數時,Filesystem
是使用的預設模式。
具有 volumeMode: Filesystem
的卷掛載到 Pod 中的目錄。如果卷由區塊裝置支援且裝置為空,則 Kubernetes 會在第一次掛載之前在裝置上建立檔案系統。
您可以將 volumeMode
的值設定為 Block
,以將卷用作原始區塊裝置。此類卷以區塊裝置的形式呈現到 Pod 中,而其上沒有任何檔案系統。此模式對於為 Pod 提供存取卷的最快方式非常有用,而 Pod 和卷之間沒有任何檔案系統層。另一方面,在 Pod 中執行的應用程式必須知道如何處理原始區塊裝置。請參閱 原始區塊卷支援,以取得如何在 Pod 中使用 volumeMode: Block
的卷的範例。
存取模式
PersistentVolume 可以以資源供應商支援的任何方式掛載在主機上。如下表所示,供應商將具有不同的功能,並且每個 PV 的存取模式都設定為該特定卷支援的特定模式。例如,NFS 可以支援多個讀/寫用戶端,但特定的 NFS PV 可能在伺服器上以唯讀方式匯出。每個 PV 都有自己的一組存取模式,用於描述該特定 PV 的功能。
存取模式為
ReadWriteOnce
- 卷可以由單一節點掛載為讀寫。當 Pod 在同一節點上執行時,ReadWriteOnce 存取模式仍然可以允許多個 Pod 存取卷。對於單一 Pod 存取,請參閱 ReadWriteOncePod。
ReadOnlyMany
- 卷可以由多個節點掛載為唯讀。
ReadWriteMany
- 卷可以由多個節點掛載為讀寫。
ReadWriteOncePod
- 功能狀態:卷可以由單一 Pod 掛載為讀寫。如果您想確保整個叢集中只有一個 Pod 可以讀取該 PVC 或寫入其中,請使用 ReadWriteOncePod 存取模式。
Kubernetes v1.29 [stable]
注意
ReadWriteOncePod
存取模式僅適用於 CSI 卷和 Kubernetes 版本 1.22+。若要使用此功能,您需要將以下 CSI sidecar 更新到這些版本或更高版本
在 CLI 中,存取模式縮寫為
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
- RWOP - ReadWriteOncePod
注意
Kubernetes 使用卷存取模式來匹配 PersistentVolumeClaim 和 PersistentVolume。在某些情況下,卷存取模式也會限制 PersistentVolume 可以掛載的位置。卷存取模式在儲存掛載後不會強制執行寫入保護。即使存取模式指定為 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany,它們也不會設定任何卷上的限制。例如,即使 PersistentVolume 建立為 ReadOnlyMany,也不能保證它將是唯讀的。如果存取模式指定為 ReadWriteOncePod,則卷受到限制,並且只能掛載在單一 Pod 上。重要! 即使卷支援多種存取模式,一次也只能使用一種存取模式掛載卷。
卷外掛程式 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany | ReadWriteOncePod |
---|---|---|---|---|
AzureFile | ✓ | ✓ | ✓ | - |
CephFS | ✓ | ✓ | ✓ | - |
CSI | 取決於驅動程式 | 取決於驅動程式 | 取決於驅動程式 | 取決於驅動程式 |
FC | ✓ | ✓ | - | - |
FlexVolume | ✓ | ✓ | 取決於驅動程式 | - |
HostPath | ✓ | - | - | - |
iSCSI | ✓ | ✓ | - | - |
NFS | ✓ | ✓ | ✓ | - |
RBD | ✓ | ✓ | - | - |
VsphereVolume | ✓ | - | - (當 Pod 共置時運作) | - |
PortworxVolume | ✓ | - | ✓ | - |
類別
PV 可以具有類別,該類別透過將 storageClassName
屬性設定為 StorageClass 的名稱來指定。特定類別的 PV 只能綁定到請求該類別的 PVC。沒有 storageClassName
的 PV 沒有類別,並且只能綁定到不請求特定類別的 PVC。
過去,註解 volume.beta.kubernetes.io/storage-class
用於代替 storageClassName
屬性。此註解仍然有效;但是,它將在未來的 Kubernetes 版本中完全棄用。
回收策略
目前的回收策略為
- Retain -- 手動回收
- Recycle -- 基本清除 (
rm -rf /thevolume/*
) - Delete -- 刪除卷
對於 Kubernetes 1.32,只有 nfs
和 hostPath
卷類型支援回收。
掛載選項
Kubernetes 管理員可以指定在節點上掛載 Persistent Volume 時的其他掛載選項。
注意
並非所有 Persistent Volume 類型都支援掛載選項。以下卷類型支援掛載選項
azureFile
cephfs
(在 v1.28 中已棄用)cinder
(在 v1.18 中已棄用)iscsi
nfs
rbd
(在 v1.28 中已棄用)vsphereVolume
掛載選項未經過驗證。如果掛載選項無效,則掛載將失敗。
過去,註解 volume.beta.kubernetes.io/mount-options
用於代替 mountOptions
屬性。此註解仍然有效;但是,它將在未來的 Kubernetes 版本中完全棄用。
節點親和性
注意
對於大多數卷類型,您不需要設定此欄位。您需要為 local 卷明確設定此欄位。PV 可以指定節點親和性,以定義限制可以從哪些節點存取此卷的限制。使用 PV 的 Pod 將僅排程到由節點親和性選取的節點。若要指定節點親和性,請在 PV 的 .spec
中設定 nodeAffinity
。PersistentVolume API 參考具有有關此欄位的更多詳細資訊。
階段
PersistentVolume 將處於以下階段之一
Available
- 尚未綁定到請求的空閒資源
Bound
- 卷已綁定到請求
Released
- 請求已被刪除,但關聯的儲存資源尚未被叢集回收
Failed
- 卷的(自動)回收失敗
您可以使用 kubectl describe persistentvolume <name>
查看綁定到 PV 的 PVC 名稱。
階段轉換時間戳記
Kubernetes v1.31 [stable]
(預設啟用:true)PersistentVolume 的 .status
欄位可以包含 Alpha lastPhaseTransitionTime
欄位。此欄位記錄卷上次轉換其階段的時間戳記。對於新建立的卷,階段設定為 Pending
,並且 lastPhaseTransitionTime
設定為目前時間。
PersistentVolumeClaim
每個 PVC 都包含 spec 和 status,分別是請求的規範和狀態。PersistentVolumeClaim 物件的名稱必須是有效的 DNS 子網域名稱。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
存取模式
請求在使用特定存取模式請求儲存時,使用與卷相同的慣例。
卷模式
請求使用與卷相同的慣例來指示卷是作為檔案系統還是區塊裝置使用。
資源
請求與 Pod 一樣,可以請求特定數量的資源。在這種情況下,請求是針對儲存空間。相同的資源模型適用於卷和請求。
選擇器
請求可以指定標籤選擇器,以進一步篩選卷的集合。只有標籤與選擇器匹配的卷才能綁定到請求。選擇器可以包含兩個欄位
matchLabels
- 卷必須具有帶有此值的標籤matchExpressions
- 透過指定鍵、值列表和將鍵和值相關聯的運算子所做的需求列表。有效的運算子包括 In、NotIn、Exists 和 DoesNotExist。
來自 matchLabels
和 matchExpressions
的所有需求都以 AND 方式組合在一起 - 它們都必須滿足才能匹配。
類別
請求可以透過使用屬性 storageClassName
指定 StorageClass 的名稱來請求特定的類別。只有請求類別的 PV,即具有與 PVC 相同的 storageClassName
的 PV,才能綁定到 PVC。
PVC 不一定需要請求類別。storageClassName
設定為 ""
的 PVC 始終被解釋為請求沒有類別的 PV,因此它只能綁定到沒有類別的 PV(沒有註解或設定為 ""
的註解)。沒有 storageClassName
的 PVC 並不完全相同,並且叢集對待它的方式不同,這取決於 DefaultStorageClass
准入外掛程式是否已開啟。
- 如果准入外掛程式已開啟,管理員可以指定預設的 StorageClass。所有沒有
storageClassName
的 PVC 只能綁定到該預設的 PV。指定預設 StorageClass 是透過在 StorageClass 物件中將註解storageclass.kubernetes.io/is-default-class
設定為true
來完成的。如果管理員未指定預設值,則叢集對 PVC 建立的回應就好像准入外掛程式已關閉一樣。如果指定了多個預設 StorageClass,則在動態佈建 PVC 時,將使用最新的預設值。 - 如果准入外掛程式已關閉,則沒有預設 StorageClass 的概念。所有將
storageClassName
設定為""
的 PVC 只能綁定到也將storageClassName
設定為""
的 PV。但是,一旦預設 StorageClass 可用,稍後可以更新遺失storageClassName
的 PVC。如果 PVC 得到更新,它將不再綁定到也將storageClassName
設定為""
的 PV。
有關更多詳細資訊,請參閱追溯預設 StorageClass 指派。
根據安裝方法,預設 StorageClass 可以在安裝期間由附加元件管理員部署到 Kubernetes 叢集。
當 PVC 除了請求 StorageClass
之外還指定了 selector
時,這些需求會以 AND 邏輯結合在一起:只有請求類別且帶有所請求標籤的 PV 才能繫結至 PVC。
注意
目前,具有非空selector
的 PVC 無法為其動態佈建 PV。過去,註釋 volume.beta.kubernetes.io/storage-class
是用來取代 storageClassName
屬性的。此註釋目前仍然有效;但是,在未來的 Kubernetes 版本中將不再支援。
追溯預設 StorageClass 指派
Kubernetes v1.28 [穩定]
您可以建立 PersistentVolumeClaim,而無需為新的 PVC 指定 storageClassName
,即使您的叢集中不存在預設的 StorageClass 也可以這樣做。在這種情況下,新的 PVC 會按照您的定義建立,並且該 PVC 的 storageClassName
會保持未設定狀態,直到預設值可用為止。
當預設的 StorageClass 可用時,控制平面會識別任何現有且沒有 storageClassName
的 PVC。對於 storageClassName
值為空或沒有此鍵的 PVC,控制平面接著會更新這些 PVC,以將 storageClassName
設定為與新的預設 StorageClass 相符。如果您有一個現有的 PVC,其 storageClassName
為 ""
,並且您設定了一個預設的 StorageClass,則此 PVC 將不會被更新。
為了保持繫結到 storageClassName
設定為 ""
的 PV(當預設 StorageClass 存在時),您需要將相關 PVC 的 storageClassName
設定為 ""
。
這種行為有助於管理員變更預設的 StorageClass,方法是先移除舊的 StorageClass,然後建立或設定另一個。在沒有預設 StorageClass 的這段短暫期間,那時建立的沒有 storageClassName
的 PVC 將不會有任何預設值,但由於追溯預設 StorageClass 指派,這種變更預設值的方式是安全的。
宣告作為卷
Pod 透過將宣告作為卷來存取儲存空間。宣告必須與使用該宣告的 Pod 存在於相同的命名空間中。叢集會在 Pod 的命名空間中找到該宣告,並使用它來取得支援該宣告的 PersistentVolume。然後,該卷會掛載到主機並進入 Pod 中。
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
關於命名空間的注意事項
PersistentVolume 繫結是獨佔的,而且由於 PersistentVolumeClaim 是命名空間物件,因此使用「多重」模式(ROX
、RWX
)掛載宣告僅在一個命名空間內才有可能。
類型為 hostPath
的 PersistentVolume
hostPath
PersistentVolume 使用節點上的檔案或目錄來模擬網路附加儲存空間。請參閱hostPath
類型卷的範例。
原始區塊卷支援
Kubernetes v1.18 [stable]
以下卷外掛程式支援原始區塊卷,包括在適用的情況下進行動態佈建
- CSI
- FC(光纖通道)
- iSCSI
- 本機卷
- OpenStack Cinder
- RBD(已棄用)
- RBD(Ceph 區塊裝置;已棄用)
- VsphereVolume
使用原始區塊卷的 PersistentVolume
apiVersion: v1
kind: PersistentVolume
metadata:
name: block-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
volumeMode: Block
persistentVolumeReclaimPolicy: Retain
fc:
targetWWNs: ["50060e801049cfd1"]
lun: 0
readOnly: false
請求原始區塊卷的 PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: block-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Block
resources:
requests:
storage: 10Gi
Pod 規格在容器中新增原始區塊裝置路徑
apiVersion: v1
kind: Pod
metadata:
name: pod-with-block-volume
spec:
containers:
- name: fc-container
image: fedora:26
command: ["/bin/sh", "-c"]
args: [ "tail -f /dev/null" ]
volumeDevices:
- name: data
devicePath: /dev/xvda
volumes:
- name: data
persistentVolumeClaim:
claimName: block-pvc
注意
當為 Pod 新增原始區塊裝置時,您需要在容器中指定裝置路徑,而不是掛載路徑。繫結區塊卷
如果使用者透過在 PersistentVolumeClaim 規格中使用 volumeMode
欄位來請求原始區塊卷,則繫結規則與先前未將此模式視為規格一部分的版本略有不同。下面列出的是使用者和管理員可能為請求原始區塊裝置指定的可能組合表格。該表格指出在給定組合的情況下,卷是否會被繫結:「靜態佈建卷的卷繫結矩陣」
PV volumeMode | PVC volumeMode | 結果 |
---|---|---|
未指定 | 未指定 | 繫結 |
未指定 | 區塊 | 不繫結 |
未指定 | 檔案系統 | 繫結 |
區塊 | 未指定 | 不繫結 |
區塊 | 區塊 | 繫結 |
區塊 | 檔案系統 | 不繫結 |
檔案系統 | 檔案系統 | 繫結 |
檔案系統 | 區塊 | 不繫結 |
檔案系統 | 未指定 | 繫結 |
注意
僅 alpha 版本支援靜態佈建卷。管理員在使用原始區塊裝置時應注意考量這些值。卷快照和從快照還原卷的支援
Kubernetes v1.20 [穩定]
卷快照僅支援樹狀結構外的 CSI 卷外掛程式。如需詳細資訊,請參閱卷快照。樹狀結構內卷外掛程式已被棄用。您可以在卷外掛程式常見問題解答中閱讀有關已棄用的卷外掛程式的資訊。
從卷快照建立 PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: restore-pvc
spec:
storageClassName: csi-hostpath-sc
dataSource:
name: new-snapshot-test
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
卷複製
卷複製僅適用於 CSI 卷外掛程式。
從現有的 PVC 建立 PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cloned-pvc
spec:
storageClassName: my-csi-plugin
dataSource:
name: existing-src-pvc-name
kind: PersistentVolumeClaim
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
卷填充程式和資料來源
Kubernetes v1.24 [beta]
Kubernetes 支援自訂卷填充程式。若要使用自訂卷填充程式,您必須為 kube-apiserver 和 kube-controller-manager 啟用 AnyVolumeDataSource
功能閘道。
卷填充程式利用名為 dataSourceRef
的 PVC 規格欄位。與 dataSource
欄位不同,後者只能包含對另一個 PersistentVolumeClaim 或 VolumeSnapshot 的參照,dataSourceRef
欄位可以包含對相同命名空間中任何物件的參照,但核心物件(PVC 除外)除外。對於已啟用功能閘道的叢集,建議使用 dataSourceRef
而不是 dataSource
。
跨命名空間資料來源
Kubernetes v1.26 [alpha]
Kubernetes 支援跨命名空間卷資料來源。若要使用跨命名空間卷資料來源,您必須為 kube-apiserver 和 kube-controller-manager 啟用 AnyVolumeDataSource
和 CrossNamespaceVolumeDataSource
功能閘道。此外,您還必須為 csi-provisioner 啟用 CrossNamespaceVolumeDataSource
功能閘道。
啟用 CrossNamespaceVolumeDataSource
功能閘道可讓您在 dataSourceRef 欄位中指定命名空間。
注意
當您為卷資料來源指定命名空間時,Kubernetes 會在接受參照之前檢查另一個命名空間中是否有 ReferenceGrant。ReferenceGrant 是gateway.networking.k8s.io
擴充 API 的一部分。如需詳細資訊,請參閱 Gateway API 文件中的 ReferenceGrant。這表示您必須使用 Gateway API 中的至少 ReferenceGrant 來擴充您的 Kubernetes 叢集,才能使用此機制。資料來源參照
dataSourceRef
欄位的行為幾乎與 dataSource
欄位相同。如果指定了其中一個欄位而未指定另一個欄位,則 API 伺服器會為這兩個欄位賦予相同的值。這兩個欄位在建立後都無法變更,並且嘗試為這兩個欄位指定不同的值將會導致驗證錯誤。因此,這兩個欄位將始終具有相同的內容。
使用者應注意 dataSourceRef
欄位和 dataSource
欄位之間存在兩個差異
dataSource
欄位會忽略無效值(如同該欄位為空白),而dataSourceRef
欄位永遠不會忽略值,並且如果使用無效值,則會導致錯誤。無效值是任何核心物件(沒有 apiGroup 的物件),但 PVC 除外。dataSourceRef
欄位可能包含不同類型的物件,而dataSource
欄位僅允許 PVC 和 VolumeSnapshot。
當啟用 CrossNamespaceVolumeDataSource
功能時,還存在其他差異
dataSource
欄位僅允許本機物件,而dataSourceRef
欄位允許任何命名空間中的物件。- 當指定命名空間時,
dataSource
和dataSourceRef
不會同步。
使用者應始終在已啟用功能閘道的叢集上使用 dataSourceRef
,並在未啟用功能閘道的叢集上回退到 dataSource
。在任何情況下都無需同時查看這兩個欄位。具有略微不同語義的重複值僅為了向後相容性而存在。特別是,較舊和較新的控制器混合使用能夠互通操作,因為這些欄位是相同的。
使用卷填充程式
卷填充程式是控制器,可以建立非空卷,其中卷的內容由自訂資源決定。使用者透過使用 dataSourceRef
欄位參照自訂資源來建立已填充的卷。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: populated-pvc
spec:
dataSourceRef:
name: example-name
kind: ExampleDataSource
apiGroup: example.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
因為卷填充程式是外部元件,如果未安裝所有正確的元件,則嘗試建立使用卷填充程式的 PVC 可能會失敗。外部控制器應在 PVC 上產生事件,以提供關於建立狀態的回饋,包括如果由於缺少某些元件而無法建立 PVC 時的警告。
您可以在叢集中安裝 alpha 卷資料來源驗證器 控制器。在未註冊任何填充程式來處理該類型的資料來源的情況下,該控制器會在 PVC 上產生警告事件。當為 PVC 安裝了合適的填充程式時,報告與卷建立以及過程中問題相關的事件是該填充程式控制器的責任。
使用跨命名空間卷資料來源
Kubernetes v1.26 [alpha]
建立 ReferenceGrant 以允許命名空間擁有者接受參照。您可以使用 dataSourceRef
欄位指定跨命名空間卷資料來源來定義已填充的卷。您必須在來源命名空間中已經有一個有效的 ReferenceGrant
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-ns1-pvc
namespace: default
spec:
from:
- group: ""
kind: PersistentVolumeClaim
namespace: ns1
to:
- group: snapshot.storage.k8s.io
kind: VolumeSnapshot
name: new-snapshot-demo
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: foo-pvc
namespace: ns1
spec:
storageClassName: example
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
dataSourceRef:
apiGroup: snapshot.storage.k8s.io
kind: VolumeSnapshot
name: new-snapshot-demo
namespace: default
volumeMode: Filesystem
撰寫可攜式組態
如果您正在撰寫可在各種叢集上執行並需要持久儲存的組態範本或範例,建議您使用以下模式
- 在您的組態套件中包含 PersistentVolumeClaim 物件(與 Deployments、ConfigMaps 等一起)。
- 請勿在組態中包含 PersistentVolume 物件,因為實例化組態的使用者可能沒有建立 PersistentVolume 的權限。
- 在實例化範本時,讓使用者可以選擇提供儲存類別名稱。
- 如果使用者提供儲存類別名稱,請將該值放入
persistentVolumeClaim.storageClassName
欄位中。如果叢集已由管理員啟用 StorageClass,這將使 PVC 與正確的儲存類別相符。 - 如果使用者未提供儲存類別名稱,請將
persistentVolumeClaim.storageClassName
欄位保留為 nil。這將導致為使用者自動佈建具有叢集中預設 StorageClass 的 PV。許多叢集環境都安裝了預設的 StorageClass,或者管理員可以建立自己的預設 StorageClass。
- 如果使用者提供儲存類別名稱,請將該值放入
- 在您的工具中,請監看一段時間後仍未繫結的 PVC,並將其呈現給使用者,因為這可能表示叢集沒有動態儲存支援(在這種情況下,使用者應建立相符的 PV)或叢集沒有儲存系統(在這種情況下,使用者無法部署需要 PVC 的組態)。
接下來是什麼
- 深入瞭解建立 PersistentVolume。
- 深入瞭解建立 PersistentVolumeClaim。
- 閱讀持久儲存設計文件。
API 參考資料
閱讀此頁面中描述的 API