PV和PVC概念
PVC描述的則是Pod所希望使用的持久化存儲的屬性.比如Volume 存儲的大小、可讀寫權限等等
PVC對象通常由開發人員創建或者以PVC模板的方式成為StatefulSet的一部分,然后由StatefulSet控制器負責創建帶編號的PVC
PVC要真正被容器使用起來就必須先和某個符合條件的PV進行綁定兩者實現綁定要滿足的兩個條件
1.當然是PV和PVC的spec字段.比如PV的存儲(storage)大小,就必須滿足PVC的要求
2.PV和PVC的storageClassName字段必須一樣
PVC和PV進行綁定之后Pod就能夠像使用hostPath等常規類型的Volume一樣
創建Pod的時候系統里並沒有合適的PV跟它定義的PVC綁定,也就是說此時容器想要使用的Volume不存在的時候Pod的啟動就會報錯
架構設計
Kubernetes中實際上存在着一個專門處理持久化存儲的控制器,叫作Volume Controller.這個Volume Controller 維護着多個控制循環,其中有一個循環扮演的就是撮合PV和PVC的角色.它的名字叫作 PersistentVolumeController.
PersistentVolumeController會不斷地查看當前每一個PVC是不是已經處於 Bound(已綁定)狀態.如果不是,那它就會遍歷所有的、可用的PV,並嘗試將其與這個PVC進行綁定.這樣Kubernetes就可以保證用戶提交的每一個PVC只要有合適的PV 出現它就能夠很快進入綁定狀態
PV和PVC綁定的原理
將這個PV對象的名字填在了PVC對象的spec.volumeName字段上.所以接下來Kubernetes只要獲取到這個PVC對象就能夠找到它所綁定的PV
PV持久化存儲原理
容器的Volume其實就是將一個宿主機上的目錄跟一個容器里的目錄綁定掛載在了一起所謂的“持久化Volume”,指的就是這個宿主機上的目錄,具備“持久性”.即:這個目錄里面的內容,既不會因為容器的刪除而被清理掉,也不會跟當前的宿主機綁定.這樣,當容器被重啟或者在其他節點上重建出來之后,它仍然能夠通過pv編號掛載這個Volume
Kubernetes需要做的工作,就是使用這些存儲服務,來為容器准備一個持久化的宿主機目錄,以供將來進行綁定掛載時使用.而所謂“持久化”,指的是容器在這個目錄里寫入的文件,都會保存在遠程存儲中,從而使得這個目錄具備了“持久性”
持久化Volume的實現,往往依賴於一個遠程存儲服務
掛載目錄的實現
1.遠程文件存儲(比如,NFS、GlusterFS)
遠程文件存儲服務相當於直接提供存儲目錄 直接可以掛載使用
mount -t nfs <NFS服務器地址>:/var/lib/kubelet/pods/pod_id/volumes/kubernetes.io~volume類型/volume名字
通過這個掛載操作Volume的宿主機目錄就成為了一個遠程 NFS目錄的掛載點,后面在這個目錄里寫入的所有文件都會被保存在遠程 NFS 服務器上.所以我們也就完成了對這個 Volume 宿主機目錄的“持久化"
2.遠程塊存儲(比如,公有雲提供的遠程磁盤)
相當於一塊磁盤 磁盤在第一次使用之前必須先對磁盤進行格式化,否則無法寫入文件
1.先把遠程磁盤掛載到Pod所在的宿主機上
gcloud compute instances attach-disk <虛擬機名字> --disk <遠程磁盤名字>
2.格式化磁盤設備創建掛載目錄
# 通過lsblk命令獲取磁盤設備ID
$ lsblk
# 格式化成ext4格式
$ mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/<磁盤設備ID>
# 把格式化后的磁盤掛載到volume目錄
mkdir -p /var/lib/kubelet/pods/pod_id/volumes/kubernetes.io~volume類型/volume名字
Kubernetes需要做的工作,就是使用這些存儲服務,來為容器准備一個持久化的宿主機目錄,以供將來進行綁定掛載時使用.而所謂“持久化”,指的是容器在這個目錄里寫入的文件,都會保存在遠程存儲中,從而使得這個目錄具備了“持久性”
創建持久化宿主機目錄
當一個Pod調度到一個節點上之后kubelet就要負責為這個Pod創建它的Volume 目錄.默認情況下,kubelet為Volume創建的目錄是如下所示的一個宿主機上的路徑/var/lib/kubelet/pods/pod_id/volumes/kubernetes.io~volume類型/volume名字
把持久化目錄掛載到容器中
經過了attach和mount兩階段我們就得到了一個“持久化”的Volume 宿主機目錄.所以接下來kubelet只要把這個Volume目錄通過CRI里的Mounts參數,傳遞給Docker然后就可以為Pod里的容器掛載這個“持久化”的Volume 了.其實,這一步相當於執行了如下所示的命令:docker run -v /var/lib/kubelet/pods/pod_id/volumes/kubernetes.io~volume類型/volume名字:/<容器內的目標目錄> 我的鏡像...
StorageClass動態創建PV
需要后台存儲插件支持Dynamic Provisioning機制 如果不支持就不能用StorageClass動態創建pv.StorageClass並不是專門為了Dynamic Provisioning而設計的
可以通過設置storageClassName來控制pv和pvc的綁定關系. storageClassName可以是任何一個字符串
集群已經開啟名叫DefaultStorageClass的Admission Plugin,它就會為PVC和PV自動添加一個默認的StorageClass;否則PVC的storageClassName 的值就是" "這也意味着它只能夠跟storageClassName也是" "的PV進行綁定
PVC 描述的是Pod想要使用的持久化存儲的屬性,比如存儲的大小、讀寫權限等
PV 描述的則是一個具體的Volume的屬性,比如Volume的類型、掛載目錄、遠程存儲服務器
StorageClass的作用則是充當PV的模板.並且只有同屬於一個StorageClass的PV和PVC才可以綁定在一起
StorageClass的另一個重要作用,是指定PV的 Provisioner(存儲插件).這時候,如果存儲插件支持Dynamic Provisioning 的話k8s就可以自動為你創建PV
Local Persistent Volume設計
希望Kubernetes能夠直接使用宿主機上的本地磁盤目錄,而不依賴於遠程存儲服務,來提供“持久化”的容器Volume
這樣做的好處很明顯由於這個Volume直接使用的是本地磁盤尤其是SSD盤,它的讀寫性能相比於大多數遠程存儲來說,要好得多
這個需求對本地物理服務器部署的私有Kubernetes集群來說 非常常見
常規PVC和Local PV的區別:
對於常規的PV來說Kubernetes都是先調度Pod到某個節點上,然后再通過“兩階段處理”來“持久化”這台機器上的Volume 目錄,進而完成Volume目錄與容器的綁定掛載
對於Local PV來說,節點上可供使用的磁盤(或者塊設備)必須是運維人員提前准備好的.它們在不同節點上的掛載情況可以完全不同,甚至有的節點可以沒這種磁盤
這時候調度器就必須能夠知道所有節點與Local Persistent Volume對應的磁盤的關聯關系,然后根據這個信息來調度Pod
延遲綁定機制:
默認情況下 用戶在提交PV和PVC的YAML 文件之后,Kubernetes 就會根據它們倆的屬性,以及它們指定的StorageClass來進行綁定.只有綁定成功后Pod才能通過聲明這個 PVC 來使用對應的PV
PVC和PV的綁定是由獨立運行的控制循環來執行的 相當於是實時的 Volume檢測循環和Pod的調度循環是異步的 PV和PVC綁定完成后 調用該PV的Pod可能還沒有被調度
延遲綁定機制就是確保PVC和PV的綁定操作推遲到使用該PV的Pod進行調度的時候 這樣可以讓調度器綜合考慮所有的調度規則同時也包含了PV所在的節點位置來統一決定這個Pod聲明的PVC具體和哪個PV進行綁定
通過這個延遲綁定機制,原本實時發生的PVC和PV的綁定過程,就被延遲到了 Pod 第一次調度的時候在調度器中進行,從而保證了這個綁定結果不會影響Pod的正常調度