持久卷
本文件介紹了 Kubernetes 中的**持久卷**。建議熟悉卷、StorageClasses和VolumeAttributesClasses。
介紹
管理儲存與管理計算例項是不同的問題。PersistentVolume 子系統為使用者和管理員提供了一個 API,用於抽象儲存的提供方式和消耗方式的細節。為此,我們引入了兩個新的 API 資源:PersistentVolume 和 PersistentVolumeClaim。
一個 **PersistentVolume** (PV) 是叢集中的一塊儲存,它由管理員配置,或使用StorageClass動態配置。它就像節點是叢集資源一樣,是叢集中的一種資源。PV 類似於卷外掛,但其生命週期獨立於使用該 PV 的任何單個 Pod。這個 API 物件捕獲了儲存實現的細節,無論是 NFS、iSCSI 還是雲提供商特定的儲存系統。
一個 **PersistentVolumeClaim** (PVC) 是使用者對儲存的請求。它類似於 Pod。Pod 消耗節點資源,而 PVC 消耗 PV 資源。Pod 可以請求特定級別的資源(CPU 和記憶體)。宣告可以請求特定大小和訪問模式(例如,它們可以以 ReadWriteOnce、ReadOnlyMany、ReadWriteMany 或 ReadWriteOncePod 方式掛載,參見訪問模式)。
雖然 PersistentVolumeClaims 允許使用者抽象地使用儲存資源,但使用者通常需要具有不同屬性(例如效能)的 PersistentVolumes 來解決不同的問題。叢集管理員需要能夠提供多種在大小和訪問模式之外存在差異的 PersistentVolumes,同時又不會向用戶暴露這些卷的具體實現細節。為了滿足這些需求,存在 **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,其中包含特定數量的儲存請求和某些訪問模式。控制平面中的一個控制迴圈監視新的 PVC,查詢匹配的 PV(如果可能),並將它們繫結在一起。如果為新的 PVC 動態配置了 PV,則該迴圈將始終將該 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 (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/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 刪除保護終結器
Kubernetes v1.33 [stable]
(預設啟用:true)可以在 PersistentVolume 上新增終結器,以確保具有 Delete
回收策略的 PersistentVolume 僅在後端儲存被刪除後才會被刪除。
終結器 external-provisioner.volume.kubernetes.io/finalizer
(v1.31 引入) 被新增到動態配置和靜態配置的 CSI 卷中。
終結器 `kubernetes.io/pv-controller` (v1.31 引入) 被新增到動態配置的 in-tree 外掛卷中,並跳過靜態配置的 in-tree 外掛卷。
以下是動態配置的 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>
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` 終結器將被 `external-provisioner.volume.kubernetes.io/finalizer` 終結器替換。
終結器確保僅在 PV 的回收策略為 `Delete` 的情況下,在卷從儲存後端刪除後才移除 PV 物件。這還確保無論 PV 和 PVC 的刪除順序如何,卷都會從儲存後端刪除。
預留 PersistentVolume
控制平面可以將PersistentVolumeClaims 繫結到叢集中匹配的 PersistentVolumes。但是,如果你希望 PVC 繫結到特定的 PV,你需要預先繫結它們。
透過在 PersistentVolumeClaim 中指定 PersistentVolume,你聲明瞭該特定 PV 和 PVC 之間的繫結。如果 PersistentVolume 存在且尚未透過其 claimRef
欄位預留 PersistentVolumeClaims,則 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 擁有任何繫結特權。如果其他 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 (PVC) 的支援預設啟用。你可以擴充套件以下型別的卷:
- csi(包括一些 CSI 遷移的卷型別)
- flexVolume (已棄用)
- 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 執行時且底層檔案系統支援線上擴充套件時完成。
FlexVolumes (自 Kubernetes v1.23 起已棄用) 允許調整大小,如果驅動程式配置了 `RequiresFSResize` 功能為 `true`。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 可以繫結到它。這應該使 PV 變為Available
狀態。 - 重新建立大小小於 PV 且其 `volumeName` 欄位設定為 PV 名稱的 PVC。這將把新的 PVC 繫結到現有的 PV。
- 別忘了恢復 PV 的回收策略。
如果 PVC 擴充套件失敗,你可以嘗試以小於之前請求值的大小再次擴充套件。要以更小的新建議大小重新嘗試擴充套件,請編輯該 PVC 的 `resources.spec` 並選擇一個小於你之前嘗試的值。這在由於容量限制導致擴充套件到更大值未成功時很有用。如果發生這種情況,或者你懷疑可能發生,你可以透過指定一個在底層儲存提供商容量限制範圍內的大小來重試擴充套件。你可以透過觀察 `status.allocatedResourceStatuses` 和 PVC 上的事件來監控調整大小操作的狀態。
請注意,儘管你可以指定低於先前請求的儲存量,但新值仍必須高於 .status.capacity
。Kubernetes 不支援將 PVC 縮小到小於其當前大小。
持久卷型別
PersistentVolume 型別以外掛形式實現。Kubernetes 目前支援以下外掛:
csi
- 容器儲存介面 (CSI)fc
- 光纖通道 (FC) 儲存hostPath
- HostPath 卷(僅用於單節點測試;在多節點叢集中將**不工作**;請考慮改用local
卷)iscsi
- iSCSI(透過 IP 的 SCSI)儲存local
- 掛載在節點上的本地儲存裝置。nfs
- 網路檔案系統 (NFS) 儲存
以下 PersistentVolume 型別已棄用但仍可用。如果你正在使用除 flexVolume
、cephfs
和 rbd
之外的這些卷型別,請安裝相應的 CSI 驅動程式。
awsElasticBlockStore
- AWS Elastic Block Store (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 起**不再可用**)glusterfs
- GlusterFS 儲存。(從 v1.26 起**不再可用**)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
- 該卷可以被單個節點以讀寫方式掛載。ReadWriteOnce 訪問模式仍允許多個 Pod 在同一節點上執行時訪問(讀或寫)該卷。對於單個 Pod 訪問,請參見 ReadWriteOncePod。
ReadOnlyMany
- 該卷可以被多個節點以只讀方式掛載。
ReadWriteMany
- 該卷可以被多個節點以讀寫方式掛載。
ReadWriteOncePod
- 特性狀態:該卷可以被單個 Pod 以讀寫方式掛載。如果你希望確保整個叢集中只有一個 Pod 可以讀取或寫入該 PVC,請使用 ReadWriteOncePod 訪問模式。
Kubernetes v1.29 [stable]
在 CLI 中,訪問模式被縮寫為:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
- RWOP - ReadWriteOncePod
注意
Kubernetes 使用卷訪問模式來匹配 PersistentVolumeClaims 和 PersistentVolumes。在某些情況下,卷訪問模式也限制了 PersistentVolume 可以掛載的位置。卷訪問模式**不**在儲存掛載後強制執行寫入保護。即使訪問模式指定為 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany,它們也不會對卷設定任何限制。例如,即使 PersistentVolume 建立為 ReadOnlyMany,也不能保證它是隻讀的。如果訪問模式指定為 ReadWriteOncePod,則該卷受到限制,只能掛載到單個 Pod 上。**重要提示!** 一個卷一次只能使用一種訪問模式掛載,即使它支援多種模式。
卷外掛 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany | ReadWriteOncePod |
---|---|---|---|---|
AzureFile | ✓ | ✓ | ✓ | - |
CephFS | ✓ | ✓ | ✓ | - |
CSI | 取決於驅動程式 | 取決於驅動程式 | 取決於驅動程式 | 取決於驅動程式 |
FC | ✓ | ✓ | - | - |
FlexVolume | ✓ | ✓ | 取決於驅動程式 | - |
HostPath | ✓ | - | - | - |
iSCSI | ✓ | ✓ | - | - |
NFS | ✓ | ✓ | ✓ | - |
RBD | ✓ | ✓ | - | - |
VsphereVolume | ✓ | - | - (當 Pods 位於同一位置時工作) | - |
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.34,只有 nfs
和 hostPath
卷型別支援回收。
掛載選項
Kubernetes 管理員可以指定當 Persistent Volume 掛載到節點時額外的掛載選項。
注意
並非所有 Persistent Volume 型別都支援掛載選項。以下卷型別支援掛載選項:
csi
(包括 CSI 遷移的卷型別)iSCSI
nfs
掛載選項不進行驗證。如果掛載選項無效,掛載將失敗。
過去,使用註解 `volume.beta.kubernetes.io/mount-options` 而不是 `mountOptions` 屬性。此註解仍然有效;但是,它將在未來的 Kubernetes 版本中完全棄用。
節點親和性
注意
對於大多數卷型別,你無需設定此欄位。對於本地卷,你需要明確設定此欄位。PV 可以指定節點親和性,以定義限制該卷可從哪些節點訪問的約束。使用 PV 的 Pod 只會被排程到由節點親和性選擇的節點上。要指定節點親和性,請在 PV 的 .spec
中設定 nodeAffinity
。有關此欄位的更多詳細資訊,請參閱PersistentVolume API 參考。
階段
PersistentVolume 將處於以下階段之一:
Available
- 一個未繫結到宣告的空閒資源
Bound
- 該卷已繫結到一個宣告
Released
- 該宣告已被刪除,但相關儲存資源尚未被叢集回收
Failed
- 卷的(自動)回收失敗
你可以使用 `kubectl describe persistentvolume
階段轉換時間戳
Kubernetes v1.31 [stable]
(預設啟用:true)PersistentVolume 的 .status
欄位可以包含一個 alpha 版的 lastPhaseTransitionTime
欄位。此欄位記錄了捲上次轉換其階段的時間戳。對於新建立的卷,階段設定為 Pending
,lastPhaseTransitionTime
設定為當前時間。
PersistentVolumeClaims
每個 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,則繫結將處於掛起狀態。
資源
宣告與 Pod 類似,可以請求特定數量的資源。在這種情況下,請求的是儲存。相同的資源模型適用於卷和宣告。
注意
對於 `Filesystem` 卷,儲存請求指的是“外部”卷大小(即,從儲存後端分配的大小)。這意味著對於在塊裝置上構建檔案系統的提供商,由於檔案系統開銷,可寫大小可能會略低。這在 XFS 上尤其明顯,其中許多元資料功能預設啟用。選擇器
宣告可以指定一個標籤選擇器來進一步過濾卷集。只有標籤與選擇器匹配的卷才能繫結到該宣告。選擇器可以包含兩個欄位:
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 都只能繫結到該預設 StorageClass 的 PV。透過在 StorageClass 物件中將註解storageclass.kubernetes.io/is-default-class
設定為true
來指定預設 StorageClass。如果管理員未指定預設值,叢集將像關閉准入外掛一樣響應 PVC 建立。如果指定了多個預設 StorageClass,則在動態配置 PVC 時使用最新的預設值。 - 如果准入外掛被關閉,則沒有預設 StorageClass 的概念。所有
storageClassName
設定為""
的 PVC 都只能繫結到storageClassName
也設定為""
的 PV。但是,缺少storageClassName
的 PVC 可以在預設 StorageClass 可用後進行更新。如果 PVC 被更新,它將不再繫結到storageClassName
也設定為""
的 PV。
請參閱追溯預設 StorageClass 分配瞭解更多詳情。
根據安裝方法,在安裝過程中,addon manager 可能會將預設 StorageClass 部署到 Kubernetes 叢集。
當 PVC 除了請求 StorageClass 外還指定了 selector
時,這些要求將進行 AND 運算:只有屬於所請求類且具有所請求標籤的 PV 才能繫結到 PVC。
注意
目前,帶有非空selector
的 PVC 無法為其動態配置 PV。過去,使用註解 volume.beta.kubernetes.io/storage-class
而不是 storageClassName
屬性。此註解仍然有效;但是,它將在未來的 Kubernetes 版本中不再支援。
追溯預設 StorageClass 分配
Kubernetes v1.28 [stable]
你可以在建立新的 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 的短暫時間內建立的 PVC 將沒有預設 StorageClass,但由於追溯預設 StorageClass 分配,這種更改預設 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
關於名稱空間的注意事項
PersistentVolumes 繫結是排他性的,並且由於 PersistentVolumeClaims 是名稱空間物件,因此以“多”模式(ROX
、RWX
)掛載宣告僅在一個名稱空間內是可能的。
HostPath 型別的 PersistentVolumes
hostPath
PersistentVolume 使用節點上的檔案或目錄來模擬網路附加儲存。請參閱hostPath
型別卷的示例。
裸塊卷支援
Kubernetes v1.18 [stable]
以下卷外掛支援裸塊卷,包括在適用的情況下進行動態配置:
- CSI (包括一些 CSI 遷移的卷型別)
- FC (光纖通道)
- iSCSI
- 本地卷
使用裸塊卷的 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 | 結果 |
---|---|---|
未指定 | 未指定 | 繫結 |
未指定 | Block | 不繫結 |
未指定 | Filesystem | 繫結 |
Block | 未指定 | 不繫結 |
Block | Block | 繫結 |
Block | Filesystem | 不繫結 |
Filesystem | Filesystem | 繫結 |
Filesystem | Block | 不繫結 |
Filesystem | 未指定 | 繫結 |
注意
僅靜態配置卷支援 alpha 版本。管理員在處理裸塊裝置時應注意這些值。卷快照和從快照恢復卷支援
Kubernetes v1.20 [stable]
卷快照僅支援樹外 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
特性門控。
卷填充器利用了 PVC 規範中的一個名為 dataSourceRef
的欄位。與只能包含對另一個 PersistentVolumeClaim 或 VolumeSnapshot 的引用的 dataSource
欄位不同,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
欄位絕不忽略值,如果使用無效值將導致錯誤。無效值是指除了 PVC 之外的任何核心物件(沒有 apiGroup 的物件)。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 物件(與 Deployment、ConfigMap 等一起)。
- 不要在配置中包含 PersistentVolume 物件,因為例項化配置的使用者可能沒有建立 PersistentVolumes 的許可權。
- 在例項化模板時,向用戶提供提供儲存類名稱的選項。
- 如果使用者提供了儲存類名稱,請將該值放入 `persistentVolumeClaim.storageClassName` 欄位中。如果叢集已由管理員啟用 StorageClasses,這將使 PVC 匹配正確的儲存類。
- 如果使用者未提供儲存類名稱,則將
persistentVolumeClaim.storageClassName
欄位留空。這將導致使用叢集中的預設 StorageClass 為使用者自動配置 PV。許多叢集環境都安裝了預設 StorageClass,或者管理員可以建立自己的預設 StorageClass。
- 在你的工具中,監視一段時間後仍未繫結的 PVC,並將此情況告知使用者,因為這可能表示叢集沒有動態儲存支援(在這種情況下,使用者應建立一個匹配的 PV)或叢集沒有儲存系統(在這種情況下,使用者無法部署需要 PVC 的配置)。
下一步
- 瞭解更多關於建立 PersistentVolume 的資訊。
- 瞭解更多關於建立 PersistentVolumeClaim 的資訊。
- 閱讀持久儲存設計文件。
API 參考
閱讀本頁描述的 API