PVC和PV
一: PVC和PV概述
1.1 什么是pvc和pv
PersistentVolume (PV)是集群中已由管理員配置的一段網絡存儲。集群中的資源就像一個節點是一個集群資源。PV是諸如卷之類的卷插件,但是具有獨立於使用Pv的任何單個pod的生命周期。該API對象捕獲存儲的實現細節,即NFS, iscs1或雲提供商特定的存儲系統。
PersistentVolumeClaim (PVC)是用戶存儲的請求。PVC的使用邏輯:在pod中定義一個存儲卷(該存儲卷類型為PVC) ,定義的時候直接指定大小, pvc必須與對應的pv建立關系, pvc會根據定義去pv申請, 而pv是由存儲空間創建出來的。pv和pvc是kubernetes抽象出來的一種存儲資源。
雖然PersistentvolumeClaims允許用戶使用抽象存儲資源,但是常見的需求是,用戶需要根據不同的需求去創建PV,用於不同的場景。而此時需要集群管理員提供不同需求的PV,而不僅僅是PV的大小和訪問模式,但又不需要用戶了解這些卷的實現細節。對於這樣的需求,此時可以采用storageclass資源。
PV是集群中的資源。PVc是對這些資源的請求,也是對資源的索引檢查。
PV和pvc之間的相互作用遵循這個生命周期
- Provisioning (配置)--> Binding (綁定)--Using (使用)--> Releasing (放) ---> Recycling (回收)
1.2兩種pv的提供方式
PV的提供方式有兩種,分別是靜態和動態
- 靜態----> 直接固定存儲空間
- 集群管理員創建一些pv。它們攜帶可供集群用戶使用的正式存儲的詳細信息。它們存在於kubernetes API 中,可用於消費。
- 動態----> 通過存儲類進行動態創建空間
- 當管理員創建的靜態pv都不匹配用戶的pvc時,集群可能會嘗試動態的為pvc配置卷。此配置基於StorageClasses: PVC 必須請求存儲類,並且管理員必須已創建並配該類才能進行動態的配置。要求該類的聲明有效地為自己禁用動態配置
小結
PV 就是從存儲設備的空間創建出一個存儲資源(邏輯上存在)
-
靜態:由k8s管理員創建的,供k8s集群(pod)使用的存儲資源,可以從遠程的NFS,或者分布式對象存儲系統中創建得來(pv存儲空間大小,訪問方式)
-
動態storageClass(存儲類資源):用於動態的自動創建pvc申請的pv資源供pod使用
pod 使用pvc ----請求------> PV資源 ------> 存儲設備中
二: 查看pv和pvc的定義方式
2.1 使用explain 查看pv的定義方式
2.1.1 查看pv的定義方式
kubectl explain pv #查看pv的定義方式
FIELDS:
apiVersion
kind
metadata
spec
2.1.2 查看pv定義的規格
[root@master ~]# kubectl explain pv.spec
spec:
nfs (定義存儲類型)
path (定義掛載卷路徑)
server (定義服務器名稱)
accessModes (定義訪問模型,有以下三種訪問模型,以列表的方式存在,也就是說可以定義多個訪問模式)
ReadwriteOnce (RWO) 單節點讀寫
ReadonlyMany (ROX) 多節點只讀
ReadwriteMany (RWX) 多節點讀寫
capacity (定義PV空間的大小)
storage (指定大小)
2.2 使用explain 查看pvc的定義方式
2.2.1 查看pvc的定義方式
kubectl explain pvc #查看pvc的定義方式
KIND: PersistentVolumeClaim
VERSION: v1
FIELDS:
apiVersion: <string>
kind <string>
metadata <Object>
spec <Object>
2.2.2 查看pvc的規格
kubectl explain pvc.spec #查看pvc的規格
spec:
accessModes (定義訪問模式,必須是pv的訪問模式的子集)
resources (定義申請資源的大小)
requests:
storage:
三: 配置nfs使用pv和pvc
3.1配置nfs存儲
[root@nfs ~]# yum -y install nfs-utils rpcbind
[root@nfs ~]# mkdir -p /data/volumes/v{1..5}
[root@nfs ~]# ls -R /data/
[root@nfs ~]# chmod -R 777 /data/*
#配置nfs共享的目錄
[root@nfs ~]# for i in {1..5}
do
echo "/data/volumes/v$1 192.168.23.0/24(rw,no_root_squash,sync)" >> /etc/exports
done
#寫入網頁內容
[root@nfs ~]# for i in {1..5}
do
echo "this is pv00$i" > /data/volumes/v$i/index.html
done
[root@nfs ~]# systemctl start rpcbind
[root@nfs ~]# systemctl start nfs
[root@nfs ~]# exportfs -arv
[root@nfs ~]# showmount -e
3.2 定義pv
定義5個 pv,並且定義掛載的路徑及訪問模式,pv划分大小
[root@master ~]# vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/volumes/v1
server: stor01
accessModes:
- ReadWriteMany
- ReadWriteOnce
capacity:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/volumes/v2
server: stor01
accessModes:
- ReadWriteOnce
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/volumes/v3
server: stor01
accessModes:
- ReadWriteMany
- ReadWriteOnce
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/volumes/v4
server: stor01
accessModes:
- ReadWriteMany
- ReadWriteOnce
capacity:
storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/volumes/v5
server: stor01
accessModes:
- ReadWriteMany
- ReadWriteOnce
capacity:
storage: 5Gi
[root@master ~]# kubectl apply -f pv-demo.yaml
[root@master ~]# kubectl get pv
3.3 定義pvc
3.3.1 情況1
pvc請求的 訪問模式accessMode 及 storage大小(capacity 欄)都完全符合
[root@master ~]# vim pod-vol-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vo1-pvc
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc
[root@master ~]# kubectl apply -f pod-vol-pvc.yaml
persistentvolumeclaim/mypvc created
pod/pod-vo1-pvc created
[root@master ~]# kubectl get pods,pv -o wide
[root@master ~]# curl 10.244.1.151
this is pv003
3.3.2 情況2
在訪問模式符合 的情況下,大小不符合,則會再所以大於請求大小的pv中,選擇大小最接近的
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc-test02
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vo2-pvc
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc-test02
[root@master ~]# kubectl apply -f pod-vol-pvc.yaml
persistentvolumeclaim/mypvc-test02 created
pod/pod-vo2-pvc created
[root@master ~]# kubectl get pods,pv,pvc -o wide
[root@master ~]# curl 10.244.2.117
this is pv004
3.3.3 情況3
在訪問模式不符合,或者大小沒有滿足的(都效於),則pod和pvc都處於pending狀態
[root@master ~]# vim pod-vol-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc-test03
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 7Gi
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vo3-pvc
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc-test03
[root@master ~]# kubectl apply -f pod-vol-pvc.yaml
persistentvolumeclaim/mypvc-test03 created
pod/pod-vo3-pvc created
[root@master ~]# kubectl get pods,pv,pvc -o wide
[root@master ~]# kubectl get pods,pv,pvc -o wide
[root@master ~]# kubectl describe pod pod-vo3-pvc
3.3.4 情況4
使用多主機讀寫 RWX (ReadWriteMany) 模式,將新創建的pod 加入到已有的pvc 中
[root@master ~]# vim pod-vol-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-vo4-pvc
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc-test02
[root@master ~]# kubectl apply -f pod-vol-pvc.yaml
pod/pod-vo4-pvc created
[root@master ~]# kubectl get pods,pv,pvc -o wide
[root@master ~]# curl 10.244.1.152
this is pv004
3.3.4 pvc綁定情況和多節點讀寫的小結
當pvc請求的 類型accessModes 和存儲storage大小沒有完全符合的pv時
-
會在 accessModes類型相同的情況下
-
- 選擇storage存儲 大於請求的pv,
- 在多個都大於時,會選擇最接近的。
-
在 類型accessModes都沒有符合的情況下,或者storage存儲大小都小於請求的時候
-
- pod和pvc會處於pnding狀態
多節點讀寫:
在創建pod時,pod.spec.volumes.claimName 的值使用已有的pvc 名,可以是pod使用已有的pvc,從而使用pv
3.4 刪除pvc綁定
[root@master ~]# kubectl describe persistentvolumeclaims mypvc-test02
....
Mounted By: pod-vo2-pvc
pod-vo4-pvc
.....
#先刪除使用這個pvc的所有pod
[root@master ~]# kubectl delete pod pod-vo{2,4}-pvc
pod "pod-vo2-pvc" deleted
pod "pod-vo4-pvc" deleted
#再刪除pvc
[root@master ~]# kubectl delete persistentvolumeclaims mypvc-test02
persistentvolumeclaim "mypvc-test02" deleted
#查看發現pvc確實被刪除了,但是,相應的pv處於Released狀態,此時pv無法被新pvc綁定
[root@master ~]# kubectl get pods,pv,pvc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
persistentvolume/pv004 4Gi RWO,RWX Retain Released default/mypvc-test02 73m Filesystem
使用 edit 在線對pv 資源進行編輯,刪除claiRef段落。保存后,通過命令查看,其狀態就自動變為了Available,PV即可重新使用
[root@master ~]# kubectl edit persistentvolume pv004
...
#刪除
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: mypvc-test02
namespace: default
resourceVersion: "242922"
uid: 95ef0c00-754e-4a8e-81c3-f8ee4d5f9824
.....
[root@master ~]# kubectl get pods,pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv004 4Gi RWO,RWX Retain Available 81m Filesystem
<b
四:storageClass
4.1 為什么做storageClass
在pv和pvc使用過程中存在的問題,在pvc申請存儲空間時,未必就有現成的pv符合pvc申請的需求,上面nfs在做pvc可以成功的因素是因為我們做了指定的需求處理。
那么當PVC申請的存儲空間不一定有滿足PVC要求的PV時,又該如何處理呢? ? ?為此, Kubernetes為管理員提供了描述存儲"Class(類) "的方法(StorageClass) 。
舉個例子,在存儲系統中划分一個1TB的存儲空間提供給Kubernetes使用,當用戶需要一個10G的PVC時,會立即通過restful發送請求,從而讓存儲空間創建一個10G的image,之后在我們的集群中定義成10G的PV供給給當前的PVc作為掛載使用。在此之前我們的存儲系統必須支持restful接口,比如ceph分布式存儲,而glusterfs則需要借助第三方接口完成這樣的請求。
4.2示例
kubectl explain storageclass #storageclass也是k8s上的資源KIND: storageclass
VERSION: storage.k8s.io/v1
FIELDS:
allowVolumeExpansion <boolean>
allowedTopologies <[]object>
apiversion <string>
kind <string>
metadata <object>
mountOptions <[string> #掛載選項
parameters <map [string]string> #參數,取決於分配器,可以接受不同的參數。例如,參數type的值io1和參數iopsPerGB特定於EBS PV。當參數被省略時,會使用默認值。
provisioner <string>-required- #存儲分配器,用來決定使用哪個卷插件分配pv。該字段必須指
reclaimPolicy <string> #回收策略,可以是Delete或者Retain。如果storageclass對象被創建時沒有指定reclaimPolicy它將默認為Delete
volumeBindingMode <string> #卷的綁定模式
storageclass中包含provisioner、 parameters和reclaimPolicy字段,當class需要動態分配persistentvolume時會使用到。由於storageclass需要一個獨立的存儲系統,此處就不再演示。
從其他資料查看定義storageclass的方式如下:
kind: storageclass
apiversion: storage.k8s.io/vl
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
reclaimPolicy: Retain
mountOptions:
- debug