Docker容器是有生命週期的,所以數據卷能夠實現數據持久化node
數據卷主要解決的問題:mysql
存儲類(Storage class)是k8s資源類型的一種,它是有管理員爲管理PV更加方便建立的一個邏輯組,能夠按照存儲系統的性能高低,或者綜合服務質量,備份策略等分類。不過k8s自己不知道類別究竟是什麼,它這是做爲一個描述。sql
存儲類的好處之一就是支持PV的動態建立,當用戶用到持久性存儲時,沒必要再去提早建立PV,而是直接建立PVC就能夠了,很是的方便。docker
存儲類對象的名稱很重要,而且出了名稱以外,還有3個關鍵字段shell
Provisioner(供給方):數據庫
及提供了存儲資源的存儲系統。k8s內建有多重供給方,這些供給方的名字都以「kubernetes.io」爲前綴。而且還能夠自定義。vim
Parameters(參數):存儲類使用參數描述要關聯到的存儲卷,注意不一樣的供給方參數也不一樣。api
reclaimPolicy:PV的回收策略,可用值有Delete(默認)和Retain網絡
emptyDir(空目錄):使用狀況比較少,通常只作臨時使用,相似Docker數據 持久化的:docker manager volume,該數據卷初始分配時,是一個空目錄,同一個Pod中的容器能夠對該目錄有執行讀寫操做,而且共享數據app
使用場景:在同一個Pod裏,不一樣的容器,共享數據卷
若是容器被刪除,數據仍然存在,若是Pod被刪除,數據也會被刪除
使用實例:
[root@master ~]# vim emptyDir.yaml apiVersion: v1 kind: Pod metadata: name: producer-consumer spec: containers: - image: busybox name: producer volumeMounts: - mountPath: /producer_dir //容器內的路徑 name: shared-volume //指定本地的目錄名 args: - /bin/sh - -c - echo "hello k8s" > /producer_dir/hello; sleep 30000 - image: busybox name: consumer volumeMounts: - mountPath: /consumer_dir name: shared-volume args: - /bin/sh - -c - cat /consumer_dir/hello; sleep 30000 volumes: - name: shared-volume //這裏的名字必須與上面的Pod的mountPath的name相對應 emptyDir: {} //定義數據持久化類型,即表示空目錄 [root@master ~]# kubectl applky -f emptyDir.yaml [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE producer-consumer 2/2 Running 0 14s [root@master ~]# kubectl logs producer-consumer consumer hello k8s
//使用inspect查看掛載的目錄在哪(查看Mount字段)
[root@master ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES producer-consumer 2/2 Running 0 69s 10.244.1.2 node01 <none> <none> //能夠看到容器運行在node01上,在node01上找到這個容器並查看並查看詳細信息 [root@node01 ~]# docker ps CONTAINER ID IMAGE f117beb235cf busybox 13c7a18109a1 busybox [root@node01 ~]# docker inspect 13c7a18109a1 "Mounts": [ { "Type": "bind", "Source": "/var/lib/kubelet/pods/5225f542-0859-4a6a-8d99-1f23b9781807/volumes/kubernetes.io~empty-dir/shared-volume", "Destination": "/producer_dir", //容器內的掛載目錄 "Mode": "", "RW": true, "Propagation": "rprivate" //再查看另外一個容器 [root@node01 ~]# docker inspect f117beb235cf "Mounts": [ { "Type": "bind", "Source": "/var/lib/kubelet/pods/5225f542-0859-4a6a-8d99-1f23b9781807/volumes/kubernetes.io~empty-dir/shared-volume", "Destination": "/consumer_dir", //容器內的掛載目錄 "Mode": "", "RW": true, "Propagation": "rprivate" //能夠看到兩個容器使用的同一個掛載目錄 [root@node01 ~]# cd /var/lib/kubelet/pods/5225f542-0859-4a6a-8d99-1f23b9781807/volumes/kubernetes.io~empty-dir/shared-volume [root@node01 shared-volume]# ls hello [root@node01 shared-volume]# cat hello hello k8s
//將容器刪除,驗證目錄是否存在
[root@node01 ~]# docker rm -f 13c7a18109a1 13c7a18109a1 [root@node01 ~]# docker ps CONTAINER ID IMAGE a809717b1aa5 busybox f117beb235cf busybox //它會從新生成一個新的容器,來達到咱們用戶所指望的狀態,因此這個目錄仍是存在的
//刪除Pod
[root@master ~]# kubectl delete pod producer-consumer [root@master ~]# ls /var/lib/kubelet/pods/5225f542-0859-4a6a-8d99-1f23b9781807/volumes/kubernetes.io~empty-dir/shared-volume ls: 沒法訪問/var/lib/kubelet/pods/5225f542-0859-4a6a-8d99-1f23b9781807/volumes/kubernetes.io~empty-dir/shared-volume: 沒有那個文件或目錄 //Pod刪除後數據也會被刪除
hostPath Volume(使用場景也比較少):相似Docker數據持久化的:bind mount
將Pod所在節點的文件系統上某一個文件或目錄掛載進容器內
若是Pod被刪除,數據會保留,相比較emptyDir會好一點,不過,一旦host崩潰,hostPath也沒法訪問
docker或者k8s集羣自己的存儲會採用hostPath這種方式
k8s集羣中會有不少pod,若是都是用hostPath Volume的話管理起來很不方便,因此就用到了PV
Persistent Volume | PV(持久卷)提早作好的,數據持久化的數據存放目錄
是集羣中的一塊存儲空間,由集羣管理員管理或者由Storage class(存儲類)自動管理,PV和pod、deployment、Service同樣,都是一個資源對象
PersistentVolume(PV)是集羣中已由管理員配置的一段網絡存儲。 集羣中的資源就像一個節點是一個集羣資源。 PV是諸如卷之類的卷插件,可是具備獨立於使用PV的任何單個pod的生命週期。 該API對象捕獲存儲的實現細節,即NFS,iSCSI或雲提供商特定的存儲系統
Psesistent Volume Claim | PVC(持久卷使用聲明|申請)
PVC表明用戶使用存儲的請求,應用申請PV持久化空間的一個申請、聲明。K8s集羣可能會有多個PV,你須要不停的爲不一樣的應用建立多個PV
它相似於pod。Pod消耗節點資源,PVC消耗存儲資源。 pod能夠請求特定級別的資源(CPU和內存)。 權限要求能夠請求特定的大小和訪問模式
官方文檔有更詳細的說明:https://www.kubernetes.org.cn/pvpvcstorageclass
基於NFS服務來作的PV
[root@master ~]# yum -y install nfs-utils (須要節點所有下載,會報掛載類型錯誤) [root@master ~]# yum -y install rpcbind [root@master ~]# mkdir /nfsdata [root@master ~]# vim /etc/exports /nfsdata *(rw,sync,no_root_squash) [root@master ~]# systemctl start rpcbind [root@master ~]# systemctl start nfs-server [root@master ~]# showmount -e Export list for master: /nfsdata *
1.建立PV(實際的存儲目錄) 2.建立PVC 3.建立pod
建立PV資源對象:
[root@master ~]# vim nfs-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: test-pv spec: capacity: //PV容量的大小 storage: 1Gi accessModes: //PV支持的訪問模式 - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle //PV的存儲空間的回收策略是什麼 storageClassName: nfs nfs: path: /nfsdata/pv1 server: 192.168.1.70 [root@master ~]# kubectl apply -f nfs-pv.yaml [root@master ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE test-pv 1Gi RWO Recycle Available nfs 9m30s
accessModes: (PV支持的訪問模式)
- ReadWriteOnce:能以讀-寫的方式mount到單個節點
- ReadWariteMany:能以讀-寫的方式mount到多個節點
- ReadOnlyOnce:能以只讀的方式mount到單個節點
persistentVolumeReclaimPolicy:(PV的存儲空間的回收策略是什麼)
Recycle:自動清除數據
Retain:須要管理員手動回收
Delete:雲存儲專用。直接刪除數據
PV和PVC相互的關聯:經過的是storageClassName && accessModes
建立PVC
[root@master ~]# vim nfs-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc spec: accessModes: //訪問模式 - ReadWriteOnce resources: requests: storage: 1Gi //申請的容量大小 storageClassName: nfs //向哪一個PV申請 [root@master ~]# kubectl apply -f nfs-pvc.yaml [root@master ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-pvc Bound test-pv 1Gi RWO nfs 14s
建立一個Pod資源:
[root@master ~]# vim pod.yaml kind: Pod apiVersion: v1 metadata: name: test-pod spec: containers: - name: pod1 image: busybox args: - /bin/sh - -c - sleep 30000 volumeMounts: - mountPath: "/mydata" name: mydata volumes: - name: mydata persistentVolumeClaim: claimName: test-pvc [root@master ~]# kubectl apply -f pod.yaml
以前建立PV的時候指定的掛載目錄是/nfsdata/pv1,咱們並無建立pv1這個目錄,因此這個pod是運行不成功的。
如下是排錯方法:
- kubectl describe
- kubectl logs
- /var/log/messages
- 查看該節點的kubelet的日誌
//使用kubectl describe [root@master ~]# kubectl describe pod test-pod mount.nfs: mounting 192.168.1.70:/nfsdata/pv1 failed, reason given by server: No such file or directory //提示沒有文件或目錄
建立目錄,再查看pod狀態:
[root@master ~]# mkdir /nfsdata/pv1 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-pod 1/1 Running 0 12m 10.244.1.3 node01 <none> <none>
驗證是否應用成功:
[root@master ~]# kubectl exec test-pod touch /mydata/hello [root@master ~]# ls /nfsdata/pv1/ hello [root@master ~]# echo 123 > /nfsdata/pv1/hello [root@master ~]# kubectl exec test-pod cat /mydata/hello 123
刪除Pod,驗證回收策略(Recycle):
[root@master ~]# kubectl delete pod test-pod [root@master ~]# kubectl delete pvc test-pvc [root@master ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE test-pv 1Gi RWO Recycle Available nfs 42h [root@master ~]# ls /nfsdata/pv1/ [root@master ~]# //驗證成功,數據已經回收
一般狀況下不會設置爲自動刪除,否則就和emptyDir就差很少了
刪除pv,修改回收策略:
以前是先建立PV--->PVC--->Pod,如今調整一下,先建立PV--->---Pod--->PVC
[root@master ~]# vim nfs-pv.yaml persistentVolumeReclaimPolicy: Retain [root@master ~]# kubectl apply -f nfs-pv.yaml [root@master ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE test-pv 1Gi RWO Retain Available nfs 7s [root@master ~]# kubectl apply -f pod.yaml [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE test-pod 0/1 Pending 0 5s //Pending正在被調度 [root@master ~]# kubectl describe pod test-pod Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 41s (x2 over 41s) default-scheduler persistentvolumeclaim "test-pvc" not found //沒有發現對應的pvc 建立pvc [root@master ~]# kubectl apply -f nfs-pvc.yaml [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE test-pod 1/1 Running 0 114s
驗證Retain(管理員手動刪除)回收策略:
[root@master ~]# kubectl exec test-pod touch /mydata/k8s [root@master ~]# ls /nfsdata/pv1/ k8s [root@master ~]# kubectl delete pod test-pod [root@master ~]# kubectl delete pvc test-pvc [root@master ~]# ls /nfsdata/pv1/ k8s //能夠看到並無回收 [root@master ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE test-pv 1Gi RWO Retain Available nfs 6s
mysql對數據持久化的應用:
//這裏就再也不建立PV,PVC了,用以前的就行
[root@master ~]# kubectl apply -f nfs-pvc.yaml [root@master ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-pvc Bound test-pv 1Gi RWO nfs 7s
建立Deploment資源對象,mysql容器
[root@master ~]# vim mysql.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: test-mysql spec: selector: matchLabels: //基於等值的標籤 app: mysql template: metadata: labels: app: mysql spec: containers: - image: mysql:5.6 name: mysql env: - name: MYSQL_ROOT_PASSWORD value: 123.com volumeMounts: - name: mysql-storage mountPath: /var/lib/mysql volumes: - name: mysql-storage persistentVolumeClaim: claimName: test-pvc [root@master ~]# kubectl get deployments. NAME READY UP-TO-DATE AVAILABLE AGE test-mysql 1/1 1 1 61s
進入容器建立數據,驗證是否應用PV:
[root@master ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-mysql-569f8df4db-fnnxc 1/1 Running 0 32m 10.244.1.5 node01 <none> <none> [root@master ~]# kubectl exec -it test-mysql-569f8df4db-fnnxc -- mysql -u root -p123.com mysql> create database yun33; //建立數據庫 mysql> use yun33; //選擇使用數據路 Database changed mysql> create table my_id( id int(4)); 建立表 mysql> insert my_id values(9527); //在表中插入數據 mysql> select * from my_id; //查看錶中全部數據 +------+ | id | +------+ | 9527 | +------+ 1 row in set (0.00 sec) [root@master ~]# ls /nfsdata/pv1/ auto.cnf ibdata1 ib_logfile0 ib_logfile1 k8s mysql performance_schema yun33
關閉node01節點,模擬節點宕機:
[root@master ~]# kubectl get pod -o wide -w NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-mysql-569f8df4db-fnnxc 1/1 Running 0 36m 10.244.1.5 node01 <none> <none> test-mysql-569f8df4db-fnnxc 1/1 Terminating 0 38m 10.244.1.5 node01 <none> <none> test-mysql-569f8df4db-2m5rd 0/1 Pending 0 0s <none> <none> <none> <none> test-mysql-569f8df4db-2m5rd 0/1 Pending 0 0s <none> node02 <none> <none> test-mysql-569f8df4db-2m5rd 0/1 ContainerCreating 0 0s <none> node02 <none> <none> test-mysql-569f8df4db-2m5rd 1/1 Running 0 2s 10.244.2.4 node02 <none> <none> [root@master ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-mysql-569f8df4db-2m5rd 1/1 Running 0 20s 10.244.2.4 node02 <none> <none> test-mysql-569f8df4db-fnnxc 1/1 Terminating 0 38m 10.244.1.5 node01 <none> <none>
驗證:在node02上新生成的pod,它內部是否有咱們建立的數據
[root@master ~]# kubectl exec -it test-mysql-569f8df4db-2m5rd -- mysql -u root -p123.com mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | yun33 | +--------------------+ 4 rows in set (0.01 sec) mysql> use yun33; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +-----------------+ | Tables_in_yun33 | +-----------------+ | my_id | +-----------------+ 1 row in set (0.01 sec) mysql> select * from my_id; +------+ | id | +------+ | 9527 | +------+ 1 row in set (0.01 sec) [root@master ~]# ls /nfsdata/pv1/ auto.cnf ibdata1 ib_logfile0 ib_logfile1 k8s mysql performance_schema yun33