本文檔描述 Kubernetes 中的永續性磁碟區 (Persistent Volumes)。建議您熟悉 磁碟區 (Volumes)、StorageClasses 和 VolumeAttributesClasses。
儲存管理與運算執行個體管理是兩個不同的問題。PersistentVolume 子系統為使用者和管理員提供了一個 API,將儲存如何提供與如何被消費的細節進行了抽象。為此,我們引入了兩個新的 API 資源:PersistentVolume 和 PersistentVolumeClaim。
PersistentVolume (PV) 是叢集中的一塊儲存空間,由管理員配置,或使用 Storage Classes 動態配置。它是叢集中的一種資源,就像節點 (Node) 是叢集資源一樣。PV 是像 Volumes 一樣的磁碟區外掛程式,但其生命週期獨立於任何使用該 PV 的個別 Pod。此 API 物件封裝了儲存實作的詳細資訊,無論是 NFS、iSCSI 還是特定雲端供應商的儲存系統。
PersistentVolumeClaim (PVC) 是使用者對儲存的請求。它類似於 Pod。Pod 消耗節點資源,而 PVC 消耗 PV 資源。Pod 可以請求特定層級的資源(CPU 和記憶體)。宣告 (Claim) 可以請求特定的儲存大小和存取模式(例如,可以掛載為 ReadWriteOnce、ReadOnlyMany、ReadWriteMany 或 ReadWriteOncePod,請參閱 存取模式)。
雖然 PersistentVolumeClaims 允許使用者消耗抽象的儲存資源,但使用者通常需要具備不同屬性(例如效能)的 PersistentVolumes 來解決不同的問題。叢集管理員需要能夠提供各種不同的 PersistentVolumes,且其差異不限於大小和存取模式,同時又不需向使用者揭露這些磁碟區是如何實作的。為滿足這些需求,提供了 StorageClass 資源。
請參閱 包含實作範例的詳細逐步指南。
PV 是叢集中的資源。PVC 是對這些資源的請求,也作為資源的宣告檢查。PV 與 PVC 之間的互動遵循此生命週期:
PV 有兩種配置方式:靜態或動態。
叢集管理員建立多個 PV。它們攜帶了真實儲存的詳細資訊,供叢集使用者使用。它們存在於 Kubernetes API 中並可供消費。
當管理員建立的靜態 PV 與使用者的 PersistentVolumeClaim 不符時,叢集可能會嘗試為該 PVC 特別動態配置一個磁碟區。此配置基於 StorageClasses:PVC 必須請求一個 storage class,且管理員必須已建立並配置該 class,才能進行動態配置。請求 class 為 "" 的宣告實際上會停用其自身的動態配置。
若要啟用基於 storage class 的動態儲存配置,叢集管理員需要在 API 伺服器上啟用 DefaultStorageClass 准入控制器 (Admission Controller)。例如,可以確保 DefaultStorageClass 包含在 API 伺服器元件的 --enable-admission-plugins 旗標的逗號分隔有序清單中。關於 API 伺服器命令列旗標的更多資訊,請查看 kube-apiserver 文件。
使用者建立(或在動態配置的情況下,系統已自動建立)一個 PersistentVolumeClaim,請求特定數量的儲存空間以及特定的存取模式。控制平面中的控制迴圈會監控新的 PVC,找到一個匹配的 PV(如果可能),並將它們綁定在一起。如果 PV 是為新的 PVC 動態配置的,控制迴圈將始終將該 PV 綁定到 PVC。否則,使用者將獲得至少滿足其要求的空間,但磁碟區的大小可能會超過請求的大小。一旦綁定,PersistentVolumeClaim 的綁定就是排他的,無論它們是如何綁定的。PVC 到 PV 的綁定是一種一對一的對應關係,使用 ClaimRef,這是在 PersistentVolume 和 PersistentVolumeClaim 之間的一種雙向綁定。
如果沒有匹配的磁碟區,宣告將無限期保持未綁定狀態。當匹配的磁碟區可用時,宣告將被綁定。例如,配置了許多 50Gi PV 的叢集將無法匹配請求 100Gi 的 PVC。當 100Gi PV 新增到叢集時,該 PVC 就可以被綁定。
Pod 將宣告作為磁碟區使用。叢集檢查宣告以找到綁定的磁碟區,並為 Pod 掛載該磁碟區。對於支援多種存取模式的磁碟區,使用者在 Pod 中將其宣告作為磁碟區使用時,會指定所需的模式。
一旦使用者擁有一個宣告且該宣告已被綁定,綁定的 PV 就歸使用者所有,直到他們不再需要為止。使用者透過在 Pod 的 volumes 區塊中包含 persistentVolumeClaim 部分來排程 Pod 並存取其宣告的 PV。更多詳細資訊,請參閱 作為磁碟區使用的宣告。
「儲存物件使用中保護」功能的目的是確保 Pod 正在主動使用的 PersistentVolumeClaims (PVCs) 以及綁定到 PVCs 的 PersistentVolume (PVs) 不會從系統中移除,因為這可能會導致資料遺失。
如果使用者刪除了一個正由 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 的回收政策 (Reclaim Policy) 告訴叢集在磁碟區宣告被釋放後該如何處理該磁碟區。目前,磁碟區可以被 Retain(保留)、Recycle(回收)或 Delete(刪除)。
Retain 回收政策允許手動回收資源。當 PersistentVolumeClaim 被刪除時,PersistentVolume 仍然存在,該磁碟區被視為「已釋放 (released)」。但它尚無法用於另一個宣告,因為先前使用者的資料仍保留在磁碟區上。管理員可以透過以下步驟手動回收磁碟區。
如果您想重複使用相同的儲存資產,請使用相同的儲存資產定義建立一個新的 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/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 部分指定的特定路徑會被替換為正在回收的磁碟區的特定路徑。
Kubernetes v1.33 [stable] (預設啟用)可以在 PersistentVolume 上新增終結器,以確保具有 Delete 回收政策的 PersistentVolume 僅在後端儲存被刪除後才被刪除。
終結器 external-provisioner.volume.kubernetes.io/finalizer(於 v1.31 引入)會新增至動態配置和靜態配置的 CSI 磁碟區。
終結器 kubernetes.io/pv-controller(於 v1.31 引入)會新增至動態配置的內建 (in-tree) 外掛程式磁碟區,而靜態配置的內建外掛程式磁碟區則會跳過此項。
以下是動態配置的內建外掛程式磁碟區範例:
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>
對於 CSI 磁碟區,會新增終結器 external-provisioner.volume.kubernetes.io/finalizer。以下是一個範例:
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 終結器會被 external-provisioner.volume.kubernetes.io/finalizer 終結器取代。
終結器確保僅在 PV 的回收政策為 Delete 且磁碟區已從儲存後端刪除後,PV 物件才會被移除。這也確保了無論 PV 和 PVC 的刪除順序如何,磁碟區都會從儲存後端刪除。
控制平面可以 將 PersistentVolumeClaims 綁定到叢集中匹配的 PersistentVolumes。但是,如果您希望 PVC 綁定到特定的 PV,則需要預先綁定它們。
透過在 PersistentVolumeClaim 中指定 PersistentVolume,您可以宣告該特定 PV 與 PVC 之間的綁定。如果 PersistentVolume 存在且未透過其 claimRef 欄位預留 PersistentVolumeClaims,則 PersistentVolume 和 PersistentVolumeClaim 將會被綁定。
無論某些磁碟區匹配條件(包括節點親和性)如何,綁定都會發生。控制平面仍會檢查 storage class、存取模式和請求的儲存大小是否有效。
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 的任何綁定特權。如果其他 PersistentVolumeClaims 可能會使用您指定的 PV,您首先需要預留該儲存磁碟區。在 PV 的 claimRef 欄位中指定相關的 PersistentVolumeClaim,這樣其他 PVC 就無法將其綁定。
apiVersion: v1
kind: PersistentVolume
metadata:
name: foo-pv
spec:
storageClassName: ""
claimRef:
name: foo-pvc
namespace: foo
...
如果您想使用 persistentVolumeReclaimPolicy 設定為 Retain 的 PersistentVolumes(包括重複使用現有 PV 的情況),此方法非常有用。
Kubernetes v1.24 [stable]預設情況下已啟用對擴充 PersistentVolumeClaims (PVCs) 的支援。您可以擴充以下類型的磁碟區:
只有在 PVC 的 storage class 的 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 來滿足該請求,而是調整現有磁碟區的大小。
.spec 以使大小相符,則不會發生儲存調整大小。Kubernetes 控制平面會發現這兩個資源的預期狀態相符,從而斷定底層磁碟區大小已被手動增加,且無需進一步調整。Kubernetes v1.24 [stable]預設情況下啟用對擴充 CSI 磁碟區的支援,但它也需要特定的 CSI 驅動程式支援磁碟區擴充。有關更多資訊,請參閱特定 CSI 驅動程式的文件。
只有當檔案系統為 XFS、Ext3 或 Ext4 時,您才能調整包含檔案系統的磁碟區大小。
當磁碟區包含檔案系統時,只有在新的 Pod 以 ReadWrite 模式使用 PersistentVolumeClaim 時,才會調整檔案系統大小。檔案系統擴充是在 Pod 啟動時執行,或者當 Pod 正在執行且底層檔案系統支援線上擴充時執行。
FlexVolumes(自 Kubernetes v1.23 起棄用)若驅動程式將 RequiresFSResize 能力設定為 true,則允許調整大小。FlexVolume 可以在 Pod 重啟時調整大小。
Kubernetes v1.24 [stable]在這種情況下,您不需要刪除並重新建立正在使用現有 PVC 的 Pod 或部署。任何使用中的 PVC 一旦檔案系統擴充完成,就會立即自動提供給其 Pod。此功能對於未由 Pod 或部署使用的 PVC 無效。您必須先建立一個使用該 PVC 的 Pod,擴充才能完成。
與其他磁碟區類型類似,FlexVolume 磁碟區也可以在 Pod 使用時進行擴充。
如果使用者指定的新大小太大,導致底層儲存系統無法滿足,PVC 的擴充將會持續重試,直到使用者或叢集管理員採取某些行動。這是不受歡迎的,因此 Kubernetes 提供了以下從此類失敗中恢復的方法。
如果擴充底層儲存失敗,叢集管理員可以手動恢復 Persistent Volume Claim (PVC) 狀態並取消調整大小請求。否則,調整大小請求將由控制器持續重試,而無需管理員干預。
Retain。Retain 回收政策,我們在重新建立 PVC 時不會遺失任何資料。claimRef 項目,以便新的 PVC 可以綁定到它。這應使 PV 狀態變為 Available。volumeName 欄位設定為 PV 的名稱。這應該會將新的 PVC 綁定到現有的 PV。如果 PVC 擴充失敗,您可以嘗試以小於先前請求值的較小大小重試擴充。若要以較小的建議大小請求新的擴充嘗試,請編輯該 PVC 的 .spec.resources 並選擇一個小於先前嘗試的值。如果擴充到較大值是因為容量限制而未成功,這很有用。如果發生這種情況,或者您懷疑可能發生這種情況,您可以透過指定在底層儲存供應商容量限制內的大小來重試擴充。您可以透過觀察 .status.allocatedResourceStatuses 以及 PVC 上的事件來監控調整大小操作的狀態。
請注意,雖然您可以指定小於先前請求的儲存量,但新值仍必須大於 .status.capacity。Kubernetes 不支援將 PVC 縮小至小於其當前大小。
PersistentVolume 類型作為外掛程式實作。Kubernetes 目前支援以下外掛程式:
csi - 容器儲存介面 (Container Storage Interface)fc - 光纖通道 (Fibre Channel, FC) 儲存hostPath - HostPath 磁碟區(僅用於單節點測試;在多節點叢集中將無法運作;建議改用 local 磁碟區)iscsi - iSCSI (SCSI over IP) 儲存local - 掛載在節點上的本地儲存裝置。nfs - 網路檔案系統 (Network File System, NFS) 儲存以下 PersistentVolume 類型已棄用,但仍可使用。如果您正在使用這些磁碟區類型(flexVolume、cephfs 和 rbd 除外),請安裝對應的 CSI 驅動程式。
awsElasticBlockStore - AWS Elastic Block Store (EBS)(自 v1.23 起預設開啟遷移)azureDisk - Azure Disk(自 v1.23 起預設開啟遷移)azureFile - Azure File(自 v1.24 起預設開啟遷移)cinder - Cinder (OpenStack 區塊儲存)(自 v1.21 起預設開啟遷移)flexVolume - FlexVolume(自 v1.23 起已棄用,無遷移計畫且無移除支援的計畫)gcePersistentDisk - GCE Persistent Disk(自 v1.23 起預設開啟遷移)portworxVolume - Portworx 磁碟區(自 v1.31 起預設開啟遷移)vsphereVolume - vSphere VMDK 磁碟區(自 v1.25 起預設開啟遷移)舊版 Kubernetes 也支援以下內建 PersistentVolume 類型:
cephfs(自 v1.31 起無法使用)flocker - Flocker 儲存。(自 v1.25 起無法使用)glusterfs - GlusterFS 儲存。(自 v1.26 起無法使用)photonPersistentDisk - Photon 控制器永久磁碟。(自 v1.15 起無法使用)quobyte - Quobyte 磁碟區。(自 v1.25 起無法使用)rbd - Rados Block Device (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
通常,PV 會有特定的儲存容量。這是使用 PV 的 capacity 屬性來設定的,該屬性是一個 Quantity (數值)。
目前,儲存空間大小是唯一可以設定或請求的資源。未來的屬性可能包括 IOPS、傳輸量等。
Kubernetes v1.18 [穩定]Kubernetes 支援 PersistentVolumes 的兩種 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 的功能。
存取模式包括:
ReadWriteOnceReadOnlyManyReadWriteManyReadWriteOncePodKubernetes v1.29 [穩定]ReadWriteOncePod 存取模式僅支援 CSI 磁碟區以及 Kubernetes 1.22+ 版本。若要使用此功能,您需要將以下 CSI sidecars 更新至這些版本或更高版本:
在 CLI 中,存取模式縮寫為:
重要! 磁碟區一次只能以一種存取模式掛載,即使它支援多種模式。
| 磁碟區外掛程式 | 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 版本中完全棄用。
目前的回收政策為:
rm -rf /thevolume/*)對於 Kubernetes 1.36,只有 nfs 和 hostPath 磁碟區類型支援回收 (Recycle)。
Kubernetes 管理員可以指定額外的掛載選項,以便在節點上掛載永續性磁碟區時使用。
以下磁碟區類型支援掛載選項:
csi(包含已遷移的 CSI 磁碟區類型)iscsinfs掛載選項不會經過驗證。如果掛載選項無效,掛載將失敗。
過去,使用註釋 volume.beta.kubernetes.io/mount-options 而不是 mountOptions 屬性。該註釋仍然有效;但是,它將在未來的 Kubernetes 版本中完全棄用。
PV 可以指定節點親和性來定義約束,限制此磁碟區可以從哪些節點存取。使用 PV 的 Pod 將只會排程到由節點親和性選定的節點上。若要指定節點親和性,請在 PV 的 .spec 中設定 nodeAffinity。PersistentVolume API 參考有關於此欄位的更多詳細資訊。
Kubernetes v1.35 [alpha 版](預設禁用)如果您的叢集中啟用了 MutablePVNodeAffinity 功能旗標,則 PersistentVolume 的 .spec.nodeAffinity 欄位是可變的。這允許叢集管理員或外部儲存控制器在資料遷移時更新 PersistentVolume 的節點親和性,而不會中斷正在執行的 Pod。
更新節點親和性時,您應該確保新的節點親和性仍然與磁碟區目前使用的節點相符。對於違反新親和性的 Pod,如果 Pod 已經在執行中,它可能會繼續執行。但 Kubernetes 不支援此種設定。您應該儘速終止這些違規的 Pod。由於記憶體快取的原因,在更新後建立的 Pod 可能會在短時間內仍然根據舊的節點親和性進行排程。
若要使用此功能,您應該在以下元件上啟用 MutablePVNodeAffinity 功能旗標:
kube-apiserverkubeletPersistentVolume 將處於以下階段 (phase) 之一:
Available (可用)Bound (綁定)Released (釋放)Failed (失敗)您可以使用 kubectl describe persistentvolume <name> 查看綁定到 PV 的 PVC 名稱。
Kubernetes v1.31 [穩定版](預設啟用)PersistentVolume 的 .status 欄位可以包含一個 alpha 階段的 lastPhaseTransitionTime 欄位。此欄位記錄了磁碟區最後一次轉換階段的時間戳記。對於新建立的磁碟區,階段被設定為 Pending,且 lastPhaseTransitionTime 被設定為當前時間。
每個 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]}
宣告在請求具有特定存取模式的儲存時,使用 與磁碟區相同的慣例。
宣告使用 與磁碟區相同的慣例 來指明將磁碟區作為檔案系統或區塊裝置進行消費。
宣告可以使用 volumeName 欄位明確綁定到特定的 PersistentVolume。您也可以將 volumeName 留空,這表示您希望 Kubernetes 建立一個與該宣告匹配的新 PersistentVolume。如果指定的 PV 已綁定到另一個 PVC,則綁定將卡在待處理 (pending) 狀態。
與 Pod 一樣,宣告可以請求特定數量的資源。在此情況下,請求的是儲存空間。相同的 資源模型 同樣適用於磁碟區和宣告。
Filesystem 磁碟區,儲存請求指的是「外部」磁碟區大小(即從儲存後端分配的大小)。這意味著對於在區塊裝置之上建立檔案系統的提供者來說,可寫入大小可能略小,這是因為檔案系統開銷所致。這在使用 XFS 時特別明顯,因為預設啟用了許多中繼資料功能。宣告可以使用 標籤選擇器 (label selector) 來進一步篩選磁碟區集。只有標籤與選擇器匹配的磁碟區才能綁定到該宣告。選擇器可以包含兩個欄位:
matchLabels - 磁碟區必須具有包含此值的標籤matchExpressions - 一系列需求清單,透過指定 key、值清單以及關聯 key 和值的運算子來建立。有效的運算子包括 In、NotIn、Exists 和 DoesNotExist。所有來自 matchLabels 和 matchExpressions 的需求都必須同時滿足 (AND) – 它們必須全部滿足才能匹配。
宣告可以透過使用 storageClassName 屬性指定 StorageClass 的名稱來請求特定類別。只有請求類別的 PV(即與 PVC 具有相同 storageClassName 的 PV)才能綁定到該 PVC。
PVC 不一定必須請求類別。將 storageClassName 設定為 "" 的 PVC 總是會被解釋為請求一個沒有類別的 PV,因此它只能綁定到沒有類別的 PV(沒有註釋或設定為 "")。沒有 storageClassName 的 PVC 則不完全相同,叢集對其處理方式取決於是否開啟了 DefaultStorageClass 准入外掛程式。
storageClassName 的 PVC 只能綁定到該預設的 PV。指定預設 StorageClass 的方式是在 StorageClass 物件中將註釋 storageclass.kubernetes.io/is-default-class 設定為 true。如果管理員未指定預設值,叢集對 PVC 建立的響應將如同准入外掛程式已關閉一樣。如果指定了多個預設 StorageClass,則在動態配置 PVC 時將使用最新的預設值。storageClassName 設定為 "" 的 PVC 只能綁定到同樣將 storageClassName 設定為 "" 的 PV。但是,缺少 storageClassName 的 PVC 可以在預設 StorageClass 可用後進行更新。如果 PVC 獲得了更新,它將不再綁定到同樣將 storageClassName 設定為 "" 的 PV。有關更多詳細資訊,請參閱 追溯預設 StorageClass 分配。
根據安裝方法,預設 StorageClass 可能會在安裝期間由附加元件管理員部署到 Kubernetes 叢集中。
當 PVC 在請求 StorageClass 的同時指定了 selector,這些要求會同時生效 (AND):只有請求該類別且具有所請求標籤的 PV 才能綁定到該 PVC。
selector 的 PVC 無法動態配置 PV。過去,使用註釋 volume.beta.kubernetes.io/storage-class 而不是 storageClassName 屬性。該註釋仍然有效;但是,它將在未來的 Kubernetes 版本中不被支援。
Kubernetes v1.28 [stable]您可以建立 PersistentVolumeClaim 而不為新的 PVC 指定 storageClassName,即使您的叢集中沒有預設 StorageClass,也可以這樣做。在這種情況下,新的 PVC 會按您定義的方式建立,並且在預設 StorageClass 可用之前,該 PVC 的 storageClassName 將保持未設定狀態。
當預設 StorageClass 可用時,控制平面會識別任何沒有 storageClassName 的現有 PVC。對於 storageClassName 為空值或沒有此索引鍵的 PVC,控制平面隨後會更新這些 PVC,將 storageClassName 設定為匹配新的預設 StorageClass。如果您有一個現有的 PVC 且其 storageClassName 為 "",並且您配置了預設 StorageClass,則該 PVC 將不會獲得更新。
為了保持與 storageClassName 設定為 "" 的 PV 綁定(同時存在預設 StorageClass),您需要將關聯 PVC 的 storageClassName 設定為 ""。
此行為有助於管理員透過先刪除舊的 StorageClass,然後再建立或設定另一個來變更預設 StorageClass。在沒有預設值的短暫視窗期間,當時建立的沒有 storageClassName 的 PVC 將不會有任何預設值,但由於追溯預設 StorageClass 分配,這種變更預設值的方式是安全的。
Kubernetes v1.36 [alpha] (預設停用)啟用後,PVC 保護控制器會將 Unused 條件 (condition) 新增至每個 PersistentVolumeClaim,以指示它目前是否被任何非終止狀態 (non-terminal) 的 Pod 所參照。
該條件有兩種狀態:
Unused 狀態為 "True" (原因 NoPodsUsingPVC)lastTransitionTime 記錄了 PVC 變為未使用的時間。Unused 狀態為 "False" (原因 PodUsingPVC)lastTransitionTime 記錄了 PVC 開始被使用的時間。如果 Pod 的階段不為 Succeeded 或 Failed,則被視為非終止狀態。這意味著 Pending 狀態的 Pod(即使尚未排程的 Pod)也計算為正在使用該 PVC。
Unused 條件的 lastTransitionTime 可供叢集管理員、監控工具和外部控制器使用,以識別長期未使用的 PVC。例如,要尋找所有已超過 30 天未使用的 PVC,您可以查詢 Unused 條件狀態為 "True" 且 lastTransitionTime 早於 30 天的 PVC。
deletionTimestamp(即正在刪除的 PVC)時,該條件不會更新。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
PersistentVolumes 的綁定是排他的,且由於 PersistentVolumeClaims 是命名空間物件,因此掛載「多」模式(ROX, RWX)的宣告只能在同一個命名空間內進行。
hostPath 的 PersistentVolumeshostPath PersistentVolume 使用節點上的檔案或目錄來模擬網路附加儲存。請參閱 hostPath 型別磁碟區的範例。
Kubernetes v1.18 [穩定]以下磁碟區外掛程式支援原始區塊磁碟區,包括適用時的動態配置:
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
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: block-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Block
resources:
requests:
storage: 10Gi
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
如果使用者透過指示 PersistentVolumeClaim 規格中的 volumeMode 欄位來請求原始區塊磁碟區,其綁定規則會與之前不考慮此模式作為規格一部分的發行版本略有不同。下表列出了使用者和管理員在請求原始區塊裝置時可能指定的組合。表格指示了給定組合下磁碟區是否會被綁定:靜態配置磁碟區的磁碟區綁定矩陣
| PV volumeMode | PVC volumeMode | 結果 |
|---|---|---|
| 未指定 | 未指定 | 綁定 |
| 未指定 | Block (區塊) | 不綁定 |
| 未指定 | Filesystem (檔案系統) | 綁定 |
| Block (區塊) | 未指定 | 不綁定 |
| Block (區塊) | Block (區塊) | 綁定 |
| Block (區塊) | Filesystem (檔案系統) | 不綁定 |
| Filesystem (檔案系統) | Filesystem (檔案系統) | 綁定 |
| Filesystem (檔案系統) | Block (區塊) | 不綁定 |
| Filesystem (檔案系統) | 未指定 | 綁定 |
Kubernetes v1.20 [穩定]磁碟區快照僅支援外部 CSI 磁碟區外掛程式。詳細資訊請參閱 磁碟區快照。內建磁碟區外掛程式已棄用。您可以閱讀 磁碟區外掛程式常見問題解答 以瞭解有關棄用的磁碟區外掛程式資訊。
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 磁碟區外掛程式。
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 規格欄位。與只能包含對另一個 PersistentVolumeClaim 或 VolumeSnapshot 參照的 dataSource 欄位不同,dataSourceRef 欄位可以包含對同一命名空間中任何物件的參照(除了核心物件外的 PVC)。對於已啟用該功能旗標的叢集,建議使用 dataSourceRef 而非 dataSource。
Kubernetes v1.26 [Alpha]Kubernetes 支援跨命名空間磁碟區資料來源。若要使用跨命名空間磁碟區資料來源,您必須為 kube-apiserver 和 kube-controller-manager 啟用 AnyVolumeDataSource 和 CrossNamespaceVolumeDataSource 功能旗標。此外,您必須為 csi-provisioner 啟用 CrossNamespaceVolumeDataSource 功能旗標。
啟用 CrossNamespaceVolumeDataSource 功能旗標允許您在 dataSourceRef 欄位中指定命名空間。
gateway.networking.k8s.io 擴充 API 的一部分。詳情請參閱 Gateway API 文件中的 ReferenceGrant。這意味著在您使用此機制之前,必須使用 Gateway API 的 ReferenceGrant 至少擴充您的 Kubernetes 叢集。dataSourceRef 欄位的行為幾乎與 dataSource 欄位相同。如果指定了其中一個而未指定另一個,API 伺服器會將相同的值賦予兩個欄位。建立後這兩個欄位均無法變更,且嘗試為這兩個欄位指定不同的值將導致驗證錯誤。因此,這兩個欄位的內容將始終相同。
dataSourceRef 欄位與 dataSource 欄位之間有兩點差異,使用者應注意:
dataSource 欄位會忽略無效值(如同該欄位為空白一樣),而 dataSourceRef 欄位永不忽略值,且若使用了無效值則會導致錯誤。無效值是指除了 PVC 以外的任何核心物件(沒有 apiGroup 的物件)。dataSourceRef 欄位可能包含不同類型的物件,而 dataSource 欄位僅允許 PVC 和 VolumeSnapshots。當啟用了 CrossNamespaceVolumeDataSource 功能時,存在額外的差異:
dataSource 欄位僅允許本地物件,而 dataSourceRef 欄位允許任何命名空間中的物件。dataSource 和 dataSourceRef 不會同步。使用者應始終在啟用了該功能旗標的叢集上使用 dataSourceRef,並在未啟用的叢集上回退使用 dataSource。在任何情況下都不需要查看這兩個欄位。具有不同語意的重複值僅為了向後相容性而存在。特別是,較舊與較新的控制器混合使用是可以互通的,因為欄位是相同的。
磁碟區填充器是 控制器,它們可以建立非空磁碟區,其中磁碟區內容由自訂資源 (Custom Resource) 決定。使用者透過使用 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.storageClassName 欄位中。如果叢集由管理員啟用 StorageClasses,這將導致 PVC 匹配正確的儲存類別。persistentVolumeClaim.storageClassName 欄位留為 nil。這將導致 PV 自動為使用者配置叢集中的預設 StorageClass。許多叢集環境都安裝了預設 StorageClass,或者管理員可以建立自己的預設 StorageClass。閱讀關於本頁面描述的 API: