歡迎光臨
每天分享高質量文章

Kubernetes儲存系統介紹及機制實現

本文分為三大部分。第一部分主要介紹Kubernetes中常用的幾種儲存,及其使用場景和生命周期等等。第二部分試圖介紹一些設計原則和基本架構,並簡要介紹各種儲存plugin的實現機制及持久捲的一些特性,例如訪問樣式、回收策略等等。動態捲供給是一個Kubernetes獨有的功能,這一功能允許按需創建儲存捲,使管理員不必預先創建儲存捲,而是隨用戶需求進行創建。第三部分會介紹一下v1.9中儲存的一些新特性。

一、Kubernetes中儲存的應用場景

在Kubernetes中部署和運行的服務大致分為:
1. 無狀態服務
Kubernetes使用ReplicaSet來保證一個服務的實體數量,如果說某個Pod實體由於某種原因掛掉或崩潰,ReplicaSet會立刻用這個Pod的模版新啟一個Pod來替代它。由於是無狀態的服務,新Pod與舊Pod一模一樣。此外Kubernetes通過Service(一個Service後面可以掛多個Pod)對外提供一個穩定的訪問接口,實現服務的高可用。
2. 普通有狀態服務
和無狀態服務相比,它多了狀態儲存的需求。Kubernetes提供了以Volume和Persistent Volume為基礎的儲存系統,可以實現服務的狀態儲存。
3. 有狀態集群服務
和普通有狀態服務相比,它多了集群管理的需求。要運行有狀態集群服務要解決的問題有兩個,一個是狀態儲存,另一個是集群管理。Kubernetes為此開發了StatefulSet(以前叫做PetSet),方便有狀態集群服務在Kubernetes上部署和管理。
簡單來說是通過Init Container來做集群的初始化工作,用Headless Service來維持集群成員的穩定關係,用動態儲存供給來方便集群擴容,最後用StatefulSet來綜合管理整個集群。 

分析以上的服務型別,Kubernetes中對於儲存的使用主要集中在以下幾個方面:
  • 服務的基本配置檔案讀取、密碼密鑰管理等;

  • 服務的儲存狀態、資料存取等;

  • 不同服務或應用程式間共享資料。

二、Kubernetes中幾種常見的儲存系統

目前Kubernetes所支持的Volume Plugins如下表所示。

Kubernetes已經提供非常豐富的Volume和Persistent Volume插件,大家可以根據自己業務的需要,使用這些插件給容器提供儲存服務。每一種Plugin的使用方法和註意事項在此不做贅述,請參考Kubernetes Volume 的官方文件[1]。
容器儲存接口(Container Storage Interface,CSI[2])是一項跨行業標準倡議,旨在降低雲原生儲存開發工作的門檻,從而進一步確保兼容性水平。Kubernetes v1.9已經引入了CSI的一套alpha實現版本,將新分捲插件的安裝流程簡化至與安裝pod相當,並允許第三方儲存供應商在無需接觸核心Kubernetes代碼庫的前提下開發自己的解決方案。
如果上述的這些Plugin不滿足業務要求, 你可以通過以下兩種途徑進行二次開發。
  1. 可以使用FlexVolume實現自己的Volume插件。此Plugin仍是alpha版本,後向兼容性需要考慮。具體方法在此不做贅述,參考FlexVolume的社區文件[3]。

  2. 推薦使用CSI。目前還只是alpha版本,使用時需要在feature-gate中enable,不推薦在production環境中使用。v1.9已經把CSI作為in-tree plugin,把out-off-tree volume插件的開發從 Kubernetes 中脫離出來,極大地方便了插件的開發、維護和集成。如何使用CSI,可參考How to Use Kubernetes 1.9.0 with CSI[4]。

三、Kubernetes儲存的設計與基本架構

Kubernete儲存在設計的時候遵循著Kubernetes的一貫哲學,即宣告式(Declarative)架構。同時為了盡可能多地兼容各種儲存平臺,Kubernetes以in-tree plugin的形式來對接不同的儲存系統,滿足用戶可以根據自己業務的需要使用這些插件給容器提供儲存服務。同時兼容用戶使用FlexVolume和CSI定製化插件。相比較於Docker Volume,支持的儲存功能更加豐富和多樣。

Kubernetes中mount 一個PV的基本過程包括:
  1. 用戶通過API創建一個包含PVC的Pod;

  2. Scheduler把這個Pod分配到某個節點,比如Node1;

  3. Node1上的Kubelet開始等待Volume Manager準備device;

  4. PV controller呼叫相應Volume Plugin(in-tree或者out-of-tree),創建PV,併在系統中與對應的PVC系結;

  5. Attach/Detach controller或者Volume Manager通過Volume Plugin實現device掛載(Attach);

  6. Volume Manager等待device掛載完成後,將捲掛載到節點指定目錄(mount), 比如/var/lib/kubelet/pods/xxxxxxxxxxx/volumes/aws-ebs/vol-xxxxxxxxxxxxxxxxx;

  7. Node1上的Kubelet此時被告知volume已經準備好後,開始啟動Pod,通過volume mapping將PV已經掛載到相應的容器中去。

其實對於Kubernetes中大部分的Volume Plugin來說,mount的過程遵循著如下的規則:
/some/global/mount/path -> /var/lib/kubelet/pods//volumes/// -> container volume
這種方式的好處相當於熱插拔,一旦Pod掛掉,kubelet可以馬上重啟,並快速mount volume,不會出現類似於device busy的情形。
但是對於hostpath這個Plugin而言,直接就是 /some/global/mount/path -> container volume。

四、Persistent Volume與Persistent Volume Claim

一個運行中的容器,預設情況下,對檔案系統的寫入,都是發生在其分層檔案系統的可寫層的(Copy-on-Write)。當遷移的應用程式從開發到生產環境時候,開發人員面臨著巨大的挑戰。當容器掛掉、崩潰或運行結束時,任何與之相關的資料都會丟失。為瞭解決這個問題引發的資料丟失,我們需要將資料儲存持久化,也可以稱為Persistent Volume。
Kubernetes使用兩種資源管理儲存:
  • PersistentVolume(簡稱PV):由管理員添加的的一個儲存的描述,是一個全域性資源,包含儲存的型別,儲存的大小和訪問樣式等。它的生命周期獨立於Pod,例如當使用它的Pod銷毀時對PV沒有影響。

  • PersistentVolumeClaim(簡稱PVC):是Namespace里的資源,描述對PV的一個請求。請求信息包含儲存大小,訪問樣式等。

Kubernetes中的Volume則是基於Docker進行擴展,使用Docker Volume掛載宿主機上的檔案目錄到容器中。
一般來說,Kubernetes中Pod通過如下三種方式來訪問儲存資源。
直接訪問

該種方式移植性較差,可擴展能力差,把Volume的基本信息完全暴露給用戶,有嚴重的安全隱患,同時需要協調不同users對Volume的訪問。
靜態provision

動態provision

StorageClass將說明Volume將由哪種Volume Plugin創建、創建時引數以及從其他功能性/非功能性角度描述的後臺volume的各種引數。一般為storage cluster的一些配置信息,以及label註釋信息。

一般來說,PV和PVC的生命周期分為5個階段:
  1. Provisioning,即PV的創建,可以直接創建PV(靜態方式),也可以使用StorageClass動態創建

  2. Binding,將PV分配給PVC

  3. Using,Pod通過PVC使用該Volume

  4. Releasing,Pod釋放Volume並刪除PVC

  5. Reclaiming,回收PV,可以保留PV以便下次使用,也可以直接從雲儲存中刪除

根據這5個階段,Volume的狀態有以下4種:
  1. Available:可用

  2. Bound:已經分配給PVC

  3. Released:PVC解綁但還未執行回收策略

  4. Failed:發生錯誤

五、v1.9中對儲存做了哪些更改

  1. 引入了CSI alpha版本的實現,可見第二部分關於CSI的介紹。

  2. 修複Bug:刪除運行狀態container的PVC

    這個bug會導致資料丟失。社區的解決辦法是引入一個Finalizer來保護PVC。

    詳細的步驟請參考相關的Proposal[5]及其代碼實現[6]。

    簡單來說,這個Fianlizer類似於垃圾回收(GC)裡面的指標計數,當這個使用這個PVC的POD都被刪除(deleted)或處於完成狀態(completed)時,才可以刪除這個PVC。從而避免了刪除正在運行中的container的PVC,從而引發資料丟失。

Q&A;

Q:Kubernetes和Cloud Foundry有什麼區別,優勢在什麼地方?
A:Cloud Foundry更像是Application PaaS,Kubernetes主要是Container PaaS。CF不會直接把container層暴露給用戶,Kubernetes則不然,你可以直接訪問container。個人覺得kubernetes的部署和使用更簡單,更直接,操作起來也更方便。

Q:請問對於Galera Cluster的集群儲存如何設計儲存方案,CSI有考慮有狀態儲存的解決方案嗎?
A:對於有狀態服務,請使用StatefulSet來部署你的應用。Volume只是一個儲存的地方。StatefulSet會負責給Pod設置順序等等,保證是有序的,優雅的刪除停止和擴展。

Q:有沒有物件儲存,比如Ceph RGW,在Kubernetes集群中的使用案例,比如用戶通過客戶端上傳、下載PVC中的資料之類的?
A:有試過RGW來儲存資料,但是性能不是很好,速度要慢很多。在Kubernetes集群中可以使用RGW來儲存一些靜態的檔案,比如配置檔案,Nginx靜態html檔案之類,用戶也可以下載PV中的資料。不建議對RGW中的資料進行頻繁的更改。

Q:能否詳細說下CSI?
A:CSI在kubernetes v1.9才引入。這部分內容比較多,可以去看看CSI文件[2],以及Kubernetes官方的介紹[7],以及這個feature實現代碼[8]。

Q:RBD用什麼插件,有沒有什麼坑?
A:需要在kubelet節點上安裝ceph-common這個包,在volume mount的時候,會呼叫相關的命令。基本上沒什麼坑,RBD提供的volume還是很好使的。

Q:儲存這塊IO性能下降大概多少呢,有實測過嗎?
A:儲存的性能與Cluster的能力、儲存的型別有很大關係。實測過RBD的IO性能,當然case by case,當時測出來的結果還是很不錯的,相比較與CephFS、GlusterFS。

Q:多個Pod共享一個Nas,是否可行,需要註意什麼?
A:可行,但是需要註意Volume的讀寫權限,這個可以通過mount時候的PV的access mode進行設置,比如ReadWrite、ReadWriteOnce等等。

Q:CSI和社區孵化的volume provisioner有什麼區別?
A:CSI的主要目的還是為了給容器儲存定義一個統一的接口,方便進行定製化,以及新功能添加。社區孵化的volume provisioner,你指的應該是external-storage這個專案吧,這個專案的主要目的是為了方便對in-tree的那些Plugin進行修改和定製,這樣可以獨立地進行更新。

Q:請問你現在有把MySQL可以放進PV裡面麽?求介紹這方面的經驗。
A:如果只是單節點的MySQL,直接放進PV就好了,跟其它正常服務一樣。對於多節點的MySQL Cluster,在部署的時候就需要註意了,建議部署成StatefulSet,有狀態的服務。之前有試過用Galera Cluster For MySQL來部署集群,發現效果不是很好,尤其是在隨意啟停Pod的時候,Cluster的沒辦法自組成新的集群,新節點也無法加入集群。你可以再次試驗下,確認一下。 後來使用MySQL Cluster CGE,效果很好,Cluster能夠及時回覆並重新組織起來。
相關鏈接:
  1. https://kubernetes.io/docs/concepts/storage/volumes/

  2. https://github.com/container-storage-interface

  3. https://github.com/kubernetes/community/blob/master/contributors/devel/flexvolume.md

  4. https://blog.thecodeteam.com/2017/12/19/use-kubernetes-1-9-0-csi/

  5. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/postpone-pvc-deletion-if-used-in-a-pod.md

  6. https://github.com/kubernetes/kubernetes/pull/55824

  7. http://blog.kubernetes.io/2018/01/introducing-container-storage-interface.html

  8. https://github.com/kubernetes/kubernetes/pull/54529

基於Kubernetes的DevOps實踐培訓

本次培訓包含:Kubernetes核心概念;Kubernetes集群的安裝配置、運維管理、架構規劃;Kubernetes組件、監控、網絡;針對於Kubernetes API接口的二次開發;DevOps基本理念;微服務架構;微服務的容器化等,點擊識別下方二維碼加微信好友瞭解具體培訓內容
點擊閱讀原文鏈接即可報名。
赞(0)

分享創造快樂