關於PV、PVC、StorageClass ,這篇文章講的不錯:https://www.cnblogs.com/rexcheny/p/10925464.html
容器的設計理念就是一次性,也就是容器銷毀后容器里的所有數據都會銷毀,所以需要將容器里面需要保留的數據掛載到持久性存儲中,這里就涉及到三個概念:PV、PVC、StorageClass 。
HostPath
當使用docker創建container的時候,一般都是加參數 -v 掛載宿主機的目錄到container里面,k8s 也可以實現該功能,先講解一下 掛載到宿主機目錄的方法。
創建一個deployment資源配置文件,掛載到宿主機目錄:
[root@ylserver10686071 ~]# cat volumes001.yml apiVersion: apps/v1 kind: Deployment metadata: name: volumes001 namespace: prod spec: replicas: 1 selector: matchLabels: k8s-app: volumes001 template: metadata: labels: k8s-app: volumes001 spec: containers: - name: nginx image: nginx:1.21 volumeMounts: - mountPath: /usr/share/nginx/html/ name: html volumes: - name: html hostPath: path: /data/nginx/html/ type: DirectoryOrCreate
- volumeMounts 掛載到container 指定目錄的相關配置,根據name來匹配volumes對象的下的name,據此來找到掛載對象
- volumes 聲明掛載對象
- hostPath 存儲類型
- type: DirectoryOrCreate 如果宿主機路徑不存在則創造該路徑,當值為Directory 是,宿主機必須有該目錄,否則會導致pod創建失敗
創建deployment資源,查看pod在哪台Node上運行:
[root@ylserver10686071 ~]# kubectl apply -f volumes001.yml deployment.apps/volumes001 created [root@ylserver10686071 ~]# kubectl get pods -n prod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES volumes001-66767f866f-rc5qk 1/1 Running 0 21s 10.233.72.59 ylserver10686073 <none> <none> [root@ylserver10686071 ~]#
在ylserver10686071 Node上查看目錄是否創建,然后到Pod運行的節點上查看目錄是否創建:
[root@ylserver10686071 ~]# ll /data/nginx/html/ ls: cannot access /data/nginx/html/: No such file or directory [root@ylserver10686071 ~]# [root@ylserver10686073 ~]# ll /data/nginx/html/ total 0 [root@ylserver10686073 ~]#
給掛載目錄創建文件,驗證是否掛載到Pod里面:
[root@ylserver10686073 ~]# echo "Hello K8S" > /data/nginx/html/index.html [root@ylserver10686073 ~]# curl http://10.233.72.59/index.html Hello K8S [root@ylserver10686073 ~]#
PV
上面的實驗中宿主機掛載的目錄只有在 Pod 運行的 Node 上才會創建,換言之,Pod要掛載的目錄必須跟Node做綁定,這會增加運維的難度,也失去k8s的故障轉移特性。
針對這個問題,可以使用存儲券解決,這里就要引入一個概念:PV。
PV全稱叫做Persistent Volume,持久化存儲卷。它是用來描述或者說用來定義一個存儲卷的,這個通常都是有運維或者數據存儲工程師來定義。本節使用NFS來作為存儲端,NFS搭建這里不做講解。
先創建一個PV資源配置文件:
[root@ylserver10686071 ~]# cat pv001.yml apiVersion: v1 kind: PersistentVolume ###PV資源不屬於任何命名空間,屬於集群級別的 ###kubectl api-resources --namespaced=true 命令可以查看哪些資源屬於命名空間 metadata: name: pv001 labels: ###Label可以不定義 name: pv001 storetype: nfs spec: ###定義PV資源規格 storageClassName: normal accessModes: ###設置訪問模型 - ReadWriteMany - ReadWriteOnce - ReadOnlyMany capacity: ###設置存儲空間大小 storage: 500Mi persistentVolumeReclaimPolicy: Retain ###回收策略 nfs: path: /data/nfs/k8s/ server: 10.68.60.193 [root@ylserver10686071 ~]#
accessModes 有3種屬性值:
- ReadWriteMany 多路讀寫,卷能被集群多個節點掛載並讀寫
- ReadWriteOnce 單路讀寫,卷只能被單一集群節點掛載讀寫
- ReadOnlyMany 多路只讀,卷能被多個集群節點掛載且只能讀
persistentVolumeReclaimPolicy 回收策略也有3種屬性值:
- Retain
當刪除與之綁定的PVC時候,這個PV被標記為released(PVC與PV解綁但還沒有執行回收策略)且之前的數據依然保存在該PV上,但是該PV不可用,需要手動來處理這些數據並刪除該PV
這種方式是最常用的,可以避免誤刪pvc或者pv而造成數據的丟失
- Delete 刪除存儲資源,AWS EBS, GCE PD, Azure Disk, and Cinder volumes支持這種方式
- Recycle 這個在1.14版本中以及被廢棄,取而代之的是推薦使用動態存儲供給策略,它的功能是當刪除與該PV關聯的PVC時,自動刪除該PV中的所有數據
創建完PV后,PV會有幾種狀態:
- Available(可用) 塊空閑資源還沒有被任何聲明綁定
- Bound(已綁定) 卷已經被聲明綁定
- Released(已釋放) 聲明被刪除,但是資源還未被集群重新聲明
- Failed(失敗) 該卷的自動回收失敗
創建PV資源,並查看PV信息:
[root@ylserver10686071 ~]# kubectl apply -f pv001.yml persistentvolume/pv001 created [root@ylserver10686071 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 500Mi RWO,ROX,RWX Retain Available normal 6s
PVC
PV只是定義了一個存儲卷實體,還需要一層抽象的接口使其與POD關聯,這層抽象的接口就是PVC,全稱 Persistent Volume Claim,也就是持久化存儲聲明。開發人員使用這個來描述該容器需要一個什么存儲。
創建一個PVC資源配置文件:
[root@ylserver10686071 ~]# cat pvc001.yml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc001 namespace: prod ###PVC資源屬於命名空間級別 labels: ###Label可以不定義 name: pvc001 storetype: nfs capacity: 500Mi spec: storageClassName: normal accessModes: ###PVC也需要定義訪問模式,不過它的模式一定是和現有PV相同或者是它的子集,否則匹配不到PV - ReadWriteMany resources: ###定義資源要求PV滿足這個PVC的要求才會被匹配到 requests: storage: 500Mi # 定義要求有多大空間
創建PVC資源,查看PVC資源和PV資源綁定情況,可以看到PV和PVC已經實現綁定:
[root@ylserver10686071 ~]# kubectl apply -f pvc001.yml persistentvolumeclaim/pvc001 created [root@ylserver10686071 ~]# kubectl get pvc -n prod NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc001 Bound pv001 500Mi RWO,ROX,RWX normal 15s [root@ylserver10686071 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 500Mi RWO,ROX,RWX Retain Bound prod/pvc001 normal 62m [root@ylserver10686071 ~]#
PVC是如何跟PVC綁定的呢,有以下幾個原則:
- PV和PVC中的spec關鍵字段要匹配,比如存儲(storage)大小
- PVC的訪問模式一定是和現有PV相同或者是它的子集,否則匹配不到PV
- PV和PVC中的 StorageClass Name字段必須一致,StorageClass后面會講到
- Label 標簽在這里只做描述作用,跟 PV 和 PVC 的綁定沒有任何關系
看到這里,回想總結一下就會發現 k8s 里面會通過定義一層抽象概念來管理實體或者連接實體,類似於 Pod 和 Container , PVC 和 PV ;對象和對象的匹配設計原理也是一直,例如 deployment匹配replicaset通過matchLabels ,PV 和 PVC通過 StorageClass Name以及 resources等,即對象與對象之間通過匹配關系進行綁定。
更新上面的deployment資源配置文件,使其使用創建好的PVC資源:
[root@ylserver10686071 ~]# cat volumes001.yml apiVersion: apps/v1 kind: Deployment metadata: name: volumes001 namespace: prod ###要和指定的PVC同一個命名空間 spec: replicas: 1 selector: matchLabels: k8s-app: volumes001 template: metadata: labels: k8s-app: volumes001 spec: containers: - name: nginx image: nginx:1.21 volumeMounts: ###container的掛載聲明沒有改變 - mountPath: /usr/share/nginx/html/ name: html volumes: ###依然使用volumes聲明掛載卷 - name: html persistentVolumeClaim: ###指定PVC claimName: pvc001
更新資源deployment資源配置文件,查看pod關於volumes相關信息:
[root@ylserver10686071 ~]# kubectl apply -f volumes001.yml deployment.apps/volumes001 configured [root@ylserver10686071 ~]# kubectl describe pod volumes001 -n prod|grep -5 Volumes Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: html: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: pvc001 ReadOnly: false default-token-lx75g: [root@ylserver10686071 ~]#
寫一個文件到NFS掛載目錄中,測試一下效果:
[root@ylserver106860193 ~]# echo "K8S PV" > /data/nfs/k8s/index.html [root@ylserver10686071 ~]# kubectl get pods -n prod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES volumes001-55f5bb9585-nx9xd 1/1 Running 0 11m 10.233.72.60 ylserver10686073 <none> <none> [root@ylserver10686071 ~]# curl http://10.233.72.60 K8S PV [root@ylserver10686071 ~]#
給原來的Node打上Taint,重啟deployment資源,查看Pod在其他Node上運行時,原來的掛載文件是否還存在:
[root@ylserver10686071 ~]# kubectl taint node ylserver10686073 web=nginx:NoSchedule node/ylserver10686073 tainted [root@ylserver10686071 ~]# kubectl rollout restart deployment volumes001 -n prod deployment.apps/volumes001 restarted [root@ylserver10686071 ~]# kubectl get pods -n prod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES volumes001-7fcd68c5b8-hcwcf 1/1 Running 0 30s 10.233.67.54 ylserver10686072 <none> <none> [root@ylserver10686071 ~]#
驗證一下,可以看到掛載的文件依然存在:
[root@ylserver10686071 ~]# curl http://10.233.67.54 K8S PV [root@ylserver10686071 ~]#
PV回收時需要刪除PVC,刪除PVC需要先刪除關聯的Pod,驗證一下:
[root@ylserver10686071 ~]# kubectl delete deployments volumes001 -n prod deployment.apps "volumes001" deleted [root@ylserver10686071 ~]# kubectl delete pvc pvc001 -n prod persistentvolumeclaim "pvc001" deleted [root@ylserver10686071 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 500Mi RWO,ROX,RWX Retain Released prod/pvc001 normal 18m [root@ylserver10686071 ~]#
可以看到刪除pvc后,pv處於Released狀態,此時pv只能刪除重新創建才能繼續使用,驗證一下:
[root@ylserver10686071 ~]# kubectl apply -f pvc001.yml persistentvolumeclaim/pvc001 created [root@ylserver10686071 ~]# kubectl get pvc -n prod NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc001 Pending normal 17s [root@ylserver10686071 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 500Mi RWO,ROX,RWX Retain Released prod/pvc001 normal 19m
刪除PV,因為回收策略是Retain,所以NFS端的數據依然存在,驗證一下:
[root@ylserver10686071 ~]# kubectl delete pv pv001 persistentvolume "pv001" deleted [root@ylserver106860193 ~]# cat /data/nfs/k8s/index.html K8S PV [root@ylserver106860193 ~]#
重新創建PV,PVC就可以繼續綁定:
[root@ylserver10686071 ~]# kubectl apply -f pv001.yml persistentvolume/pv001 created [root@ylserver10686071 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 500Mi RWO,ROX,RWX Retain Bound prod/pvc001 normal 18s [root@ylserver10686071 ~]# kubectl get pvc -n prod NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc001 Bound pv001 500Mi RWO,ROX,RWX normal 4m11s [root@ylserver10686071 ~]#
StorageClass
PV是運維人員創建的,開發操作PVC,一個PV只能被一個PVC綁定,如果這些PV都需要運維手動來處理將會是一件十分繁瑣的事情,所以就有了動態供給概念,也就是Dynamic Provisioning。而我們上面的創建的PV都是靜態供給方式,也就是Static Provisioning。而動態供給的關鍵就是StorageClass,它的作用就是創建PV模板。
創建StorageClass里面需要定義PV屬性比如存儲類型、大小等;另外創建這種PV需要用到存儲插件。最終效果是,用戶提交PVC,里面指定存儲類型,如果符合我們定義的StorageClass,則會為其自動創建PV並進行綁定。
Kubernetes本身支持的動態PV創建不包括nfs,所以需要使用額外插件實現。nfs-client
GitHub的部署里面使用的鏡像地址國內無法下載,這里修改了一下,用國內的鏡像地址,這里使用helm部署nfs插件,先下載 chart文件: https://www.mediafire.com/file/pzi7skcwdm0v64a/nfs-subdir-external-provisioner.tar.gz/file
下載文件后,解壓到 /opt 目錄下:
tar -zxvf nfs-subdir-external-provisioner.tar.gz -C /opt/
使用helm部署 nfs-client插件:
[root@ylserver10686071 ~]# cd /opt/nfs-subdir-external-provisioner/ [root@ylserver10686071 nfs-subdir-external-provisioner]# helm install nfs-subdir-external-provisioner --namespace kube-system . --set nfs.server=10.68.60.193 --set nfs.path=/data/nfs/k8s/ NAME: nfs-subdir-external-provisioner LAST DEPLOYED: Fri Jul 30 20:36:05 2021 NAMESPACE: prod STATUS: deployed REVISION: 1 TEST SUITE: None [root@ylserver10686071 nfs-subdir-external-provisioner]#
查看已經創建的 StorageClass,StorageClass屬於集群級別:
[root@ylserver10686071 nfs-subdir-external-provisioner]# kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs-client cluster.local/nfs-subdir-external-provisioner Delete Immediate true 48s [root@ylserver10686071 nfs-subdir-external-provisioner]#
創建PVC資源配置文件,使用nfs-client StorageClass:
[root@ylserver10686071 ~]# cat pvc002.yml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc002 namespace: default labels: name: pvc002 storetype: nfs capacity: 300Mi spec: storageClassName: nfs-client accessModes: - ReadWriteMany resources: requests: storage: 300Mi [root@ylserver10686071 ~]#
創建PVC資源,可以看到PV已經自動創建:
[root@ylserver10686071 ~]# kubectl apply -f pvc002.yml persistentvolumeclaim/pvc002 created [root@ylserver10686071 ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc002 Bound pvc-13f05a23-0fce-429f-9803-db4ec3dd6465 300Mi RWX nfs-client 5m [root@ylserver10686071 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-13f05a23-0fce-429f-9803-db4ec3dd6465 300Mi RWX Delete Bound default/pvc002 nfs-client 5m3s [root@ylserver10686071 ~]#
NFS服務端可以看到創建的PV對應存儲目錄:
[root@ylserver106860193 ~]# ll /data/nfs/k8s/ total 4 drwxrwxrwx 2 root root 6 Jul 31 03:17 default-pvc002-pvc-13f05a23-0fce-429f-9803-db4ec3dd6465 -rw-r--r-- 1 root root 7 Jul 30 03:32 index.html [root@ylserver106860193 ~]#
現在往PV對應的目錄寫入文件,然后刪除PVC,看NFS端PV對應的存儲目錄是否存儲:
[root@ylserver106860193 ~]# echo "StorageClass" > /data/nfs/k8s/default-pvc002-pvc-13f05a23-0fce-429f-9803-db4ec3dd6465/index.html [root@ylserver106860193 ~]#
開始刪除PVC,PV也會自動刪除
[root@ylserver10686071 ~]# kubectl delete pvc pvc002 persistentvolumeclaim "pvc002" deleted [root@ylserver10686071 ~]# kubectl get pvc No resources found in default namespace. [root@ylserver10686071 ~]# kubectl get pv No resources found [root@ylserver10686071 ~]#
查看NFS服務端目錄,可以看到文件依然保留,目錄在原有名稱上添加了archived-:
[root@ylserver106860193 ~]# cat /data/nfs/k8s/archived-default-pvc002-pvc-13f05a23-0fce-429f-9803-db4ec3dd6465/index.html StorageClass [root@ylserver106860193 ~]#
其實跟StorageClass回收策略,涉及兩個參數,文件 /opt/nfs-subdir-external-provisioner/values.yaml里可以修改,然后helm update 即可:
archiveOnDelete: true reclaimPolicy: Delete
- archiveOnDelete 當設置為 true 時,在刪除PVC后,會對 PV 對應的存儲目錄進行備份
- reclaimPolicy 回收策略,上面有講解過,Delete策略就是刪除PVC時自動刪除綁定的PV
StatefulSet StorageClass
當使用 StatefulSet 控制器創建Pod的時候,可以在 StatefulSet 配置文件里面直接聲明 PV的創建,創建一個StatefulSet 資源配置文件:
[root@ylserver10686071 ~]# cat volumes002.yml apiVersion: apps/v1 kind: StatefulSet metadata: name: volumes002 namespace: prod spec: serviceName: volumes002-svc selector: matchLabels: k8s-app: volumes002 replicas: 3 template: metadata: labels: k8s-app: volumes002 spec: containers: - name: nginx image: nginx:1.21 volumeMounts: - mountPath: /usr/share/nginx/html/ name: html volumeClaimTemplates: ###這里聲明PV資源 - metadata: ###這里聲明具體PV信息,數組類型,可以聲明多個 name: html annotations: volume.beta.kubernetes.io/storage-class: nfs-client spec: accessModes: - ReadWriteMany resources: requests: storage: 200Mi
創建 StatefulSet 資源,查看PV創建信息:
[root@ylserver10686071 ~]# kubectl apply -f volumes002.yml statefulset.apps/volumes002 created [root@ylserver10686071 ~]# kubectl get pvc -n prod NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE html-volumes002-0 Bound pvc-216d73b5-b4b6-4103-a163-f67c235b8cda 200Mi RWX nfs-client 38s html-volumes002-1 Bound pvc-17a767a7-282a-4fc4-8050-72ddc5829d86 200Mi RWX nfs-client 22s html-volumes002-2 Bound pvc-40409054-f6a8-46f8-9c0a-96979de34249 200Mi RWX nfs-client 5s [root@ylserver10686071 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-17a767a7-282a-4fc4-8050-72ddc5829d86 200Mi RWX Delete Bound prod/html-volumes002-1 nfs-client 26s pvc-216d73b5-b4b6-4103-a163-f67c235b8cda 200Mi RWX Delete Bound prod/html-volumes002-0 nfs-client 42s pvc-40409054-f6a8-46f8-9c0a-96979de34249 200Mi RWX Delete Bound prod/html-volumes002-2 nfs-client 9s [root@ylserver10686071 ~]#
Local PV
PV的后端存儲也支持本地宿主機目錄,類似於hostPath,跟hostPath 同樣存在一個問題,通常先創建PV,然后創建PVC,這時候如果兩者匹配那么系統會自動進行綁定,哪怕是動態PV創建,也是先調度POD到任意一個節點,然后根據PVC來進行創建PV然后進行綁定最后掛載到POD中,可是本地持久化存儲有一個問題就是這種PV必須要先准備好,而且不一定集群所有節點都有這種PV,如果POD隨意調度肯定不行,如何保證POD一定會被調度到有PV的節點上呢?這時候就需要在PV中聲明節點親和,且POD被調度的時候還要考慮卷的分布情況。
編寫PV資源配置文件:
[root@ylserver10686071 ~]# cat pv002.yml apiVersion: v1 kind: PersistentVolume metadata: name: pv002 labels: name: pv002 storetype: Local spec: storageClassName: local-storage accessModes: - ReadWriteMany - ReadWriteOnce - ReadOnlyMany capacity: storage: 5000Mi persistentVolumeReclaimPolicy: Retain local: ### local類型 path: /data/pv002 ###宿主機目錄 nodeAffinity: ###節點親和性設置 required: nodeSelectorTerms: - matchExpressions: - key: database operator: In values: - mysql
編寫存儲類配置文件:
[root@ylserver10686071 ~]# cat storageclass002.yml kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer
這里的volumeBindingMode: WaitForFirstConsumer
很關鍵,意思就是延遲綁定,當有符合PVC要求的PV不立即綁定。因為POD使用PVC,而綁定之后,POD被調度到其他節點,顯然其他節點很有可能沒有那個PV所以POD就掛起了,另外就算該節點有合適的PV,而POD被設置成不能運行在該節點,這時候就沒法了,延遲綁定的好處是,POD的調度要參考卷的分布。當開始調度POD的時候看看它要求的LPV在哪里,然后就調度到該節點,然后進行PVC的綁定,最后在掛載到POD中,這樣就保證了POD所在的節點就一定是LPV所在的節點。所以讓PVC延遲綁定,就是等到使用這個PVC的POD出現在調度器上之后(真正被調度之前),然后根據綜合評估再來綁定這個PVC。
編寫PVC配置文件:
[root@ylserver10686071 ~]# cat pvc002.yml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc002 namespace: prod labels: name: pvc002 storetype: local capacity: 5000Mi spec: storageClassName: local-storage accessModes: - ReadWriteOnce resources: requests: storage: 5000Mi
創建PV、StorageClass、PVC資源,查看PVC綁定情況:
[root@ylserver10686071 ~]# kubectl apply -f pv002.yml persistentvolume/pv002 created [root@ylserver10686071 ~]# kubectl apply -f storageclass002.yml storageclass.storage.k8s.io/local-storage created [root@ylserver10686071 ~]# kubectl apply -f pvc002.yml persistentvolumeclaim/pvc002 created [root@ylserver10686071 ~]# kubectl get pvc -n prod|grep pvc002 pvc002 Pending local-storage 17s
可以看到PVC處於Pending狀態,這也就是延遲綁定,因為此時還沒有POD。
創建 StatefulSet 資源配置文件:
[root@ylserver10686071 ~]# cat volumes003.yml apiVersion: apps/v1 kind: StatefulSet metadata: name: volumes003 namespace: prod spec: serviceName: volumes003-svc replicas: 1 selector: matchLabels: k8s-app: volumes003 template: metadata: labels: k8s-app: volumes003 spec: containers: - name: mysql env: - name: "MYSQL_DATABASE" value: "admin" - name: "MYSQL_USER" value: "admin" - name: "MYSQL_ROOT_PASSWORD" value: "123456" - name: "MYSQL_PASSWORD" value: "123456" image: mysql:5.7 imagePullPolicy: IfNotPresent ports: - containerPort: 3306 name: mysql protocol: TCP volumeMounts: - mountPath: /var/lib/mysql name: mysql-data volumes: - name: mysql-data persistentVolumeClaim: claimName: pvc002
先創建掛載目錄(目錄必須先手動創建),接着給Node打上標簽,然后創建StatefulSet,查看Pod運行情況:
[root@ylserver10686073 ~]# mkdir /data/pv002 [root@ylserver10686071 ~]# kubectl label node ylserver10686073 database=mysql node/ylserver10686073 labeled [root@ylserver10686071 ~]# kubectl apply -f volumes003.yml statefulset.apps/volumes003 created [root@ylserver10686071 ~]# kubectl get pods -n prod -o wide|grep volumes003 volumes003-0 1/1 Running 0 23s 10.233.72.71 ylserver10686073 <none> <none> [root@ylserver10686071 ~]#
Pod運行的 Node 節點上查看掛載目錄內容:
[root@ylserver10686073 ~]# ll /data/pv002/ total 188484 -rw-r-----. 1 polkitd input 56 Jul 31 17:31 auto.cnf -rw-------. 1 polkitd input 1676 Jul 31 17:31 ca-key.pem -rw-r--r--. 1 polkitd input 1112 Jul 31 17:31 ca.pem -rw-r--r--. 1 polkitd input 1112 Jul 31 17:31 client-cert.pem -rw-------. 1 polkitd input 1680 Jul 31 17:31 client-key.pem -rw-r-----. 1 polkitd input 436 Jul 31 17:31 ib_buffer_pool -rw-r-----. 1 polkitd input 79691776 Jul 31 17:31 ibdata1 -rw-r-----. 1 polkitd input 50331648 Jul 31 17:31 ib_logfile0 -rw-r-----. 1 polkitd input 50331648 Jul 31 17:30 ib_logfile1 -rw-r-----. 1 polkitd input 12582912 Jul 31 17:31 ibtmp1 drwxr-x---. 2 polkitd input 4096 Jul 31 17:31 mysql drwxr-x---. 2 polkitd input 8192 Jul 31 17:31 performance_schema -rw-------. 1 polkitd input 1676 Jul 31 17:31 private_key.pem -rw-r--r--. 1 polkitd input 452 Jul 31 17:31 public_key.pem -rw-r--r--. 1 polkitd input 1112 Jul 31 17:31 server-cert.pem -rw-------. 1 polkitd input 1680 Jul 31 17:31 server-key.pem drwxr-x---. 2 polkitd input 8192 Jul 31 17:31 sys [root@ylserver10686073 ~]#
這個POD被調度到Node ylserver10686073上,因為PV就在Node ylserver10686073上,這時候刪除這個POD,然后在重建該POD,那么依然會被調度到Node ylserver10686073上。
總結一下:
- 根據 Container 一次性原則,Container銷毀時,里面的數據也會銷毀,所以需要保存的數據需要掛載到持久化存儲中;
- Container 保存數據數據可以選擇直接掛載宿主機目錄,即 掛載卷類型為 hostPath,或者使用 PVC 卷進行掛載;
- PVC 是一層抽象接口,綁定的 PV 實體存儲后端類型可以根據需求自定義,可以是本地宿主機目錄, NFS,AWS EBS, GCE PD, Azure Disk, and Cinder volumes等等;
- PVC 綁定 PV 是根據 storage 大小、accessModes類型、以及相同的 storageClassName來綁定,其中 storage 大小、accessModes類型 必須是 PV的子集;
- StatefulSet 類型的資源可以在模板里面定義PVC資源,而不需要單獨配置PVC文件;
- StorageClass 動態持久化存儲可以由PVC資源自動生成PV資源,減少了維護成本