K8S | Kubernetes 1.7 本地數據卷管理


本期文章來自才雲科技(Caicloud)CTO 鄧德源的技術原創。node

1
Overviewgit

Kubernetes 1.7 不會引入過多新功能,比較重要的幾個特性包括 Priority API、CRI 的加強以及 Federation 的部分功能。此外,計劃中還將提供本地存儲管理,主要分爲兩個層面:github

本地系統容量的管理。Kubernetes 的主分區主要包含 Kubelet 的根目錄(/var/lib/kubelet),/var/log 目錄等。此外,容器鏡像,容器讀寫層,容器日誌,Kubernetes 空數據卷(emptyDir)等都須要消耗該空間(默認狀況下)。在 Kubernetes 1.7 中,社區將嘗試把此類資源集中管理起來,並做爲調度資源。數據庫

本地數據卷管理。本地數據卷管理的主要內容是將非主分區的其餘分區所有做爲本地持久化數據卷供 Kubernetes 調度使用,遵循 Kubernetes 的 PV/PVC 模型。分佈式

2
Local Volume API性能

在本文中,咱們集中介紹本地數據卷管理,一塊兒思考如何設計本地持久化數據卷,後續再介紹 Kubernetes 準備如何進行容量管理。spa

首先,在設計之初,咱們須要思考本地數據卷的場景和用例,社區認爲的兩個主要應用場景是分佈式文件系統和數據庫,由於二者都須要高性能和可靠性,好比在雲的環境裏,本地 SSD 比掛載的數據盤性能高出許多;另外,本地磁盤在多數狀況下成本更低,適合數據量大的場景。插件

瞭解場景以後,開始進入 API 設計階段。本地數據卷的管理是一個比較複雜的工程,須要支持文件系統和塊存儲。不一樣的文件系統具備不一樣的特性(好比 xfs 支持 quota,而目前 ext4 並不支持 quota),掛載選項也截然不同。設計

而且,本地存儲卷是目前爲止惟一一個涉及到同時支持文件系統和塊存儲的插件方案(ceph 能夠算一個,可是 cephfs 和 RBD 目前是兩個插件)。爲了兼容各類可能的狀況,通過長時間討論,目前 API 已經基本定型:localstorage

clipboard.png

有了上述定義,咱們能夠建立相對應的 Persistent Volume:

clipboard.png

這裏有幾個注意事項:

spec.local.path 能夠是任意的路徑,可是 Kubernetes 推薦把一塊磁盤或者分區掛載到該分區。使用一塊磁盤除了能夠作到容量隔離以外,還能夠作到性能隔離;若是性能隔離對應用場景不重要,那麼能夠把磁盤劃分爲多個分區,所以能夠建立多個 PV。Kubernetes 的這種方式將控制權所有交給了用戶,用戶能夠更加靈活的配置系統。

spec.local.path 目前只能是路徑,後續 Kubernetes 會支持塊設備,這樣一來 spec.local.path 會被重用,即當 PV 是一個掛載點時,path 是一個路徑;當 PV 是一個塊設備時,path 表明設備路徑。另外一種方案是採用更深層次的鍵值,例如 spec.local.fs.path, spec.local.block.path,這樣的好處是能夠支持多重屬性,好比 spec.local.fs.fsType,可是社區目前並無這麼去作,主要緣由是考慮適配 CSI (container storage interface)。

spec.capacity 目前是 informational。若是咱們採用的是磁盤或者分區的方式,那麼該值是磁盤或分區的大小,也就作到了容量隔離。但若是咱們採用的是任意的目錄,目前 Kubernetes 並不會限制該目錄可使用的大小。

上述 API 僅僅定義了 local PV 的 path 屬性,可是不一樣於其餘存儲插件,local PV 的一大特色就是它必定會與本地所綁定,所以,咱們須要給 PV 再加一個屬性,告知系統 PV 屬於哪一個節點。咱們能夠簡簡單單地在 PV 內加上 NodeName 的屬性,以下所示:

clipboard.png

這裏最大的問題在於,咱們將 PV 的拓撲結構限定在節點層面,可是「本地」的含義並非說存儲必定是分配在某臺機器上,咱們能夠說:這個存儲是屬於該 rack 的本地存儲。那麼對於 rack 內的機器而言,該存儲就是他們的本地存儲。鑑於此,local volume 的 API 須要設計得更加通用:

clipboard.png

上述 Yaml 與最開始介紹的配置表達的相同的內容,可是提供了更加靈活的表達方式,同時也複用了 Kubernetes 中已經存在的 node affinity 的概念。

3
Local Volume Scheduling

Kubernetes PV/PVC 在設計時,忽略了與調度器的交互部分,致使 PV/PVC 的綁定與 Pod 調度毫無關係。在 「remote volume「 的狀況下問題並不大,由於 Pod 被調度後,能夠動態掛載數據卷,可是在本地數據卷的狀況下,問題已經凸顯出來。當用戶建立 PV 和 PVC 以後,因爲本地數據卷的特性,任何要求某個特定 PVC 的 Pod 實際上已經被調度了。

例如,管理員建立一個名爲 super-pv 的數據卷,該數據卷存在於節點 Kube-node-1 上;當用戶建立一個名爲 claim-it 的 PVC 並被 Kubernetes 綁定在 super-pv 上以後,任何使用 PVC 的 Pod 實際上已經被調度到了 Kube-node-1 上。

假設此時,Kube-node-1 的資源沒法知足 Pod 的需求(例如 CPU 足夠),那麼 Pod 會一直處於 Pending 狀態,即便另一臺機器 Kube-node-2 有足夠的資源,也有知足需求的本地數據卷。

在 Kubernetes 1.7 中,本地數據卷管理暫時不會處理該問題(會設計一個外部控制器來按期查詢該錯誤狀態,並根據必定的策略從新調度)。後續的解決方案暫無定論,其中一個可行的方案是將綁定邏輯放在調度器中:

PV/PVC 的綁定被延遲到調度時刻,即當真有 Pod 使用某個 PVC 時再進行綁定
調度器經過 PVC.storageclass 找到可使用的 PV,並拿到每一個 PV 的 affinity
調度器綜合考慮 Pod 的調度需求和 PV 的 affinity 進行調度
若是沒有知足需求的 Node,調度器經過和 PV provisioner 交互,動態建立 PV

若是咱們從總體的設計上來看,該問題並不是只會出如今本地存儲上,任何須要調度器和 PV/PVC 綁定控制器交互的地方都會有問題。

例如,在多 zone 的狀況下,PV/PVC 控制器並不會考慮一個 PV 須要建立在哪一個 zone 裏面;所以,頗有可能控制器選擇了一個 zone,可是該 zone 並不知足 Pod 的需求(例如 affinity 需求,或者全部節點資源都不夠)。

因爲一個 zone 可能包含多個機器,所以問題被縮小,但仍然存在。若是咱們仔細思考能夠看出,實際上 node 就是一個 」tiny zone「,問題的本質其實是同樣的。

4
Local Volume Static Provisioner

本地數據卷的建立由新的 Kubernetes 組件處理(local volume provisioner addon),該組件將以 DaemonSet 的方式部署。

Provisioner 有兩個核心組件:

Discovery: discovery 組件的功能是接收用戶配置的信息,而後建立 PV。例如,當用戶將 「/var/lib/kubelet/localstorages」 做爲本地數據卷的目錄後,provisioner 會爲該目錄下的每個目錄建立一個新的 PV,並添加正確的拓撲信息。

Deleter: deleter 負責處理 PV 狀態改變。當 deleter 發現其管理的 PV 進入了 Released 狀態,deleter 會清理數據並將 PV 從 Kubernetes API 中刪除。此時,Discovery 發現 PV 被刪除,會從新建立新的 PV,從而達到回收的效果。

Provisioner 後續還能夠完成各類錯誤彙報,容量檢查等功能,在 kubernetes 1.7 中會提供 alpha 版本。

5
Future

儘管 Kubernetes 1.7 中本地存儲卷只能說處於基本能夠試一試的狀態,社區後續會爲這個功能投入大量精力,具體實現內容已經涉及到 1.八、1.9 版,包括 dynamic provisioner, fsGroup support, SELinux support, taints/toleration, local PV monitoring, block storage support 等,相信後續會有更多進展。

相關閱讀:
https://github.com/kubernetes...

https://github.com/kubernetes...

相關文章
相關標籤/搜索