K8s數據持久化之自動創建PV

在前兩篇實現k8s的數據持久化的流程爲:搭建nfs底層存儲===》創建PV====》創建PVC===》創建pod。最終pod中的container實現數據的持久化。

上述流程中,看似沒什麼問題,但細想一下,PVC在向PV申請存儲空間的時候,是根據指定的pv名稱、訪問模式、容量大小來決定具體向哪個PV來申請空間的,如果PV的容量爲20G,定義的訪問模式是WRO(只允許以讀寫的方式掛載到單個節點),而PVC申請的存儲空間爲10G,那麼一旦這個PVC是向上面的PV申請的空間,也就是說,那個PV有10個G的空間被浪費了,因爲其只允許被單個節點掛載。就算不考慮這個問題,我們每次手動去創建PV也就比較麻煩的事情,這時,我們就需要一個自動化的工具來替我們創建PV。

這個東西就是阿里提供的一個開源鏡像“nfs-client-provisioner”,這個東西是通過k8s內置的NFS驅動掛載遠端的NFS服務器到本地目錄,然後自身作爲storage(存儲)。

當然,PVC是無法直接去向nfs-client-provisioner申請使用的存儲空間的,這時,就需要通過SC(storageClass)這個資源對象去申請了,SC的根本作用就是根據PVC定義的值去自動創建PV。

下面是一個Nginx基於自動創建PV實現數據持久化的示例。

1、搭建nfs服務

爲了方便,我這裏直接在master上做nfs。

[root@master ~]# yum -y install nfs-utils
[root@master ~]# systemctl enable rpcbind
[root@master lv]# mkdir -p /nfsdata
[root@master ~]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash)
[root@master ~]# systemctl start nfs-server
[root@master ~]# systemctl enable nfs-server
[root@master ~]# showmount -e
Export list for master:
/nfsdata *

2、創建rbac授權

這種自動創建pv的方式涉及到了rbac授權。

[root@master ~]# vim rbac-rolebind.yaml    #創建rbac授權用戶,在以下文件必須指定名稱空間,哪怕是default

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-provisioner-runner
  namespace: default
rules:
   -  apiGroups: [""]
      resources: ["persistentvolumes"]
      verbs: ["get", "list", "watch", "create", "delete"]
   -  apiGroups: [""]
      resources: ["persistentvolumeclaims"]
      verbs: ["get", "list", "watch", "update"]
   -  apiGroups: ["storage.k8s.io"]
      resources: ["storageclasses"]
      verbs: ["get", "list", "watch"]
   -  apiGroups: [""]
      resources: ["events"]
      verbs: ["watch", "create", "update", "patch"]
   -  apiGroups: [""]
      resources: ["services", "endpoints"]
      verbs: ["get","create","list", "watch","update"]
   -  apiGroups: ["extensions"]
      resources: ["podsecuritypolicies"]
      resourceNames: ["nfs-provisioner"]
      verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
[root@master ~]# kubectl apply -f rbac-rolebind.yaml      #執行yaml文件

3、創建nfs-client-provisioner容器

[root@master ~]# vim nfs-deployment.yaml       #編寫yaml文件

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  namespace: default
spec:
  replicas: 1               #副本數量爲1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccount: nfs-provisioner       #指定賬戶
      containers:
        - name: nfs-client-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner   #使用的是這個鏡像
          volumeMounts:
            - name: nfs-client-root
              mountPath:  /persistentvolumes      #指定容器內的掛載目錄
          env:
            - name: PROVISIONER_NAME        #這是這個容器內置的變量
              value: ljz-test         #這是上面變量的值(名字)
            - name: NFS_SERVER       #內置變量,用於指定nfs服務的IP
              value: 192.168.20.6            
            - name: NFS_PATH              #內置變量,指定的是nfs共享的目錄
              value: /nfsdata
      volumes:              #這下面是指定上面掛載到容器內的nfs的路徑及IP
        - name: nfs-client-root
          nfs:
            server: 192.168.20.6
            path: /nfsdata
[root@master ~]# kubectl apply -f nfs-deployment.yaml          #執行yaml文件

4、創建SC(StorageClass)

[root@master ~]# vim test-storageclass.yaml   #編寫yaml文件

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: statefu-nfs
  namespace: default
provisioner: ljz-test     #這裏要和第三個nfs-client-provisioner的env環境變量中的value值對應。
reclaimPolicy: Retain        #回收策略爲:retain,還有一個默認的值爲“default”

[root@master ~]# kubectl apply -f test-storageclass.yaml    #執行yaml文件

5、創建PVC

[root@master ~]# vim test-pvc.yaml      #編寫yaml文件

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-claim
  namespace: default        
spec:
  storageClassName: statefu-nfs                 #定義存儲類的名字,要和SC的名字對應
  accessModes:
    - ReadWriteMany          #訪問模式爲RWM
  resources:
    requests:
      storage: 500Mi
[root@master ~]# kubectl apply -f test-pvc.yaml      #執行yaml文件
#查看是否自動創建了PV併爲bound狀態
[root@master ~]# kubectl get pv,pvc 
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS   REASON   AGE
persistentvolume/pvc-355593f0-2dfd-4b48-a3c6-c58d4843bcf4   500Mi      RWX            Delete           Bound    default/test-claim   statefu-nfs             2m53s

NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/test-claim   Bound    pvc-355593f0-2dfd-4b48-a3c6-c58d4843bcf4   500Mi      RWX            statefu-nfs    2m53s

其實至此,我們已經實現了根據PVC的申請存儲空間去自動創建PV(本地的nfs共享目錄下已經生成了一個目錄,名字挺長的,是pv+pvc名字定義的目錄名),至於這個PVC申請的空間是給哪個pod使用,這已經無所謂了。

6、創建基於Nginx鏡像的pod

[root@master ~]# vim nginx-pod.yaml   #編寫yaml文件

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myweb
  namespace: default
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: myweb
        image: nginx:latest
        volumeMounts:
        - name: myweb-persistent-storage
          mountPath: /usr/share/nginx/html/
      volumes:
      - name: myweb-persistent-storage
        persistentVolumeClaim:
          claimName: test-claim           #這的名字要和PVC的名字一致
[root@master ~]# kubectl apply -f nginx-pod.yaml       #執行yaml文件

當執行上述的yaml文件後,nginx容器內的網頁目錄就和本地的nfs共享目錄關聯起來了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章