- 1. PersistentVolume(PV)簡介
- 2. PersistentVolume(PV)的分類
- 3. PersistentVolumeClaim(PVC)的保護
- 4. PersistentVolume(PV)支持的底層存儲類型
- 5. PersistentVolume(PV)的資源清單
- 6. PersistentVolume(PV)的狀態
- 7. 實驗-持久化演示說明-NFS
- 8. 關於 Statefulset
1. PersistentVolume(PV)簡介
1.1 為什么需要Persistent Volume(PV)
在講PersistentVolume(PV)之前,我們需要先講一下Volume
Volume詳情可見上一章: kubernetes系列(十三) - 存儲之Volume
Volume是被定義在pod上的(emptyDir或者hostPath),屬於計算資源的一部分。所以Volume是有局限性的,因為在實際的運用過程中,我們通常會先定義一個網絡存儲,然后從中划出一個網盤並掛接到虛擬機上。
為了屏蔽底層存儲實現的細節,讓用戶方便使用,同時讓管理員方便管理。Kubernetes從V1.0版本就引入了PersistentVolume(PV)和與之相關聯的PersistentVolumeClaim(PVC)兩個資源對象來實現對存儲的管理
1.2 PersistentVolume(PV)和Volume的區別
PV可以被理解成kubernetes集群中的某個網絡存儲對應的一塊存儲,它與Volume類似,但是有如下的區別:
- PV只能是網絡存儲,不屬於任何
Node,但是可以在每個Node上訪問 - PV不是被定義在pod上,而是獨立在pod之外被定義的。
- 意味着
pod被刪除了,PV仍然存在,這點與Volume不同
- 意味着
1.3 PV和PVC更具體的概念和關系
1.3.1 PersistentVolume(PV)
PersistentVolume(PV)是由管理員設置的存儲,它是群集的一部分。就像節點是集群中的資源一樣,PV也是集群中的資源。PV是Volume之類的卷插件,但具有獨立於使用PV的Pod的生命周期。此API對象包含存儲實現的細節,即NFS、iSCSl或特定於雲供應商的存儲系統。
1.3.2 PersistentVolumeClaim(PVC)
PersistentVolumeClaim(PVC)是用戶存儲的請求。它與Pod相似。Pod消耗節點資源,PVC消耗PV資源。Pod可以請求特定級別的資源(CPU和內存)。聲明可以請求特定的大小和訪問模式(例如,可以以讀/寫一次或只讀多次模式掛載)
1.3.3 PV和PVC的關系和圖解
pvc是一種pv的請求方案,PVC定義我當前需要什么樣類型的PV,然后會自動在當前存在的pv中選取一個匹配度最高的pv
一個PVC只能綁定一個PV!!

2. PersistentVolume(PV)的分類
2.1 靜態PV
簡單來說
由集群管理員手動創建的一些PV
完整的概念
集群管理員創建一些PV。它們帶有可供群集用戶使用的實際存儲的細節。它們存在於KubernetesAPl中,可用於消費。
2.2 動態PV
簡單來說
配置了允許動態PV的策略后,如果當前存在的PV無法滿足PVC的要求,則會動態創建PV.
動態PV了解即可
完整的概念
當管理員創建的靜態PV都不匹配用戶的PersistentVolumeClaim時,集群可能會嘗試動態地為PVC創建卷。此配置基於StorageClasses,所以要啟用基於存儲級別的動態存儲配置要求:
- PVC必須請求
StorageClasses - 管理員必須創建並配置
StorageClasses才能進行動態創建 - 聲明該類為“”可以有效地禁用其動態配置
- 集群管理員需要啟用
API server上的DefaultStorageClass[准入控制器]。例如,通過確保DefaultStorageClass位於API server組件的--admission-control標志,使用逗號分隔的有序值列表中,可以完成此操作
3. PersistentVolumeClaim(PVC)的保護
PVC保護的目的是確保由pod正在使用的PVC不會從系統中移除,因為如果被移除的話可能會導致數據丟失 當啟用PVC保護alpha功能時,如果用戶刪除了一個pod正在使用的PVC,則該PVC不會被立即刪除。PVC的刪除將被推遲,直到PVC不再被任何 pod使用
4. PersistentVolume(PV)支持的底層存儲類型
PersistentVolume類型以插件形式實現. kubernetes目前支持以下類型(排名不分先后):
跟上一集中的volume支持的類型差不多
GCEPersistentDiskAWSElasticBlockStoreAzureFileAzureDiskFC(Fibre Channel)FlexVolumeFlockerNFSiSCSIRBD(Ceph Block Device)CephFSCinder(OpenStack block storage)GlusterfsVsphereVolumeQuobyteVolumesHostPathVMwarePhotonPortworx VolumesScalelo VolumesStorageOS
5. PersistentVolume(PV)的資源清單
5.1 資源清單示例
apiVersion: v1
kind: PersistentVolume
metadata:
name:pve003
spec:
capacity:
# 卷的大小為5G
storage: 5Gi
# 存儲卷的類型為:文件系統
volumeMode: Filesystem
# 訪問策略:該卷可以被單個節點以讀/寫模式掛載
accessModes:
- ReadNriteOnce
# 回收策略:回收
persistentVolumeReclaimPolicy: Recycle
# 對應的具體底層存儲的分級
# 比如有些固態或者其他存儲類型比較快,就可以定義為strong
storageClassName: slow
# (可選的)掛載選項
mountOptions:
- hard
- nfsvers=4.1
# 具體對應的真實底層存儲類型為nfs
# 掛載到172服務器下的/tmp目錄
nfs:
path: /tmp
server: 172.17.0.2
5.2 PV的訪問模式(spec.accessModes)
5.2.1 三種訪問模式
訪問模式accessModes一共有三種:
ReadWriteOnce: 該卷可以被單個節點以讀/寫模式掛載ReadOnlyMany: 該卷可以被多個節點以只讀模式掛載ReadWriteMany: 該卷可以被多個節點以讀/寫模式掛載
在命令行cli中,三種訪問模式可以簡寫為:
RWO-ReadWriteOnceROX-ReadOnlyManyRWX-ReadWriteMany
但不是所有的類型的底層存儲都支持以上三種,每種底層存儲類型支持的都不一樣!!
5.2.2 各種底層存儲具體支持的訪問模式
| Volume Plugin | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
|---|---|---|---|
| AWSElasticBlockStore | ✓ | - | - |
| AzureFile | ✓ | ✓ | ✓ |
| AzureDisk | ✓ | - | - |
| CephFS | ✓ | ✓ | ✓ |
| Cinder | ✓ | - | - |
| FC | ✓ | ✓ | - |
| FlexVolume | ✓ | ✓ | - |
| Flocker | ✓ | - | - |
| GCEPersistentDisk | ✓ | ✓ | - |
| Glusterfs | ✓ | ✓ | ✓ |
| HostPath | ✓ | - | - |
| iSCSI | ✓ | ✓ | - |
| PhotonPersistentDisk | ✓ | - | - |
| Quobyte | ✓ | ✓ | ✓ |
| NFS | ✓ | ✓ | ✓ |
| RBD | ✓ | ✓ | - |
| VsphereVolume | ✓ | - | - |
| PortworxVolume | ✓ | - | ✓ |
| ScaleIO | ✓ | ✓ | - |
5.3 PV的回收策略(spec.persistentVolumeReclaimPolicy)
5.3.1 回收策略的三種策略
Retain(保留): pv被刪除后會保留內存,手動回收Recycle(回收): 刪除卷下的所有內容(rm-rf /thevolume/*)Delete(刪除): 關聯的存儲資產(例如AWS EBS、GCE PD、Azure Disk 和OpenStack Cinder卷)將被刪除。即直接把卷給刪除了
5.3.2 回收策略注意事項
- 當前,只有
NFS和HostPath支持Recycle回收策略
最新版本中的
Recycle已被廢棄,截圖如下
附:具體官網文檔詳細說明鏈接點擊此處

- AWS EBS、GCE PD、Azure Disk 和Cinder 卷支持
Delete刪除策略
6. PersistentVolume(PV)的狀態
PV可以處於以下的某種狀態:
Available(可用): 塊空閑資源還沒有被任何聲明綁定Bound(已綁定): 卷已經被聲明綁定, 注意:但是不一定不能繼續被綁定,看accessModes而定Released(已釋放): 聲明被刪除,但是資源還未被集群重新聲明Failed(失敗): 該卷的自動回收失敗
命令行會顯示綁定到PV的PVC的名稱
7. 實驗-持久化演示說明-NFS
注:以下內容筆者沒有實際嘗試過,僅做記錄使用
7.1 安裝NFS服務器
yum install -y nfs-common nfs-utils rpcbind
mkdir /nfsdata
chmod 777 /nfsdata
chown nfsnobody /nfsdata
cat /etc/exports /nfsdata *(rw,no_root_squash,no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs
7.2 在其他節點上安裝客戶端
yum -y install nfs-utils rpcbind
mkdir /test
showmount -e 192.168.66.100
mount -t nfs 192.168.66.100:/nfsdata /test/
cd /test/
ls
umount /test/
7.3 部署PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv1
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata
server: 192.168.66.100
7.4 創建服務並使用PVC
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
8. 關於 Statefulset
StatefulSet為每個Pod副本創建了一個DNS域名,這個域名的格式為:S(podname).(headless servername)
也就意味着服務間是通過Pod域名來通信而非PodIP,因為當Pod所在Node發生故障時,Pod會被飄移到其它 Node上,PodIP會發生變化,但是Pod域名不會有變化
StatefulSet使用Headless服務來控制Pod的域名,這個域名的FQDN為:S(servicename).$(namespace).svc.cluster.local
其中,“cluster.local”指的是集群的域名
- 根據
volumeClaimTemplates,為每個Pod 創建一個pvo,pvc的命名規則匹配模式:
(volumeClaimTemplates.name)-(pod_name)
比如上面的
volumeMounts.name=www,Podname-web-[0-2],因此創建出來的PVC是www-web-0、www-web-1、 www-web-2
- 刪除 Pod 不會刪除其pvc,手動刪除 pvc將自動釋放pv
- Statefulset的啟停順序:
- 有序部署:部罷Statefulset時,如果有多個Pod副本,它們會被順序地創建(從0到N-1)並且,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態。
- 有序刪除:當Pod被刪除時,它們被終止的順序是從N-1到0。
- 有序擴展:當對Pod執行擴展操作時,與部署一樣,它前面的Pod必須都處於Running和Ready狀態。
- Statefulset使用場景:
- 穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基於PVC 來實現。
- 穩定的網絡標識符,即Pod 重新調度后其iPodName 和 HostName不變。
- 有序部署,有序擴展,基於init containers 來實現。
- 有序收縮。
