經過博文Kubernetes的存儲之Volume能夠了解到Kubernets實現數據持久化的流程爲:
搭建NFS底層存儲——>建立PV——>建立PVC——>建立pod
最終將pod中的container實現數據的持久化!html
從上述流程中,看似沒有什麼問題,可是仔細研究就會發現:PVC在向PV申請存儲空間時,是根據指定PV的名稱、訪問模式、容量大小來決定具體向哪一個PV申請空間的。nginx
打比方說:若是PV的容量是20G,定義的訪問模式是WRO(只容許以讀寫的方式掛載到單個節點),而PVC申請的存儲空間爲10G,那麼一旦這個PVC是向上述的PV申請的空間,也就是說,那麼PV有10G的空間被白白浪費了,由於其只容許單個節點掛載。這是一個很是嚴重的問題。就算不考慮這個問題,咱們每次手動去建立PV也是比較麻煩的事情,這是就須要使用一個自動化的方案來替咱們建立PV。這個自動化的方案就是——Storage Class(存儲類)!web
Storage class(存儲類)概述vim
Storage class(存儲類)是Kubernetes資源類型的一種,它是由管理員爲管理PV更加方便而建立的一個邏輯組,能夠按照存儲系統的性能高低、綜合服務質量、備份策略等分類。不過Kubernetes自己並不知道類別究竟是什麼,這是一個簡單的描述而已!api
存儲類的好處之一就是支持PV的動態建立,當用戶用到持久化存儲時,沒必要再去提早建立PV,而是直接建立PVC就能夠了,很是的方便。同時也避免了空間的浪費!bash
Storage class(存儲類)三個重要的概念:
1)Provisioner(供給方、提供者):提供了存儲資源的存儲系統。Kubernetes內部多重供給方,這些供給方的名字都以「kubernetes.io」爲前綴。而且還能夠自定義;
2)Parameters(參數):存儲類使用參數描述要關聯到的存儲卷,注意不一樣的供給方參數也不一樣;
3)ReclaimPlicy:pv的回收策略,可用的值有Delete(默認)和Retain;服務器
下面經過一個nginx基於自動建立PV實現數據持久化的案例進一步的瞭解Storage Class的具體使用!app
爲了方便,就直接在master節點上部署NFS存儲了!ide
[root@master ~]# yum -y install nfs-utils rpcbind [root@master ~]# vim /etc/exports /nfsdata *(rw,sync,no_root_squash) [root@master ~]# systemctl start nfs-server [root@master ~]# systemctl start rpcbind [root@master ~]# showmount -e Export list for master: /nfsdata *
這種自動建立PV的方式涉及到了rbac受權機制,關於rbac受權機制這裏先不詳細介紹,隨後再更新說明。性能
[root@master ~]# vim rbac-rolebind.yaml kind: Namespace #建立一個名稱空間,名稱爲xiaojiang-test apiVersion: v1 metadata: name: xiaojiang-test --- apiVersion: v1 #建立一個用於認證的服務帳號 kind: ServiceAccount metadata: name: nfs-provisioner namespace: xiaojiang-test --- apiVersion: rbac.authorization.k8s.io/v1 #建立羣集規則 kind: ClusterRole metadata: name: nfs-provisioner-runner namespace: xiaojiang-test 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: xiaojiang-test roleRef: kind: ClusterRole name: nfs-provisioner-runner apiGroup: rbac.authorization.k8s.io [root@master ~]# kubectl apply -f rbac-rolebind.yaml #執行yaml文件
nfs-deployment的做用:其實它是一個NFS客戶端。但它經過K8S的內置的NFS驅動掛載遠端的NFS服務器到(容器內)本地目錄;而後將自身做爲storage provider,關聯storage class。
[root@master ~]# vim nfs-deployment.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nfs-client-provisioner namespace: xiaojiang-test spec: replicas: 1 #指定副本數量爲1 strategy: type: Recreate #指定策略類型爲重置 template: metadata: labels: app: nfs-client-provisioner spec: serviceAccount: nfs-provisioner #指定rbac yanl文件中建立的認證用戶帳號 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: lzj-test - name: NFS_SERVER #容器內的變量用於指定nfs服務的IP地址 value: 192.168.1.1 - name: NFS_PATH #容器內的變量指定nfs服務器對應的目錄 value: /nfsdata volumes: #指定掛載到容器內的nfs的路徑及IP - name: nfs-client-root nfs: server: 192.168.1.1 path: /nfsdata [root@master ~]# kubectl apply -f nfs-deployment.yaml #執行yaml文件 [root@master ~]# kubectl get pod -n xiaojiang-test NAME READY STATUS RESTARTS AGE nfs-client-provisioner-7cf975c58b-sc2qc 1/1 Running 0 6s
[root@master ~]# vim test-storageclass.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: stateful-nfs namespace: xiaojiang-test provisioner: lzj-test #這個要和nfs-client-provisioner的env環境變量中的PROVISIONER_NAME的value值對應。 reclaimPolicy: Retain #指定回收策略爲Retain(手動釋放) [root@master ~]# kubectl apply -f test-storageclass.yaml
[root@master ~]# vim test-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-claim namespace: xiaojiang-test spec: storageClassName: stateful-nfs #定義存儲類的名稱,需與SC的名稱對應 accessModes: - ReadWriteMany #訪問模式爲RWM resources: requests: storage: 100Mi [root@master ~]# kubectl apply -f test-pvc.yaml [root@master ~]# kubectl get pvc -n xiaojiang-test NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-claim Bound pvc-267b880d-5e0a-4e8e-aaff-3af46f21c6eb 100Mi RWX stateful-nfs 14s #保證pvc的狀態爲Bound,表示關聯成功 [root@master ~]# ls /nfsdata/ #能夠看出用於nfs存儲的目錄下生成了一個對應的目錄 xiaojiang-test-test-claim-pvc-267b880d-5e0a-4e8e-aaff-3af46f21c6eb
至此位置,咱們已經實現了根據PVC的申請存儲空間去自動建立PV(本地的nfs共享目錄下已經生成了一個目錄,名字挺長的,是pv+pvc名字定義的目錄名),至於這個PVC申請的空間是給哪一個pod使用,這已經無所謂了!
[root@master ~]# vim nginx-pod.yaml apiVersion: v1 kind: Pod metadata: name: myweb namespace: xiaojiang-test 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 [root@master ~]# kubectl get pod -n xiaojiang-test NAME READY STATUS RESTARTS AGE myweb 1/1 Running 0 38s nfs-client-provisioner-7cf975c58b-sc2qc 1/1 Running 0 60m
[root@master ~]# kubectl exec -it myweb -n xiaojiang-test /bin/bash root@myweb:/# cd /usr/share/nginx/html/ root@myweb:/usr/share/nginx/html# echo "hello world" > index.html #進入容器插入數據進行測試 [root@master ~]# cat /nfsdata/xiaojiang-test-test-claim-pvc-267b880d-5e0a-4e8e-aaff-3af46f21c6eb/index.html hello world #本地目錄測試沒有問題 [root@master ~]# kubectl exec -it nfs-client-provisioner-7cf975c58b-sc2qc -n xiaojiang-test /bin/sh / # ls nfs-client-provisioner nfs-client-provisioner #自動建立pv的可執行程序 / # cat /persistentvolumes/xiaojiang-test-test-claim-pvc-267b880d-5e0a-4e8e-aaff-3af46f21c6eb/index.html hello world #nfs-client容器對應的目錄數據也是存在的
從以上測試就能夠看出:nginx容器內的網頁目錄就、本地的nfs共享目錄、nfs-client容器中的目錄就所有關聯起來了。
————————————本文到此結束,感謝閱讀————————————————