① 持久化存儲之 PV、PVC、StorageClass
容器化一個應用比較麻煩的地方,就是對於有狀態的服務的管理,最常見的狀態就是 存儲狀態 。
創建的PVC只有和對應的PV綁定才可以使用
綁定條件:
成功綁定之後,Pod 就是聲明PVC綁定的持久化存儲了,使用方法如下:
Pod 只需要在 volumes 欄位里聲明要使用的 PVC 的name,等Pod創建後,Kubelet會將 PVC 綁定的 PV, 例如上面的 NFS 類型的 volume 掛載到容器內目錄。
PVC 和 PV 的設計,其實跟「面向對象」的思想完全一致
當每次創建 PVC 聲明使用存儲時,都需要去手動的創建 PV,來滿足 PVC 的使用。
可以用一種機制來根據用戶聲明的存儲使用銷拿量(PVC)來動態的創建對應的持久化存儲卷(PV)。k8s 用 StorageClass 來實現動態創建 持久化存儲。
存儲控制器 Volume Controller,是用來專門處理持久化存儲的控制器,其一個子控制循環 PersistentVolumeController 負責實現 PV 和 PVC 的綁定。
PersistentVolumeController 會 watch kube-apiserver 的 PVC 對象。如果發現有 PVC對棚斗卜象創建,則會查看所有可用的 PV, 如果有則綁定,若沒有,則會使用 StorageClass 的配置和 PVC 的描述創建 PV 進行綁定鏈穗。
所謂將一個 PV 與 PVC 進行「綁定」,其實就是將這個PV對象的名字,填在了 PVC 對象的 spec.volumeName 欄位上
② 在K8S中使用Local持久卷
由於容器本身是非持久宴敏化的,因此需要解決在容器中運行應用程序遇到的一些問題。首先,當容器崩潰時,kubelet將重新啟動容器,但是寫入容器的文件將會丟失,容器將會以鏡像的初始狀態重新開始;第二,在通過一個Pod中一起運行的容器,通常需要共享容器之間一些文件。Kubernetes通過卷解決上述的兩個問題。
在Docker有卷的概念卷,但Docker中存儲卷只是磁碟的或另一個容器中的目錄,並沒有對其生命周期進行管理。Kubernetes的存儲卷有自己的生命周期,它的生命周期與使用的它Pod生命周期一致。因此,相比於在Pod中運行的容器來說,存儲卷的存在時間會比的其中的任何容器都長,並且在容器重新啟動時會保留數據。當然,當Pod停止存在時,存儲卷也將不再存在。在Kubernetes支持多種類型的卷,而Pod可以同時使用各種類型和任意數量的存儲卷。在Pod中通過指定下面的欄位來使用存儲卷:
PV是系統管理員設置的存儲,晌陵枝它是群集的一部分,是一種資源,所以它有獨立於Pod的生命周期。
PVC是用戶存儲的請求。它與Pod相似,Pod消耗節點的CPU和內存資源,PVC則消耗PV資源,可以生命特定的容量大小和訪問模式。
PV和PVC遵循如下的生命周期管理
PV有兩種配置方式:靜態或動態
要啟用基於存儲級別的動態存儲配置汪斗,集群管理員需要啟用 API server 上的 DefaultStorageClass 准入控制器 。例如,通過確保 DefaultStorageClass 位於 API server 組件的 --admission-control 標志,使用逗號分隔的有序值列表中,可以完成此操作。有關 API server 命令行標志的更多信息,請檢查 kube-apiserver 文檔。
一旦用戶創建或已經創建了具有特定存儲量的 PersistentVolumeClaim 以及某些訪問模式。Kubernetes控制器會監視到新的 PVC,並尋找匹配的 PV,並將它們綁定在一起。如果為新的 PVC 動態調配 PV,則控制器會始終將該 PV 綁定到 PVC。總之,用戶總會得到他們所請求的存儲,但是容量可能超出請求的數量。一旦 PV 和 PVC 綁定後,PersistentVolumeClaim 綁定是排他性的,不管它們是如何綁定的。 PVC 跟 PV 綁定是一對一的映射。
如果沒有匹配的PV,PVC將無限期地保持未綁定狀態。隨著匹配PV的可用,PVC將被綁定。例如,配置了許多 50Gi PV的集群將不會匹配請求 100Gi 的PVC。將100Gi PV 添加到群集時,則可以綁定到該 PVC。
Pod 使用PVC作為卷。集群檢查PVC以查找綁定的卷並為集群掛載該卷。對於支持多種訪問模式的卷,用戶指定在使用聲明作為容器中的卷時所需的模式(讀寫、只讀)。
用戶生命了PVC,並且該PVC是綁定的,則只要用戶需要,綁定的 PV 就屬於該用戶。用戶通過在 Pod 的 volume 配置中包含persistentVolumeClaim來調度 Pod 並訪問用戶聲明的 PV。
K8S支持的卷類型很多,主要分為分布式文件系統、ConfigMap和本地文件系統這幾種,其中本地文件系統支持:hostPath和local(從1.11開始出了Beta版本,編寫本文時目前K8S最新版本是1.13了)。
在我們目前項目的實際開發中,我們常用兩種卷掛載模式:
但是對於使用到本地磁碟來存儲數據時,hostPath往往不太適合我們了,雖然它能夠讓Pod使用本地存儲,將Node文件系統中的文件或者目錄掛載到容器內,但是在這種應用場景,hostPath並不適合生產環境使用,主要原因如下:
當然hostPath還有其他的缺點,由於以上這兩個關鍵的缺陷,在真正需要持久化數據存儲的場景,我們不得不考慮local存儲卷了。
Local PV是從kuberntes 1.10開始引入,本質目的是為了解決hostPath的缺陷。通過PV控制器與Scheler的結合,會對local PV做針對性的邏輯處理,從而,讓Pod在多次調度時,能夠調度到同一個Node上。
首先,我們要准備好K8S環境,檢查一下K8S中的節點。
現在登錄到節點10.25.68.239上,然後手工創建一個目錄,我們將後在後面創建的local PV綁定到這個目錄中。
創建local的Storage Class
查看一下創建的storage class
創建PV:
查看一下pv情況
創建PVC
PVC將會一直處於Pending狀態直到我們創建一個Pod使用它。
創建一個deployment使用這個pvc。
pvc現在綁定到對應的pv上面了。
查看pod被調度的節點,可以看到這個pod是會被調度到PV所在的Node:
我們再次登錄到10.25.68.239,在/data/pv下生成index.html文件
檢查一下index.html文件的服務
Local持久卷基本具備了hostPath的綁定本地文件系統目錄的能力和方便性,同時自動具備調度到指定節點的能力,並且可以對持久卷進行管理。
唯一的問題在於,我們還需要手工去對應的節點創建對應的目錄和刪除對應的目錄,這需要結合我們的應用系統來進行統一的設計和管理。
總得來說,對於狀態應用程序的部署來說,Local持久卷能夠提供分布式存儲無法提供的高性能,同時具備了一定的調度的靈活性,是一個不錯的選擇。