Volume 提供了很是好的數據持久化方案,不過在可管理性上還有不足。node
拿前面 AWS EBS 的例子來講,要使用 Volume,Pod 必須事先知道以下信息:mysql
當前 Volume 來自 AWS EBS。sql
EBS Volume 已經提早建立,而且知道確切的 volume-id。數據庫
Pod 一般是由應用的開發人員維護,而 Volume 則一般是由存儲系統的管理員維護。開發人員要得到上面的信息:安全
要麼詢問管理員。服務器
要麼本身就是管理員。app
這樣就帶來一個管理上的問題:應用開發人員和系統管理員的職責耦合在一塊兒了。若是系統規模較小或者對於開發環境這樣的狀況還能夠接受。但當集羣規模變大,特別是對於生成環境,考慮到效率和安全性,這就成了必需要解決的問題。ide
Kubernetes 給出的解決方案是 PersistentVolume 和 PersistentVolumeClaim。學習
PersistentVolume (PV) 是外部存儲系統中的一塊存儲空間,由管理員建立和維護。與 Volume 同樣,PV 具備持久性,生命週期獨立於 Pod。spa
PersistentVolumeClaim (PVC) 是對 PV 的申請 (Claim)。PVC 一般由普通用戶建立和維護。須要爲 Pod 分配存儲資源時,用戶能夠建立一個 PVC,指明存儲資源的容量大小和訪問模式(好比只讀)等信息,Kubernetes 會查找並提供知足條件的 PV。
有了 PersistentVolumeClaim,用戶只須要告訴 Kubernetes 須要什麼樣的存儲資源,而沒必要關心真正的空間從哪裏分配,如何訪問等底層細節信息。這些 Storage Provider 的底層信息交給管理員來處理,只有管理員才應該關心建立 PersistentVolume 的細節信息。
k8s-master nfs-server
k8s-node1 k8s-node2 nfs-client
全部節點安裝nfs
yum install -y nfs-common nfs-utils
在master節點建立共享目錄
[root@k8s-master k8s]# mkdir /nfsdata
受權共享目錄
[root@k8s-master k8s]# chmod 666 /nfsdata
編輯exports文件
[root@k8s-master k8s]# cat /etc/exports /nfsdata *(rw,no_root_squash,no_all_squash,sync)
配置生效
[root@k8s-master k8s]# export -r
啓動rpc和nfs(注意順序)
[root@k8s-master k8s]# systemctl start rpcbind [root@k8s-master k8s]# systemctl start nfs
做爲準備工做,咱們已經在 k8s-master 節點上搭建了一個 NFS 服務器,目錄爲 /nfsdata
:
下面建立一個 PV mypv1
,配置文件 nfs-pv1.yml
以下:
① capacity
指定 PV 的容量爲 1G。
② accessModes
指定訪問模式爲 ReadWriteOnce
,支持的訪問模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到單個節點。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多個節點。
ReadWriteMany – PV 能以 read-write 模式 mount 到多個節點。
③ persistentVolumeReclaimPolicy
指定當 PV 的回收策略爲 Recycle
,支持的策略有:
Retain – 須要管理員手工回收。
Recycle – 清除 PV 中的數據,效果至關於執行 rm -rf /thevolume/*
。
Delete – 刪除 Storage Provider 上的對應存儲資源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
④ storageClassName
指定 PV 的 class 爲 nfs
。至關於爲 PV 設置了一個分類,PVC 能夠指定 class 申請相應 class 的 PV。
⑤ 指定 PV 在 NFS 服務器上對應的目錄。
建立 mypv1
:
STATUS
爲 Available
,表示 mypv1
就緒,能夠被 PVC 申請。
接下來建立 PVC mypvc1
,配置文件 nfs-pvc1.yml
以下:
PVC 就很簡單了,只須要指定 PV 的容量,訪問模式和 class。
執行命令建立 mypvc1
:
從 kubectl get pvc
和 kubectl get pv
的輸出能夠看到 mypvc1
已經 Bound 到 mypv1
,申請成功。
上面已經建立好了pv和pvc,pod中直接使用這個pvc便可
與使用普通 Volume 的格式相似,在 volumes
中經過 persistentVolumeClaim
指定使用 mypvc1
申請的 Volume。
經過命令建立mypod1
:
可見,在 Pod 中建立的文件 /mydata/hello
確實已經保存到了 NFS 服務器目錄 /nfsdata
中。
若是再也不須要使用 PV,可用刪除 PVC 回收 PV。
當 PV 再也不須要時,可經過刪除 PVC 回收。
未刪除pvc以前 pv的狀態是Bound
刪除pvc以後pv的狀態變爲Available,,此時解除綁定後則能夠被新的 PVC 申請。
/nfsdata文件中的文件被刪除了
由於 PV 的回收策略設置爲 Recycle
,因此數據會被清除,但這可能不是咱們想要的結果。若是咱們但願保留數據,能夠將策略設置爲 Retain
。
經過 kubectl apply
更新 PV:
回收策略已經變爲 Retain
,經過下面步驟驗證其效果:
① 從新建立 mypvc1
。
② 在 mypv1
中建立文件 hello
。
③ mypv1
狀態變爲 Released
。
④ PV 中的數據被完整保留。
雖然 mypv1
中的數據獲得了保留,但其 PV 狀態會一直處於 Released
,不能被其餘 PVC 申請。爲了從新使用存儲資源,能夠刪除並從新建立 mypv1
。刪除操做只是刪除了 PV 對象,存儲空間中的數據並不會被刪除。
新建的 mypv1
狀態爲 Available
,已經能夠被 PVC 申請。
PV 還支持 Delete
的回收策略,會刪除 PV 在 Storage Provider 上對應存儲空間。NFS 的 PV 不支持 Delete
,支持 Delete
的 Provider 有 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
前面的例子中,咱們提早建立了 PV,而後經過 PVC 申請 PV 並在 Pod 中使用,這種方式叫作靜態供給(Static Provision)。
與之對應的是動態供給(Dynamical Provision),即若是沒有知足 PVC 條件的 PV,會動態建立 PV。相比靜態供給,動態供給有明顯的優點:不須要提早建立 PV,減小了管理員的工做量,效率高。
動態供給是經過 StorageClass 實現的,StorageClass 定義瞭如何建立 PV,下面是兩個例子。
StorageClass standard
:
StorageClass slow
:
這兩個 StorageClass 都會動態建立 AWS EBS,不一樣在於 standard
建立的是 gp2
類型的 EBS,而 slow
建立的是 io1
類型的 EBS。不一樣類型的 EBS 支持的參數可參考 AWS 官方文檔。
StorageClass 支持 Delete
和 Retain
兩種 reclaimPolicy
,默認是 Delete
。
與以前同樣,PVC 在申請 PV 時,只須要指定 StorageClass 和容量以及訪問模式,好比:
除了 AWS EBS,Kubernetes 支持其餘多種動態供給 PV 的 Provisioner,完整列表請參考 https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner
下面演示如何爲 MySQL 數據庫提供持久化存儲,步驟爲:
建立 PV 和 PVC。
部署 MySQL。
向 MySQL 添加數據。
模擬節點宕機故障,Kubernetes 將 MySQL 自動遷移到其餘節點。
驗證數據一致性。
首先建立 PV 和 PVC,配置以下:
mysql-pv.yml
mysql-pvc.yml
建立 mysql-pv
和 mysql-pvc
:
接下來部署 MySQL,配置文件以下:
PVC mysql-pvc
Bound 的 PV mysql-pv
將被 mount 到 MySQL 的數據目錄 var/lib/mysql
。
MySQL 被部署到 k8s-node2
,下面經過客戶端訪問 Service mysql
:
kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword
更新數據庫:
① 切換到數據庫 mysql。
② 建立數據庫表 my_id。
③ 插入一條數據。
④ 確認數據已經寫入。
關閉 k8s-node2
,模擬節點宕機故障。
驗證數據的一致性:
因爲node2節點已經宕機,node1節點接管了這個任務。
經過kubectl run 命令 進入node1的這個pod裏,查看數據是否依舊存在
MySQL 服務恢復,數據也無缺無損。
本章咱們討論了 Kubernetes 如何管理存儲資源。
emptyDir 和 hostPath 類型的 Volume 很方便,但可持久性不強,Kubernetes 支持多種外部存儲系統的 Volume。
PV 和 PVC 分離了管理員和普通用戶的職責,更適合生產環境。咱們還學習瞭如何經過 StorageClass 實現更高效的動態供給。
最後,咱們演示瞭如何在 MySQL 中使用 PersistentVolume 實現數據持久性。