Kubernetes持久化存儲是個難題,解決方案有哪些?
雖然 Kubernetes 在許多方面非常有用,例如可伸縮性、可移植性和管理能力,但它不支持存儲狀態。幾乎所有的生產應用程序都是有狀態的,即需要某種外部存儲。
像 Kubernetes 這樣的容器編排工具正在徹底改變應用程序的開發和部署方式。隨著微服務架構的興起,以及基礎架構與應用程序邏輯從開發人員的角度解耦,開發人員越來越關注構建軟件和交付價值。
Kubernetes 對管理的物理機器進行抽象。使用 Kubernetes,你可以通過描述獲取所需的內存總量和計算能力,而無需擔心底層基礎架構。
在管理 Docker 鏡像時,Kubernetes 還讓應用程序變得可移植。一旦使用 Kubernetes 開發容器化架構,它們就可以部署在任何地方 - 公有云、混合云、本地 - 無需對底層代碼進行任何更改。
雖然 Kubernetes 在許多方面非常有用,例如可伸縮性、可移植性和管理能力,但它不支持存儲狀態。幾乎所有的生產應用程序都是有狀態的,即需要某種外部存儲。
Kubernetes 的架構是不斷變化的。容器的創建和銷毀,取決于負載和開發人員的規范。容器組和容器可以自我修復和復制。從本質上講,它們的生命周期是短暫的。
但是,持久化存儲解決方案無法承受這種動態行為。持久化存儲不能綁定到動態創建和銷毀的規則上。
當有狀態應用需要部署在另一個基礎架構,可能是另一個云提供商、本地或混合模型上時,它們在可移植性方面面臨挑戰。持久化存儲解決方案會綁定到特定的云提供商。
此外,云原生應用程序的存儲版圖不容易理解。Kubernetes 存儲術語可能會造成混淆,因為許多術語都有復雜的含義和微妙的變化。此外,在做出決策之前,開發人員必須考慮許多選項,包括原生 Kubernetes、開源框架、托管或付費服務。
在下面的 CNCF 版圖中可以看到列出的云原生存儲解決方案:
首先想到的可能就是在 Kubernetes 中部署數據庫:選擇適合你需求的數據庫解決方案,將其容器化并在本地磁盤上運行,然后將其作為另一個工作負載部署在集群中。但是,由于數據庫的固有屬性,這種方法不是特別好。
容器是基于無狀態原則構建的。這使得容器很容易進行伸縮。由于不需要保存和遷移數據,通常來說,集群不需要處理很密集的磁盤讀寫操作。
使用數據庫,需要保存狀態。如果數據庫以容器方式部署在集群上,不進行遷移或者頻繁伸縮,那么實際的數據存儲將起作用。理想情況下,將使用數據的容器與數據庫位于同一個容器中。
這并不是說在容器中部署數據庫是一個壞主意 - 在某些用例中,這種方法可能就足夠了。在測試環境中,或者對于不需要生產級數據量的任務,由于所保存的數據規模較小,因此集群中的數據庫可能是有意義的。
在生產中,開發人員通常依賴外部存儲。
Kubernetes 如何與存儲通信?它使用控制平面接口。這些接口將 Kubernetes 與外部存儲相關聯。這些與 Kubernetes 連接的外部存儲解決方案稱為卷插件。卷插件可以抽象存儲并賦予存儲可移植性。
以前,卷插件使用 Kubernetes 核心代碼庫構建、鏈接、編譯和發布。這極大地限制了開發人員的靈活性,并帶來了額外的維護成本。添加新的存儲選項需要更改 Kubernetes 代碼庫。
通過引入 CSI 和 Flexvolume,可以在集群上部署卷插件,而無需更改代碼庫。
Kubernetes 原生和存儲
Kubernetes 原生如何處理存儲?Kubernetes 自身提供了一些管理存儲的解決方案:臨時選項、持久化存儲卷、持久化存儲卷聲明、存儲類和有狀態副本集。這可能很混亂。
持久化存儲卷(PV)是由管理員配置的存儲單元。它們獨立于任何一個容器組,使它們擺脫容器組的短暫生命周期。
另一方面,持久化存儲卷聲明(PVC)是對存儲的請求,即 PVs。使用 PVC,可以將存儲綁定到特定節點,使其可供該節點使用。
有兩種處理存儲的方法:靜態和動態。
采用靜態配置,管理員在實際請求之前,為他們認為可能需要的容器組提供 PVs,并且通過明確指定的 PVCs,將這些 PV 手動綁定到指定的容器組。
實際上,靜態定義的 PV 與 Kubernetes 的可移植結構不兼容,因為正在使用的存儲可能依賴于環境,例如 AWS EBS 或 GCE Persistent Disk。手動綁定需要更改 YAML 文件以指向特定供應商的存儲解決方案。
在開發人員如何考慮資源方面,靜態配置也違背了 Kubernetes 的思維方式:CPU 和內存未事先分配并綁定到容器組或容器。它們是動態授予的。
動態配置使用存儲類完成。集群管理員無需事先手動創建 PV。他們改為創建多個存儲配置文件,就像模板一樣。當開發人員創建 PVC 時,根據請求的要求,在請求時創建其中一個模板,并將其附加到容器組。
這是對外部存儲通常如何使用原生 Kubernetes 進行處理的一個寬泛的概述。但是,還有許多其他選擇需要考慮。
CSI - 容器存儲接口
在繼續之前,我想介紹容器存儲接口(CSI)。CSI 是由 CNCF 存儲工作組創建的統一工作,旨在定義標準容器存儲接口,使存儲驅動程序能夠在任何容器編排器上工作。
CSI 規范已經適用于 Kubernetes,并且在 Kubernetes 集群上有大量驅動程序插件可供部署。開發人員可以 Kubernetes 上使用 CSI 卷類型訪問 CSI 兼容卷驅動程序公開的存儲。
隨著 CSI 的引入,存儲可以被視為另一個工作負載容器化,并在 Kubernetes 集群上部署。
開源項目
圍繞云原生技術的工具和項目大幅增加。作為生產環境中最突出的問題之一,有相當多的開源項目致力于解決云原生架構上的存儲問題。
關于存儲的***的項目是 Ceph 和 Rook。
Ceph 是一個動態管理,可水平擴展的分布式存儲集群。Ceph 提供了對存儲資源的邏輯抽象。它被設計為沒有單點故障,可自我管理并基于軟件。Ceph 為同一存儲集群同時提供塊、對象和文件系統接口。
Ceph 的架構很復雜,有許多底層技術,如 RADOS、librados、RADOSGW、RDB、CRUSH 算法,以及監視器、OSD 和 MDS 等組件。Ceph 是一個分布式存儲集群,不需要深入研究其體架構,關鍵在于,它是一個分布式存儲集群,可以更輕松地實現可擴展性,在不犧牲性能的情況下消除單點故障,并提供了對對象、塊和文件的訪問的統一存儲。
當然,Ceph 已經適應了云原生環境。可以通過多種方式部署 Ceph 集群,例如使用 Ansible。可以從 Kubernetes 集群中使用 CSI 和 PVC 接口訪問部署的 Ceph 集群。
Ceph 架構
另一個有趣且頗受歡迎的項目是 Rook,一個旨在融合 Kubernetes 和 Ceph 的工具 - 將計算和存儲集中在一個集群中。
Rook 是一個云原生存儲編排器。它擴展了 Kubernetes。Rook 本質上允許將 Ceph 放入容器中,并提供集群管理邏輯,以便在 Kubernetes 上可靠地運行 Ceph。Rook 自動化部署、引導、配置、擴展、負載均衡,即集群管理員需要做的工作。
Rook 允許通過 yaml 文件部署 Ceph 集群,就像 Kubernetes 一樣。此文件用作集群管理員在集群中所需內容的高級聲明。Rook 整合集群,并開始積極監控。Rook 充當運維人員或控制器,確保 yaml 文件中聲明的期望狀態得到保證。Rook 在一個協調循環中運行,觀察狀態并根據檢測到的差異采取行動。
Rook 沒有自己的持久化狀態,也不需要管理。它的確是根據 Kubernetes 的原則構建的。
Rook 架構
Rook 將 Ceph 和 Kubernetes 結合在一起,是***的云原生存儲解決方案之一,在 Github 上擁有近 4000 顆星,1630 萬 下載量和 100 多名貢獻者。
作為被 CNCF 接受的***存儲項目,Rook 近期已進入孵化階段。
對于應用程序中的任何問題,確定需求,設計系統和選擇相應工具非常重要。云原生環境中的存儲也不例外。雖然問題非常復雜,但仍有許多工具和方法。隨著云原生世界的發展,無疑也會出現新的解決方案。
查看英文原文:https://softwareengineeringdaily.com/2019/01/11/why-is-storage-on-kubernetes-is-so-hard/