PV、PVC簡介
PersistentVolume(PV)
是由管理員設置的存儲,它是集群的一部分,就像節點是集群中的資源一樣,PV也是集群中的資源、PV是Volume之類的卷插件,但具有獨立於使用PV的Pod的生命周期,此API對象包含存儲實現的細節,即NFS、iSCSI或特定於雲供應商的存儲系統
PersistentVolumeClaim(PVC)
是用戶存儲的請求,它與Pod相似。Pod消耗節點資源,PVC消耗PV資源。Pod可以請求特定級別的資源(CPU和內存)。PVC可以請求特定pv的大小和訪問模式(例如,可以以讀/寫一次或只讀多次模式掛載)
靜態PV
集群管理員呢創建一些PV,他們帶有可供集群用戶使用的實際存儲細節。他們存在與Kubernetes API中,可用於消費。
PV與PVC的工作流程
- 首先將不同規格的存儲(例如NFS存儲,有5GB、10GB等)創建為PV
- 用戶再將需要用到的存儲的條件創建為PVC,PVC會在PV資源中尋找最匹配用戶需求的PV
- 匹配到最優PV后,PVC與PV進行綁定,最后掛載到對應Pod中
持久化卷聲明的保護
PVC保護的目的是確保由Pod正在使用的PVC不會從系統移除,因為如果被移除的話可能會導致數據丟失
當啟用PVC保護alpha功能時,如果用戶刪除一個Pod正在使用的PVC,則該PVC不會被立即刪除。PVC的刪除將被推遲,知道PVC不再被任何Pod使用
PV訪問模式
PersistentVolume可以以資源提供者支持的任何方式掛載到主機上。如下表所示,供應商具有不同的功能,每個PV的訪問模式都將被設置為該卷支持的特定模式,例如,NFS可以支持多個讀/寫客戶端,但特定的PV可能以只讀方式導出到服務器上。每個PV都有一套自己的用來描述特定功能的訪問模式
- ReadWriteOnce——該卷可以被單個節點以讀/寫模式掛載
- ReadOnlyMany——該卷可以被多個節點以只讀模式掛載
- ReadWriteMany——該卷可以被多個節點以讀/寫模式掛載
在命令行中,訪問模式縮寫為:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
一個pv卷一次只能使用一種訪問模式掛載,即使它支持很多訪問模式。
Volume插件 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
---|---|---|---|
AWSElasticBlockStoreAWSElasticBlockStore | √ | - | - |
AzureFile | √ | √ | √ |
AzureDisk | √ | - | - |
cephFS | √ | √ | √ |
FlexVolume | √ | - | - |
Flocker | √ | √ | - |
GCEPersistentDisk | √ | √ | - |
Glusterfs | √ | - | - |
HostPath | √ | - | √ |
NFS | √ | √ | √ |
回收策略
- Retain(保留)——手動回收
- Recycle(回收)——基本擦除(rm -rf /thevolume/*)
- Delete(刪除)——關聯的存儲資產將被刪除
當前只有HostPath和NFS支持回收策略。AWS EBS、GCE PD等支持刪除策略
狀態
卷可以處於以下某種狀態:
- Available(可用) —— 一塊空閑資源沒有被任何聲明綁定
- Bound(已綁定) —— 卷已經被聲明綁定
- Released(已釋放) —— 聲明被刪除,但是資源還沒有被集群聲明
- Failed(失敗) —— 該卷的自動回收失敗
命令行會顯示綁定到PV的PVC名稱
持久化演示說明 —— NFS
1、安裝NFS
## 安裝nfs,服務器IP地址為:192.168.152.252 yum -y install nfs-utils rpcbind ## 配置nfs配置文件,設置可連接主機及權限 vim /etc/exports ... /alibaba *(rw,no_root_squash,no_all_squash,sync) <目錄路徑> <可連接ip,*代表全部> <目錄及文件權限> ... ## 創建共享目錄,及設置目錄權限 mkdir /alibaba chmod 777 -R /alibaba chown nfsnobody /alibaba/ ## 啟動nfs服務及rpcbind服務 systemctl start nfs-server.service rpcbind ### 進入客戶機,測試能否正常訪問,注意每個節點都要測試,保證可掛載 ## 客戶機安裝nfs客戶端及rpcbind yum -y install nfs-utils rpcbind ## 創建掛載目錄及掛載 mkdir /usr/local/rds mount -t nfs 192.168.152.252:/alibaba /usr/local/rds/ [root@Centos8 rds]# df -h | grep alibaba 192.168.152.252:/alibaba 17G 6.9G 11G 41% /usr/local/rds ## 進入目錄,測試讀寫是否正常 cd /usr/local/rds/ vim test.txt ......
2、創建PV(Master節點:192.168.152.53)
vim pv.yaml
apiVersion: v1 kind: PersistentVolume metadata: name: nfspv1 labels: type: web spec: capacity: #容量 storage: 1Gi #存儲 accessModes: #類型 - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle #回收策略 storageClassName: nfs #存儲類別名稱 nfs: path: /alibaba server: 192.168.152.252
多創建幾個pv,供后邊的pvc使用
## 首先在nfs中多創建幾個文件系統 [root@kubenode2 ~]# cat /etc/exports /alibaba1 *(rw,no_root_squash,no_all_squash,sync) /alibaba2 *(rw,no_root_squash,no_all_squash,sync) /alibaba3 *(rw,no_root_squash,no_all_squash,sync) /alibaba4 *(rw,no_root_squash,no_all_squash,sync) ## 重啟nfs server和rpcbind systemctl restart rpcbind nfs-server.service ## 再次去客戶端掛載測試讀寫
創建好的pv如下
[root@Centos8 pv]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfspv1 1Gi RWO Recycle Available nfs 5s
nfspv2 10Gi RWX Retain Available cloud 5s
nfspv3 5Gi RWO Recycle Available nfs 5s
nfspv4 100Gi RWX Recycle Available nfs 5s
### 創建不同的類別,存儲大小,讀寫類型
### 我這里一共創建四個pv
3、創建PVC
vim pvc.yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-nas spec: accessModes: # 選擇類型 - ReadWriteMany resources: #選擇容量 requests: storage: 10Gi storageClassName: cloud # 選擇存儲類別 selector: # 選擇標簽可以更加准確的綁定想要綁定的pv matchLabels: type: web
[root@Centos8 pv]# kubectl create -f pvc.yaml persistentvolumeclaim/pvc-nas created [root@Centos8 pv]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-nas Bound nfspv2 10Gi RWX cloud 4s [root@Centos8 pv]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE nfspv2 10Gi RWX Retain Bound default/pvc-nas cloud
創建Deployment
vim pvc-deployment.yaml
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: pvc-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.2.1 imagePullPolicy: IfNotPresent ports: - name: web containerPort: 80 volumeMounts: - name: pvc-nas mountPath: /data # 掛載路徑 volumes: - name: pvc-nas # 定義的volume名字 persistentVolumeClaim: # 綁定pvc claimName: pvc-nas #pvc的名字
[root@Centos8 pv]# kubectl create -f pvc-deployment.yaml deployment.extensions/pvc-deployment created [root@Centos8 pv]# kubectl get pod NAME READY STATUS RESTARTS AGE pvc-deployment-db7b65ff8-6nz5g 1/1 Running 0 4s pvc-deployment-db7b65ff8-9mthh 1/1 Running 0 4s pvc-deployment-db7b65ff8-kgx5w 1/1 Running 0 4s ## 查看當前/data目錄下文件 [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-6nz5g -- ls /data 111 [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-9mthh -- ls /data 111 [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-kgx5w -- ls /data 111 ## 向/data中創建文件 [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-kgx5w -- touch /data/index.html ## 再次查看,測試文件nas的共享存儲 [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-kgx5w -- ls /data 111 index.html [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-9mthh -- ls /data 111 index.html [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-6nz5g -- ls /data 111 index.html
## 刪除Pod,檢驗數據的持久性 [root@Centos8 pv]# kubectl delete pod pvc-deployment-db7b65ff8-6nz5g pod "pvc-deployment-db7b65ff8-6nz5g" deleted [root@Centos8 pv]# kubectl get pod NAME READY STATUS RESTARTS AGE pvc-deployment-db7b65ff8-9mthh 1/1 Running 0 3m11s pvc-deployment-db7b65ff8-bnvw7 1/1 Running 0 47s pvc-deployment-db7b65ff8-kgx5w 1/1 Running 0 3m11s ## 再次查看,依舊是這兩個文件 [root@Centos8 pv]# kubectl exec -it pvc-deployment-db7b65ff8-bnvw7 -- ls /data 111 index.html
aliyunURL: https://help.aliyun.com/document_detail/100684.html?spm=a2c4g.11186623.6.1080.1668631aCuHGi2
4、創建StatefulSet
vim StatefulSet.yaml
apiVersion: v1 kind: Service metadata: name: pvc-svc namespace: default labels: app: nginx spec: clusterIP: None ports: - name: web port: 80 selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web namespace: default spec: replicas: 3 selector: matchLabels: app: nginx serviceName: "pvc-svc" template: metadata: labels: app: nginx spec: dnsPolicy: ClusterFirstWithHostNet #使pod使用k8s的dns而不是宿主機dns containers: - name: nginx image: hub.vfancloud.com/test/myapp:v1 imagePullPolicy: IfNotPresent ports: - name: web containerPort: 80 volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] #指定pv的讀寫策略 storageClassName: "nfs" #指定pv的存儲類型 resources: requests: storage: 1Gi #指定pv的存儲大小
查看Pod、PV信息
[root@Centos8 pv]# kubectl get pod NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 2m32s web-1 1/1 Running 0 2m30s web-2 0/1 Pending 0 2m27s ### yaml文件中statefulSet指定副本數為3個,其中web-2一直處於pending狀態 ## 查看web-2描述,提示Pod沒有可以綁定的pv [root@Centos8 pv]# kubectl describe pod web-2 Events: Warning FailedScheduling 66s (x3 over 3m47s) default-scheduler pod has unbound immediate PersistentVolumeClaims ## 再看PV的狀態 ### nfspv1和nfspv3的STATUS為Bound,已被綁定其他的均為Available可用狀態 ### 再來回顧一下上邊yaml文件內容 ### yaml中明確指出,accessModes必須為ReadWriteOnly,storageClassName必須為NFS,storage存儲為1Gi,可見,第一個pod創建時直接綁定最合適nfspv1,第二個Pod創建時由於沒有其他符合的nfs,所以綁定nfspv3,第三個Pod創建后,發現沒有合適的pv了,所以一直保持pending狀態 [root@Centos8 pv]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS nfspv1 1Gi RWO Recycle Bound default/www-web-0 nfs nfspv2 10Gi RWX Retain Available cloud nfspv3 5Gi RWO Recycle Bound default/www-web-1 nfs nfspv4 100Gi RWX Recycle Available nfs
測試訪問Pod、NFS持久性(statefulSet特性)
## 在web-0所綁定的nfs下創建index.html文件,內容如下 [root@kubenode2 alibaba1]# cat index.html Are you ok? ## 訪問web-0的http服務 [root@Centos8 pv]# curl http://10.244.3.56 Are you ok? ## 在web-1所綁定的nfs下創建index.html文件,內容如下 [root@kubenode2 alibaba3]# cat index.html qbbbbbb bbbbb ## 訪問web-1的http服務 [root@Centos8 pv]# curl http://10.244.3.57 qbbbbbb bbbbb ## 測試刪除pod后,存儲是否持久化 [root@Centos8 pv]# kubectl delete pod web-0 pod "web-0" deleted [root@Centos8 pv]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP web-0 1/1 Running 0 9s 10.244.3.58 ## ip已經發生改變,再次測試訪問http,數據未變化 [root@Centos8 pv]# curl http://10.244.3.58 Are you ok?
aliyunURL: https://help.aliyun.com/document_detail/100013.html?spm=a2c4g.11186623.6.1084.562220d7kAeXTB
關於StatefulSet
1、匹配Pod name(網絡標識)的模式為:(statefulset名稱)-符號,比如上面的web-0,web-1
2、StatefulSet為每個Pod副本創建了一個DNS域名,域名格式為:$(podname).(headless server name),也就意味着服務間是通過Pod域名來通信而非Pod IP,因為Pod在Node發生故障時,會將Pod漂移到其他node節點,Pod IP會發生改變,但是Pod域名不會變化
3、StatefulSet使用Headless服務來控制Pod的域名,這個域名的FQDN為:(servicename).(namespace).svc.cluster.local,其中,"cluster.local"指的是集群的域名
4、根據VolumeClaimTemplates,為每個Pod創建一個pvc,pvc命名規則匹配模式:(volumeClaimTemplate.name)-(pod.name),比如www-web-0
5、刪除Pod不會刪除其pvc,手動刪除pvc將自動釋放pv
驗證DNS解析
## 當前pod [root@Centos8 pv]# kubectl get pod NAME READY STATUS RESTARTS AGE ingress-http2-84b79f86c8-l6w7z 1/1 Running 0 8m33s ingress-http2-84b79f86c8-sgsch 1/1 Running 0 8m33s ingress-http2-84b79f86c8-xm7tj 1/1 Running 0 8m33s web-0 1/1 Running 0 24m web-1 1/1 Running 0 18m web-2 0/1 Pending 0 20m ## 當前svc [root@Centos8 pv]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-svc2 ClusterIP 10.105.70.203 <none> 8080/TCP 9m4s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 84d pvc-svc ClusterIP None <none> 80/TCP 25m ## 訪問statefulSet的pod,使用域名$(podname).(headless server name)的方式 [root@Centos8 pv]# kubectl exec -it web-0 -- nslookup web-1.pvc-svc Name: web-1.pvc-svc Address 1: 10.244.3.90 或者 [root@Centos8 pv]# kubectl exec -it web-0 -- nslookup web-1.pvc-svc.default.svc.cluster.local. Name: web-1.pvc-svc.default.svc.cluster.local. Address 1: 10.244.3.90 ## 測試其他svc的Pod是否可以通過$(podname).(headless server name)的方式訪問 [root@Centos8 pv]# kubectl exec -it ingress-http2-84b79f86c8-sgsch -- nslookup web-1.pvc-svc Name: web-1.pvc-svc Address 1: 10.244.3.90 或者 [root@Centos8 pv]# kubectl exec -it ingress-http2-84b79f86c8-sgsch -- nslookup web-0.pvc-svc.default.svc.cluster.local. Name: web-0.pvc-svc.default.svc.cluster.local. Address 1: 10.244.3.88 ## 此功能是通過無頭(headless)服務進行綁定的,最終規則如下 [root@Centos8 pv]# dig -t -A pvc-svc.default.svc.cluster.local. @10.244.0.81 ;; Warning, ignoring invalid type -A ; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el8 <<>> -t -A pvc-svc.default.svc.cluster.local. @10.244.0.81 ;; global options: +cmd ;; Got answer: ;; WARNING: .local is reserved for Multicast DNS ;; You are currently testing what happens when an mDNS query is leaked to DNS ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14325 ;; flags: qr rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 538aadec9b559ba0 (echoed) ;; QUESTION SECTION: ;pvc-svc.default.svc.cluster.local. IN A ;; ANSWER SECTION: pvc-svc.default.svc.cluster.local. 17 IN A 10.244.3.90 pvc-svc.default.svc.cluster.local. 17 IN A 10.244.3.88 ;; Query time: 0 msec ;; SERVER: 10.244.0.81#53(10.244.0.81) ;; WHEN: 日 7月 05 11:41:24 CST 2020 ;; MSG SIZE rcvd: 172
statefulSet的啟停順序
- 有序部署:部署StatefulSet時,如果有多個Pod副本,它們會被順序的創建(從0到N-1),並且,在下一個Pod運行之前,之前的Pod必須是Ready或者Running的狀態
- 有序刪除:當Pod被刪除時,他們被終止的順序是從N-1到0
- 有序擴展:當Pod執行擴展操作時,與部署一樣,他們之前的Pod必須是Running和Ready狀態
statefulSet使用場景
- 穩定的持久化存儲,即Pod重新調度后還是能訪問相同的持久化數據,基於PVC來實現
- 穩定的網絡表示符,即Pod重新調度后其PodNname與HostName不變
- 有序部署,有序擴展,基於init Container來實現
- 有序收縮
刪除持久化存儲pv、pvc
## 首先刪除pvc的yaml文件,svc和statefulSet就會被刪除 [root@Centos8 pv]# kubectl delete -f StatefulSet.yaml service "pvc-svc" deleted statefulset.apps "web" deleted ## 刪除pvc [root@Centos8 pv]# kubectl delete pvc --all persistentvolumeclaim "www-web-0" deleted persistentvolumeclaim "www-web-1" deleted persistentvolumeclaim "www-web-2" deleted ## 確認 [root@Centos8 pv]# kubectl get pvc No resources found. [root@Centos8 pv]# kubectl get statefulset No resources found. ## 查看pv,狀態已經變為Released,雖然已經解除綁定,但還沒有完全回收 [root@Centos8 pv]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE nfspv1 1Gi RWO Recycle Released default/www-web-0 nfs 6d14h nfspv2 10Gi RWX Retain Available cloud 6d14h nfspv3 5Gi RWO Recycle Released default/www-web-1 nfs 6d14h nfspv4 100Gi RWX Recycle Available nfs 6d14h ## 手動回收 [root@Centos8 pv]# kubectl edit pv nfspv3 把以下內容刪除,然后保存 claimRef: apiVersion: v1 kind: PersistentVolumeClaim name: www-web-1 namespace: default resourceVersion: "323988" uid: 32f75ce6-5462-42c1-9913-888c803b0bf4 ## 再次查看,已經完全釋放 [root@Centos8 pv]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE nfspv1 1Gi RWO Recycle Available nfs 6d14h nfspv2 10Gi RWX Retain Available cloud 6d14h nfspv3 5Gi RWO Recycle Available nfs 6d14h nfspv4 100Gi RWX Recycle Available nfs 6d14h