應用上K8S第四步:如何選擇合適的持久卷

網路通訊頻道發表於2023-01-30

需求

應用或服務上K8S時,我們可能會面對如何選擇合適的持久捲來進一步保障其穩定執行。而在K8S中我們常見儲存方面的知識點如下:

Pod Volume,如:emptydir、hostpath;

持久卷(Persistent Volume)

持久卷申領(PersistentVolumeClaim,PVC)

儲存類(StorageClass)

靜態製備(Static Provisioning)

動態製備(Dynamic Provisioning)

以上知識點中基於存算分離設計理念的PV/PVC是整個儲存的核心,而基於儲存類的靜態製備和動態製備可滿足我們對不同儲存場景的需求。

儲存的分配方式

關於儲存的核心知識,我們在此直接引用阿里云云原生更加專業的文章來進行解析。

阿里云云原生https://developer.aliyun.com/article/720251

Pod Volumes

首先來看一下 Pod Volumes 的使用場景:

場景一:如果 pod 中的某一個容器在執行時異常退出,被 kubelet 重新拉起之後,如何保證之前容器產生的重要資料沒有丟失?

場景二:如果同一個 pod 中的多個容器想要共享資料,應該如何去做?

以上兩個場景,其實都可以藉助 Volumes 來很好地解決,接下來首先看一下 Pod Volumes 的常見型別:

1.本地儲存,常用的有 emptydir/hostpath;

2.網路儲存:網路儲存當前的實現方式有兩種,一種是 in-tree,它的實現程式碼是放在 K8s 程式碼倉庫中的,隨著 K8s 對儲存型別支援的增多,這種方式會給 K8s 本身的維護和發展帶來很大的負擔;而第二種實現方式是 out-of-tree,它的實現其實是給 K8s 本身解耦的,透過抽象介面將不同儲存的 driver 實現從 K8s 程式碼倉庫中剝離,因此 out-of-tree 是後面社群主推的一種實現網路儲存外掛的方式;

3.Projected Volumes:它其實是將一些配置資訊,如 secret/configmap 用卷的形式掛載在容器中,讓容器中的程式可以透過 POSIX 介面來訪問配置資料;

4.PV 與 PVC 就是今天要重點介紹的內容。

Persistent Volumes

接下來看一下 PV(Persistent Volumes)。既然已經有了 Pod Volumes,為什麼又要引入 PV 呢?我們知道 pod 中宣告的 volume 生命週期與 pod 是相同的,以下有幾種常見的場景:

場景一:pod 重建銷燬,如用 Deployment 管理的 pod,在做映象升級的過程中,會產生新的 pod並且刪除舊的 pod ,那新舊 pod 之間如何複用資料?

場景二:宿主機當機的時候,要把上面的 pod 遷移,這個時候 StatefulSet 管理的 pod,其實已經實現了帶卷遷移的語義。這時透過 Pod Volumes 顯然是做不到的;

場景三:多個 pod 之間,如果想要共享資料,應該如何去宣告呢?我們知道,同一個 pod 中多個容器想共享資料,可以藉助 Pod Volumes 來解決;當多個 pod 想共享資料時,Pod Volumes 就很難去表達這種語義;

場景四:如果要想對資料卷做一些功能擴充套件性,如:snapshot、resize 這些功能,又應該如何去做呢?

以上場景中,透過 Pod Volumes 很難準確地表達它的複用/共享語義,對它的擴充套件也比較困難。因此 K8s 中又引入了 **Persistent Volumes **概念,它可以將儲存和計算分離,透過不同的元件來管理儲存資源和計算資源,然後解耦 pod 和 Volume 之間生命週期的關聯。這樣,當把 pod 刪除之後,它使用的 PV 仍然存在,還可以被新建的 pod 複用。

PVC 設計意圖

瞭解 PV 後,應該如何使用它呢?使用者在使用 PV 時其實是透過 PVC,為什麼有了 PV 又設計了 PVC 呢?主要原因是為了簡化 K8s 使用者對儲存的使用方式,做到職責分離。通常使用者在使用儲存的時候,只用宣告所需的儲存大小以及訪問模式。訪問模式是什麼?其實就是:我要使用的儲存是可以被多個 node 共享還是隻能單 node 獨佔訪問(注意是 node level 而不是 pod level)?只讀還是讀寫訪問?使用者只用關心這些東西,與儲存相關的實現細節是不需要關心的。透過 PVC 和 PV 的概念,將使用者需求和實現細節解耦開,使用者只用透過 PVC 宣告自己的儲存需求。PV是有叢集管理員和儲存相關團隊來統一運維和管控,這樣的話,就簡化了使用者使用儲存的方式。可以看到,PV 和 PVC 的設計其實有點像物件導向的介面與實現的關係。使用者在使用功能時,只需關心使用者介面,不需關心它內部複雜的實現細節。既然 PV 是由叢集管理員統一管控的,接下來就看一下 PV 這個物件是怎麼產生的。

Static Volume Provisioning

第一種產生方式:靜態產生方式 - 靜態 Provisioning。

靜態 Provisioning:由叢集管理員事先去規劃這個叢集中的使用者會怎樣使用儲存,它會先預分配一些儲存,也就是預先建立一些 PV;然後使用者在提交自己的儲存需求(也就是 PVC)的時候,K8s 內部相關元件會幫助它把 PVC 和 PV 做繫結;之後使用者再透過 pod 去使用儲存的時候,就可以透過 PVC 找到相應的 PV,它就可以使用了。靜態產生方式有什麼不足呢?可以看到,首先需要叢集管理員預分配,預分配其實是很難預測使用者真實需求的。舉一個最簡單的例子:如果使用者需要的是 20G,然而叢集管理員在分配的時候可能有 80G 、100G 的,但沒有 20G 的,這樣就很難滿足使用者的真實需求,也會造成資源浪費。有沒有更好的方式呢?

Dynamic Volume Provisioning

第二種訪問方式:動態 Dynamic Provisioning。

動態供給是什麼意思呢?就是說現在叢集管理員不預分配 PV,他寫了一個模板檔案,這個模板檔案是用來表示建立某一型別儲存(塊儲存,檔案儲存等)所需的一些引數,這些引數是使用者不關心的,給儲存本身實現有關的引數。使用者只需要提交自身的儲存需求,也就是 PVC 檔案,並在 PVC 中指定使用的儲存模板(StorageClass)。K8s 叢集中的管控元件,會結合 PVC 和 StorageClass 的資訊動態,生成使用者所需要的儲存(PV),將 PVC 和 PV 進行繫結後,pod 就可以使用 PV 了。透過 StorageClass 配置生成儲存所需要的儲存模板,再結合使用者的需求動態建立 PV 物件,做到按需分配,在沒有增加使用者使用難度的同時也解放了叢集管理員的運維工作。

儲存的使用

在此我們使用NFS來進一步演示儲存的分配和使用。

靜態PV使用

透過分析以上程式碼,可得出:

儲存管理員使用靜態製備應預先規劃PV資源及儲存空間;

叢集管理員透過PVC使用了其中5G的資源,並將其掛載到容器內部/data掛載點;

靜態PV雖然簡單,對於單一的儲存需求還是比較方便的,但如果是多樣性的空間資源需求下,使用靜態PV就顯得有點不合時宜了。

動態PV使用

由於Kubernetes 不包含內部 NFS 驅動,我們需要使用外部驅動為 NFS 建立 StorageClass 。

驅動手動部署

透過分析以上程式碼,並和靜態PV對比可得出:

儲存管理員透過外部NFS外掛即可實現:預先提供NFS儲存模板,而不必提前預分配儲存空間;

叢集管理員透過PV只需繫結storageclass並按需使用相應的儲存空間即可;

透過動態PV,儲存管理員可接入不同級別的儲存卷(storageclass),如:

不同效能級別的塊儲存;

不同效能級別的檔案儲存;

叢集管理員需要能夠根據應用或服務不同使用場景,選擇對應的的 PersistentVolume, 並且這些 PV 卷之間的差別不僅限於卷大小和訪問模式,同時又不將卷是如何實現的這些細節暴露給使用者。

總結

透過學習K8S儲存的幾個概念,在後續的K8S整合更多的應用或服務時,我們就可以根據使用場景、不同效能級別來更好的分配與使用儲存資源了。

來自 “ 木訥大叔愛運維 ”, 原文作者:三頁;原文連結:https://mp.weixin.qq.com/s/kIAOeMX-PzPpZfQqu6FOdQ,如有侵權,請聯絡管理員刪除。

相關文章