十、k8s入門系列----PV、PVC、StorageClass


  關於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上。

  

  總結一下:

  1. 根據 Container 一次性原則,Container銷毀時,里面的數據也會銷毀,所以需要保存的數據需要掛載到持久化存儲中;
  2. Container 保存數據數據可以選擇直接掛載宿主機目錄,即 掛載卷類型為 hostPath,或者使用 PVC 卷進行掛載;
  3. PVC 是一層抽象接口,綁定的 PV 實體存儲后端類型可以根據需求自定義,可以是本地宿主機目錄, NFS,AWS EBS, GCE PD, Azure Disk, and Cinder volumes等等;
  4. PVC 綁定 PV 是根據 storage 大小、accessModes類型、以及相同的 storageClassName來綁定,其中 storage 大小、accessModes類型 必須是 PV的子集;
  5. StatefulSet 類型的資源可以在模板里面定義PVC資源,而不需要單獨配置PVC文件;
  6. StorageClass 動態持久化存儲可以由PVC資源自動生成PV資源,減少了維護成本


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM