本文轉自魏亮的工作筆記。原文:https://weiliang-ms.github.io/wl-awesome/2.%E5%AE%B9%E5%99%A8/k8s/storage/OpenEBS.html.版權歸原作者所有。
簡介
什么是OpenEBS?
OpenEBS是一個開源的云原生存儲解決方案,由CNCF基金會托管。目前這個項目處于沙盒階段。
OpenEBS是一組存儲引擎,允許您為StatefulSet和Kubernetes平臺類型選擇正確的存儲解決方案。在高層次上,OpenEBS支持兩種類型的卷:——本地卷和復制卷。
OpenEBS是Kubernetes本地超融合存儲解決方案,管理節點可用的本地存儲,并為有狀態工作負載提供本地或高度可用的分布式持久卷。作為一個完整的本地Kubernetes解決方案的另一個優勢是,管理員和開發人員可以使用Kubernetes提供的所有優秀工具,如kubectl、Helm、Prometheus、Grafana、Weave Scope等。交互和管理OpenEBS。
OpenEBS能做什么?
OpenEBS管理k8s節點上的存儲,并為k8s StatefulSet提供本地存儲卷或分布式存儲卷。
本地卷(本地存儲)
OpenEBS可以使用主機原始塊設備或分區,或者主機路徑上的子目錄,或者LVM和ZFS來創建持久卷。
本地卷直接掛載在Stateful Pod中,在OpenEBS的數據路徑中沒有任何開銷。
OpenEBS為本地卷監控、備份/恢復、災難恢復、ZFS或LVM支持的快照等提供了額外的工具。
對于分布式卷(即復制卷)
OpenEBS使用其中一個引擎(Mayastor、cStor或Jiva)為每個分布式持久卷創建微服務。
有狀態Pod將數據寫入OpenEBS引擎,OpenEBS引擎將數據同步復制到集群中的多個節點。OpenEBS引擎本身部署為Pod,由Kubernetes協調。當運行Stateful Pod的節點出現故障時,Pod將被重新調度到集群中的另一個節點,OpenEBS將使用其他節點上的可用數據副本來提供對數據的訪問。
有狀態pod使用iSCSI(
cStor和Jiva
) 或 NVMeoF
(Mayastor
) 連接 OpenEBS 分布式持久卷OpenEBS cStor
和 Jiva
專注于存儲的易用性和持久性。它們分別使用自定義版本的 ZFS
和 Longhorn
技術將數據寫入存儲。OpenEBS Mayastor
是最新開發的以耐久性和性能為設計目標的引擎,高效地管理計算 (大頁面、核心) 和存儲 (NVMe Drives
),以提供快速分布式塊存儲?注意:
OpenEBS
分布式塊卷被稱為復制卷,以避免與傳統的分布式塊存儲混淆,傳統的分布式塊存儲傾向于將數據分布到集群中的許多節點上。復制卷是為云原生有狀態工作負載設計的,這些工作負載需要大量的卷,這些卷的容量通??梢詮膯蝹€節點提供,而不是使用跨集群中的多個節點分片的單個大卷
對比傳統分布式存儲
OpenEBS
與其他傳統存儲解決方案不同的幾個關鍵方面 :
- 使用微服務體系結構構建,就像它所服務的應用程序一樣。
OpenEBS
本身作為一組容器部署在Kubernetes
工作節點上。使用Kubernetes
本身來編排和管理OpenEBS
組件 - 完全建立在用戶空間,使其高度可移植性,以運行在任何操作系統 / 平臺。
- 完全意圖驅動,繼承了
Kubernetes
易用性的相同原則 OpenEBS
支持一系列存儲引擎,因此開發人員可以部署適合于其應用程序設計目標的存儲技術。像Cassandra
這樣的分布式應用程序可以使用LocalPV
引擎進行最低延遲的寫操作。像MySQL
和PostgreSQL
這樣的單片應用程序可以使用使用NVMe
和SPDK
構建的Mayastor
或基于ZFS
的cStor
來實現彈性。像Kafka
這樣的流媒體應用程序可以在邊緣環境中使用NVMe
引擎Mayastor
以獲得最佳性能。
驅使用戶使用 OpenEBS
的主要原因是 :
- 在所有的
Kubernetes
發行版上都是可移植的 - 提高了開發人員和平臺
SRE
的生產力 - 與其他解決方案相比,易于使用
- 優秀的社區支持
- 免費開源
本地卷類型
本地卷只能從集群中的單個節點訪問。必須在提供卷的節點上調度使用 Local Volume
的 Pods
。本地卷通常是分布式工作負載的首選,比如 Cassandra
、MongoDB
、Elastic
等,這些工作負載本質上是分布式的,并且內置了高可用性(分片)
根據附加到 Kubernetes
工作節點上的存儲類型,您可以從不同的動態本地 PV
進行選擇——Hostpath
、Device
、LVM
、ZFS
或 Rawfile
可復制卷類型
復制卷
顧名思義,是指將數據同步復制到多個節點的卷。卷可以支持節點故障。還可以跨可用性區域設置復制,以幫助應用程序跨可用性區域移動。
復制卷還能夠提供像快照、克隆、卷擴展等企業存儲特性。復制卷是有狀態工作負載 (如 Percona/MySQL
、Jira
、GitLab
等) 的首選。
根據附加到 Kubernetes
工作節點的存儲類型和應用程序性能需求,您可以從 Jiva、cStor
或 Mayastor
中進行選擇
OpenEBS 存儲引擎建議
應用需求 | 存儲類型 | OpenEBS 卷類型 |
---|---|---|
低時延、高可用性、同步復制、快照、克隆、精簡配置 | SSD/ 云存儲卷 | OpenEBS Mayastor |
高可用性、同步復制、快照、克隆、精簡配置 | 機械 /SSD/ 云存儲卷 | OpenEBS cStor |
高可用性、同步復制、精簡配置 | 主機路徑或外部掛載存儲 | OpenEBS Jiva |
低時延、本地 PV | 主機路徑或外部掛載存儲 | Dynamic Local PV - Hostpath, Dynamic Local PV - Rawfile |
低時延、本地 PV | 本地機械 /SSD/ 云存儲卷等塊設備 | Dynamic Local PV - Device |
低延遲,本地 PV,快照,克隆 | 本地機械 /SSD/ 云存儲卷等塊設備 | OpenEBS Dynamic Local PV - ZFS , OpenEBS Dynamic Local PV - LVM |
總結:
- 多機環境,如果有額外的塊設備(非系統盤塊設備)作為數據盤,選用
OpenEBS Mayastor
、OpenEBS cStor
- 多機環境,如果沒有額外的塊設備(非系統盤塊設備)作為數據盤,僅單塊系統盤塊設備,選用
OpenEBS Jiva
- 單機環境,建議本地路徑
Dynamic Local PV - Hostpath, Dynamic Local PV - Rawfile
,由于單機多用于測試環境,數據可靠性要求較低。
由此看來,OpenEBS
常用場景為以上三個場景
OpenEBS 特性
容器附加存儲

OpenEBS
是一個容器附加存儲 (Container Attached Storage, CAS
) 的例子。通過 OpenEBS
提供的卷總是被容器化。每個卷都有一個專用的存儲控制器,用于提高有狀態應用程序的持久性存儲操作的敏捷性和粒度。
同步復制

同步復制是 OpenEBS
的一個可選的流行特性。當與 Jiva
、cStor
和 Mayastor
存儲引擎一起使用時,OpenEBS
可以同步復制數據卷以實現高可用性???Kubernetes
區域進行復制,從而為跨 AZ
設置提供高可用性。這個特性對于使用 GKE、EKS
和 AKS
等云提供商服務上的本地磁盤構建高可用狀態應用程序特別有用
快照和克隆

寫時拷貝快照是 OpenEBS
另一個可選的流行特性。使用 cStor
引擎時,快照是瞬時創建的,并且不受快照個數的限制。增量快照功能增強了跨 Kubernetes
集群和跨不同云提供商或數據中心的數據遷移和可移植性。對快照和克隆的操作完全以 Kubernetes
原生方法執行,使用標準 kubectl
命令。常見的用例包括用于備份的高效復制和用于故障排除或針對數據的只讀副本進行開發的克隆
備份和恢復

OpenEBS
卷的備份和恢復可以通過開源的 OpenEBS Velero
插件與 Kubernetes
備份和恢復解決方案 (如 Velero
(前身為 Heptio Ark
)) 協同工作。經常使用 OpenEBS
增量快照功能,將數據備份到 AWS S3、GCP object storage、MinIO
等對象存儲目標。這種存儲級別的快照和備份只使用增量數據進行備份,節省了大量的帶寬和存儲空間。
真正的 Kubernetes 云原生存儲

OpenEBS
是 Kubernetes
上有狀態應用程序的云原生存儲,云原生
意味著遵循松散耦合的體系結構。因此,云原生、松散耦合體系結構的一般好處是適用的。例如,開發人員和 DevOps
架構師可以使用標準的 Kubernetes
技能和實用程序來配置、使用和管理持久存儲需求
減少存儲 TCO 高達 50%
在大多數云上,塊存儲的收費是基于購買的多少,而不是使用的多少 ; 為了實現更高的性能,并在充分利用容量時消除中斷的風險,容量經常被過度配置。OpenEBS
的精簡配置能力可以共享本地存儲或云存儲,然后根據需要增加有狀態應用程序的數據量??梢詣討B添加存儲,而不會中斷暴露給工作負載或應用程序的卷。某些用戶報告說,由于使用了 OpenEBS
的精簡配置,節省了超過 60%
的資源。
高可用性

由于 OpenEBS
遵循 CAS
架構,在節點故障時,Kubernetes
將重新調度 OpenEBS
控制器,而底層數據則通過使用一個或多個副本來保護。更重要的是——因為每個工作負載都可以利用自己的 OpenEBS
——不存在因存儲丟失而導致系統大范圍宕機的風險。例如,卷的元數據不是集中的,它可能會像許多共享存儲系統那樣受到災難性的通用中斷的影響。相反,元數據保持在卷的本地。丟失任何節點都會導致只存在于該節點上的卷副本的丟失。由于卷數據至少在其他兩個節點上進行了同步復制,因此當一個節點出現故障時,這些數據將在相同的性能級別上繼續可用
CAS 介紹
在 CAS
或容器附加存儲 (Container Attached Storage
) 體系結構中,存儲在容器中運行,并且與存儲綁定到的應用程序密切相關。存儲作為微服務運行,沒有內核模塊依賴關系。像 Kubernetes
這樣的編排系統編排存儲卷,就像任何其他微服務或容器一樣。CAS
具有 DAS
和 NAS
的優點
非 CAS 系統上的 PV
在非 CAS
模型中,Kubernetes
持久卷仍然與內核模塊緊密耦合,使得 Kubernetes
節點上的存儲軟件本質上是單片的

基于 CAS 系統上的 PV

相反,CAS
使您能夠利用云原生應用程序的靈活性和可伸縮性。定義 Kubernetes PV (Persistent Volume)
的存儲軟件是基于微服務架構的。存儲軟件的控制平面 (存儲控制器) 和數據平面 (存儲副本) 作為 Kubernetes Pods
運行,因此,使您能夠將云原生的所有優勢應用到 CAS
。
CAS 優勢
- 敏捷
CAS
中的每個存儲卷都有一個容器化的存儲控制器和相應的容器化副本。因此,圍繞這些組件的資源的維護和調優是真正敏捷的。Kubernetes
滾動升級功能可以實現存儲控制器和存儲副本的無縫升級??梢允褂萌萜?cGroups
調優 CPU
和內存等資源配額。
- 存儲策略粒度化
將存儲軟件容器化并將存儲控制器專用于每個卷可以帶來最大的存儲策略粒度。在 CAS
體系結構中,可以按卷配置所有存儲策略。此外,您可以監視每個卷的存儲參數,并動態更新存儲策略,以實現每個工作負載的預期結果。隨著卷存儲策略中這種額外粒度級別的增加,存儲吞吐量、IOPS
和延遲的控制也會增加。
- 云原生
CAS
將存儲軟件裝入容器,并使用 Kubernetes
自定義資源定義 (CRDs
) 來聲明低級存儲資源,如磁盤和存儲池。這個模型使存儲能夠無縫地集成到其他云原生工具中??梢允褂?Prometheus、Grafana、Fluentd、Weavescope、Jaeger
等云原生工具來供應、監控和管理存儲資源
PV
是CAS
中的一個微服務
如上圖所示,在 CAS
架構中,存儲控制器和副本的軟件完全是基于微服務的,因此不涉及內核組件。通常,存儲控制器 POD
被調度在與持久卷相同的節點上,以提高效率,副本 POD
可以被調度在集群節點上的任何位置。每個副本使用本地磁盤、SAN
磁盤和云磁盤的任意組合完全獨立于其他副本進行配置。這為大規模管理工作負載的存儲分配提供了巨大的靈活性。
- 超融合非分布式
CAS
架構沒有遵循典型分布式存儲架構。通過從存儲控制器到存儲副本的同步復制,存儲變得高度可用。卷副本的元數據不是在節點之間共享的,而是在每個本地節點上獨立管理。如果一個節點故障,存儲控制器 (在本例中是一個無狀態容器) 將在一個節點上輪轉,該節點上運行著第二個或第三個副本,數據仍然可用。
與超融合系統類似,CAS
中的卷的存儲和性能是可擴展的。由于每個卷都有自己的存儲控制器,因此存儲可以在一個節點的存儲容量允許的范圍內進行擴展。在給定的 Kubernetes
集群中,隨著容器應用程序數量的增加,會增加更多的節點,從而提高存儲容量和性能的整體可用性,從而使存儲對新的應用程序容器可用。這一過程與 Nutanix
等成功的超融合系統非常相似。
OpenESB 架構介紹
OpenESB
遵循容器附加存儲(CAS
)模型,每個卷都有一個專用的控制器 POD
和一組副本 POD
。CAS
體系結構的優點在`CNCF` 博客[1]上進行了討論。OpenEBS
操作和使用都很簡單,因為它看起來和感覺上就像其他云原生和 Kubernetes
友好的項目。

OpenEBS
有許多組件,可以分為以下類別 :
- 控制面組件 -
Provisioner
,API Server
,volume exports
,volume sidecars
- 數據面組件 -
Jiva
、cStor
- 節點磁盤管理器 -
Discover
,monitor
, 管理連接k8s
的媒介 - 與云原生工具的集成 - 已經與
Prometheus
,Grafana
,Fluentd
、Jaeger
集成
控制面
OpenEBS
集群的控制平面通常被稱為Maya
。
OpenEBS
控制平面負責提供卷、相關的卷操作,如快照、克隆、創建存儲策略、執行存儲策略、導出 Prometheus/grafana
使用的卷指標,等等。

OpenEBS
提供了一個動態提供程序,這是 Kubernetes
的標準外部存儲插件。OpenEBS PV
提供者的主要任務是向應用程序 PODS
啟動卷供應,并實現 PV
的 Kubernetes
規范。
m-apiserver
開放存儲的 REST API
,并承擔大量卷策略處理和管理工作。
控制平面和數據平面之間的連通性使用 Kubernetes sidecar
模式??刂破矫嫘枰c數據平面通信的場景如下所示。
- 對于卷的統計,如
IOPS
,吞吐量,延遲等--通過卷暴漏的sidecar
實現 - 使用卷控制器
pod
執行卷策略,使用卷副本pod
進行磁盤 / 池管理-通過卷管理sidecar
實現
OpenEBS PV Provisioner

此組件作為 POD
運行,并做出配置決策 , 它的使用方式是 :
開發人員用所需的卷參數構造一個聲明,選擇適當的存儲類,并在 YAML
規范上調用 kubelet
。OpenEBS PV
動態提供程序與 maya-apiserver
交互,在適當的節點上為卷控制器 pod
和卷副本 pod
創建部署規范??梢允褂?PVC
規范中的注釋來控制卷 Pod
(控制器 / 副本) 的調度。
目前,OpenEBS Provisioner
只支持一種綁定類型,即 iSCSI
。
Maya-ApiServer

m-apiserver作為
POD運行。顧名思義,
m-apiserver公開
OpenEBS REST api`。
m-apiserver
還負責創建創建卷 pod
所需的部署規范文件。在生成這些規范文件之后,它將調用 kube-apiserver
來相應地調度這些 pods
。OpenEBS PV
提供者在卷發放結束時,將創建一個 PV
對象并將其掛載到應用程序 pod
上。PV
由控制器 pod
承載,控制器 pod
由不同節點中的一組副本 pod
支持??刂破?pod
和復制 pod
是數據平面的一部分,在存儲引擎部分有更詳細的描述。
m-apiserver
的另一個重要任務是卷策略管理。OpenEBS
為表示策略提供了非常細粒度的規范。m-apiserver
解釋這些 YAML
規范,將它們轉換為可執行的組件,并通過容量管理 sidecar
來執行它們
Maya Volume Exporter
Maya卷導出器是每個存儲控制器
pod的
sidecar`。
這些 sidecar
將控制平面連接到數據平面以獲取統計信息。統計信息的粒度在卷級別。一些統計數據示例如下:
- 卷讀取延遲
- 卷寫入延遲
- 卷每秒讀取速度
- 卷每秒寫入速度
- 讀取塊大小
- 寫入塊大小
- 容量統計

這些統計信息通常由 Prometheus
客戶端來拉取,該客戶端在 OpenBS
安裝期間安裝和配置。
卷管理 sidecar
Sidecars
還用于將控制器配置參數和卷策略傳遞給卷控制器 pod
(卷控制器 pod
是一個數據平面), 并將副本配置參數和副本數據保護參數傳遞給卷副本 pod
。

數據面
OpenEBS
數據平面負責實際的卷 IO
路徑。存儲引擎在數據平面實現實際的 IO
路徑。目前,OpenEBS
提供了兩個可以輕松插入的存儲引擎。它們被稱為 Jiva
和 cStor
。這兩個存儲引擎都完全運行在 Linux
用戶空間中,并基于微服務架構。
Jiva
Jiva
存儲引擎基于 Rancher's LongHorn
與 gotgt
開發實現, 使用 go
語言開發,并運行于用戶命名空間下。LongHorn
控制器將輸入的 IO
同步復制到 LongHorn
副本。該副本將 Linux
稀疏文件視為構建存儲特性 (如精簡配置、快照、重建等) 的基礎。
cStor
cStor
數據引擎使用 C
語言編寫,具有高性能的 iSCSI target
和 Copy-On-Write
塊系統,提供數據完整性、數據彈性和時間點的快照和克隆。cStor
有一個池特性,它以條帶、鏡像或 RAIDZ
模式聚合一個節點上的磁盤,以提供更大的容量和性能單位。cStor
還可以跨區域將數據同步復制到多個節點,從而避免節點丟失或節點重啟導致數據不可用。
LocalPV
對于那些不需要存儲級復制的應用程序,LocalPV
可能是很好的選擇,因為它能提供更高的性能。OpenEBS LocalPV
與 Kubernetes LocalPV
類似,不同之處在于它是由 OpenEBS
控制平面動態提供的, 就像任何其他常規 PV
一樣。OpenEBS LocalPV
有兩種類型 :hostpath LocalPV
和 device LocalPV
。hostpath LocalPV
指的是主機上的子目錄,LocalPV
指的是在節點上發現的磁盤 (可以是直接連接的,也可以是網絡連接的)。OpenEBS
引入了一個 LocalPV
提供者,用于根據 PVC
和存儲類規范中的一些標準選擇匹配的磁盤或主機路徑。
節點磁盤管理器
節點磁盤管理器 (NDM
) 填補了使用 Kubernetes
管理有狀態應用程序的持久存儲所需的工具鏈的空白。容器時代的 DevOps
架構師必須以一種自動化的方式滿足應用程序和應用程序開發人員的基礎設施需求, 這種方式可以跨環境提供彈性和一致性。這些要求意味著存儲堆棧本身必須非常靈活, 以便 Kubernetes
和云原生生態系統中的其他軟件可以輕松地使用這個堆棧。NDM
在 Kubernetes
的存儲堆棧中起著基礎性的作用,它統一了不同的磁盤, 并通過將它們標識為 Kubernetes
對象,提供了將它們匯聚的能力。此外,NDM
發現、提供、監視和管理底層磁盤的方式,可以讓 Kubernetes PV
提供者 (如 OpenEBS
和其他存儲系統) 和 Prometheus
管理磁盤子系統

CAS 引擎
存儲引擎概述
存儲引擎是持久化卷 IO
路徑的數據平面組件。在 CAS
架構中,用戶可以根據不同的配置策略,為不同的應用工作負載選擇不同的數據平面。存儲引擎可以通過特性集或性能優化給定的工作負載。
操作員或管理員通常選擇具有特定軟件版本的存儲引擎,并構建優化的卷模板, 這些卷模板根據底層磁盤的類型、彈性、副本數量和參與 Kubernetes
集群的節點集進行微調。用戶可以在發放卷時選擇最優的卷模板,從而在給定的 Kubernetes
集群上為所有存儲卷運行最優的軟件和存儲組合提供最大的靈活性。
存儲引擎類型
OpenEBS
提供了三種存儲引擎
Jiva
Jiva
是OpenEBS 0.1
版中發布的第一個存儲引擎,使用起來最簡單。它基于GoLang
開發,內部使用LongHorn
和gotgt
堆棧。Jiva
完全在用戶空間中運行,并提供同步復制等標準塊存儲功能。Jiva
通常適用于容量較小的工作負載,不適用于大量快照和克隆特性是主要需求的情況cStor
cStor
是OpenEBS 0.7
版本中最新發布的存儲引擎。cStor
非常健壯,提供數據一致性,很好地支持快照和克隆等企業存儲特性。 它還提供了一個健壯的存儲池特性,用于在容量和性能方面進行全面的存儲管理。cStor
與NDM
(Node Disk Manager
) 一起,為Kubernetes
上的有狀態應用程序提供完整的持久化存儲特性OpenEBS Local PV
OpenEBS Local PV
是一個新的存儲引擎,它可以從本地磁盤或工作節點上的主機路徑創建持久卷或PV
。CAS
引擎可以從OpenEBS
的1.0.0
版本中獲得。使用OpenEBS Local PV
,性能將等同于創建卷的本地磁盤或文件系統 (主機路徑)。 許多云原生應用程序可能不需要復制、快照或克隆等高級存儲特性,因為它們本身就提供了這些特性。這類應用程序需要以持久卷的形式訪問管理的磁盤

SP
存儲池,表示Jiva
自定義存儲資源CV
cStor
卷,表示cStor
卷自定義資源CVR
cStor
卷副本SPC
存儲池聲明,表示cStor
池聚合的自定義資源CSP
cStor
存儲池,表示cStor Pool
每個節點上的自定義資源
一個 SPC
對應多個 CSP
,相應的一個 CV
對應多個 CVR
存儲引擎聲明
通過指定注釋 openebs
來選擇存儲引擎。StorageClass
規范中的 io/cas-type
。StorageClass
定義了提供程序的細節。為每個 CAS
引擎指定單獨的供應程序。
cStor 存儲類規范文件內容
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: cStor-storageclass
annotations:
openebs.io/cas-type: cstor
cas.openebs.io/config: |
- name: StoragePoolClaim
value: "cStorPool-SSD"
provisioner: openebs.io/provisioner-iscsi
---
Jiva 存儲類規范文件內容
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: jiva-storageclass
annotations:
openebs.io/cas-type: jiva
cas.openebs.io/config: |
- name: StoragePool
value: default
provisioner: openebs.io/provisioner-iscsi
---
當 cas
類型為 Jiva
時,StoragePool
的 default
值具有特殊含義。當 pool
為默認值時,Jiva
引擎將從容器 (副本 pod
) 本身的存儲空間中為副本 pod
開辟數據存儲空間。當所需的卷大小很小 (比如 5G
到 10G
) 時,StoragePool default
工作得很好,因為它可以容納在容器本身內。
Local PV 存儲類規范文件內容-主機路徑
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: localpv-hostpath-sc
annotations:
openebs.io/cas-type: local
cas.openebs.io/config: |
- name: BasePath
value: "/var/openebs/local"
- name: StorageType
value: "hostpath"
provisioner: openebs.io/local
---
Local PV 存儲類規范文件內容-主機設備
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: localpv-device-sc
annotations:
openebs.io/cas-type: local
cas.openebs.io/config: |
- name: StorageType
value: "device"
- name: FSType
value: ext4
provisioner: openebs.io/local
---
cStor
、Jiva
、LocalPV
特性比較:
特性 | Jiva | cStor | Local PV |
---|---|---|---|
輕量級運行于用戶空間 | Yes | Yes | Yes |
同步復制 | Yes | Yes | No |
適合低容量工作負載 | Yes | Yes | Yes |
支持快照,克隆 | Basic | Advanced | No |
數據一致性 | Yes | Yes | NA |
使用 Velero 恢復備份 | Yes | Yes | Yes |
適合高容量工作負載 | No | Yes | Yes |
自動精簡配置 | Yes | No | |
磁盤池或聚合支持 | Yes | No | |
動態擴容 | Yes | Yes | |
數據彈性 (RAID 支持) | Yes | No | |
接近原生磁盤性能 | No | No | Yes |
大多數場景推薦 cStor
,因其提供了強大的功能,包括快照 / 克隆、存儲池功能(如精簡資源調配、按需擴容等)。
Jiva
適用于低容量需求的工作負載場景,例如 5
到 50G
。盡管使用 Jiva
沒有空間限制,但建議將其用于低容量工作負載。Jiva
非常易于使用,并提供企業級容器本地存儲,而不需要專用硬盤。有快照和克隆功能的需求的場景,優先考慮使用 cStor
而不是 Jiva
。
CAS 引擎使用場景
如上表所示,每個存儲引擎都有自己的優勢。選擇引擎完全取決于應用程序的工作負載以及它當前和未來的容量和 / 或性能增長。下面的指導原則在定義存儲類時為選擇特定的引擎提供一些幫助。
選擇 cStor 的理想條件
- 當需要同步復制數據并在節點上有多個磁盤時
- 當您從每個節點上的本地磁盤或網絡磁盤池管理多個應用程序的存儲時。通過精簡配置、存儲池和卷的按需擴容、存儲池的性能按需擴容等特性,實現對存儲層的管理。
cStor
用于在本地運行的Kubernetes
集群上構建Kubernetes
本地存儲服務,類似于AWS EBS
或谷歌PD
。 - 當需要存儲級快照和克隆能力時
- 當您需要企業級存儲保護特性,如數據一致性、彈性 (
RAID
保護)。 - 如果您的應用程序不需要存儲級復制,那么使用
OpenEBS
主機路徑LocalPV
或OpenEBS
設備LocalPV
可能是更好的選擇。
選擇 Jiva 的理想條件 :
當您想要數據的同步復制,并且擁有單個本地磁盤或單個管理磁盤 (如云磁盤 (
EBS
、GPD
)),并且不需要快照或克隆特性時Jiva
是最容易管理的,因為磁盤管理或池管理不在這個引擎的范圍內。Jiva
池是本地磁盤、網絡磁盤、虛擬磁盤或云磁盤的掛載路徑。以下場景 Jiva 更優于 cStor :
- 當程序不需要存儲級的快照、克隆特性
- 當節點上沒有空閑磁盤時。
Jiva
可以在主機目錄上使用,并且仍然可以實現復制。 - 當不需要動態擴展本地磁盤上的存儲時。將更多磁盤添加到
Jiva
池是不可能的,因此Jiva
池的大小是固定的,如果它在物理磁盤上。但是,如果底層磁盤是虛擬磁盤、網絡磁盤或云磁盤,則可以動態地更改Jiva
池的大小 - 容量需求較小。大容量應用通常需要動態增加容量,
cStor
更適合這種需求
選擇 OpenEBS 主機路徑 LocalPV 的理想條件 :
- 當應用程序本身具備管理復制能力(例如:
es
)時,不需要在存儲層進行復制。在大多數這樣的情況下,應用程序是作為statefulset
部署的 - 高于
Jiva
與cStor
的讀寫性能需求 - 當特定應用程序沒有專用的本地磁盤或特定應用程序不需要專用的存儲時,建議使用
Hostpath
。如果您想跨多個應用程序共享一個本地磁盤,主機路徑LocalPV
是正確的方法
選擇 OpenEBS 主機設備 LocalPV 的理想條件 :
- 當應用程序管理復制本身,不需要在存儲層進行復制時。在大多數這種情況下,應用程序被部署為有狀態集
- 高于
Jiva
與cStor
的讀寫性能需求 - 高于
OpenEBS
主機路徑LocalPV
的讀寫性能需求 - 當需要接近磁盤性能時。該卷專用于寫入單個
SSD
或NVMe
接口以獲得最高性能
總結
- 如果應用程序處于生產中,并且不需要存儲級復制,那么首選
LocalPV
- 如果您的應用程序處于生產狀態,并且需要存儲級復制,那么首選
cStor
- 如果應用程序較小,需要存儲級復制,但不需要快照或克隆,則首選
Jiva
節點磁盤管理器(NDM)
節點磁盤管理器 (NDM
) 是 OpenEBS
體系結構中的一個重要組件。NDM
將塊設備視為需要監視和管理的資源,就像 CPU
、內存和網絡等其他資源一樣。它是一個在每個節點上運行的守護進程,基于過濾器檢測附加的塊設備,并將它們作為塊設備自定義資源加載到 Kubernetes
中。這些定制資源旨在通過提供類似于 :
- 輕松訪問
Kubernetes
集群中可用的塊設備清單 - 預測磁盤的故障,以幫助采取預防措施
- 允許動態地將磁盤掛載 / 卸載到存儲
Pod
中,而無需重新啟動在磁盤掛載 / 卸載的節點上運行的相應NDM Pod
盡管做了上述所有工作,NDM
還是有助于提供持久卷的總體簡化。

NDM
是在 OpenEBS
安裝期間作為守護進程部署的。NDM daemonset
發現每個節點上的磁盤,并創建一個名為 Block Device
或 BD
的自定義資源。
訪問權限說明
NDM
守護進程運行在容器中,必須訪問底層存儲設備并以特權模式運行。NDM
需要特權模式,因為它需要訪問 /dev、/proc
和 /sys
目錄來監視附加設備,還需要使用各種探測器獲取附加設備的詳細信息。NDM
負責發現塊設備并過濾掉不應該被 OpenEBS
使用的設備 ; 例如,檢測有 OS
文件系統的磁盤。NDM pod
默認情況下在容器中掛載主機的 /proc
目錄,然后加載 /proc/1/mounts
,以找到操作系統使用的磁盤
NDM 守護程序功能
發現
Kubernetes
節點上的塊設備- 在啟動時發現塊設備-創建和 / 或更新狀態。
- 維護集群范圍內磁盤的唯一
id
: 對WWN / PartitionUUID / FileSystemUUID / DeviceMapperUUID
進行Hash
計算 檢測節點中添加 / 移除塊設備,并更新塊設備狀態
- 添加塊設備作為
Kubernetes
自定義資源,具有以下屬性: Active
: 節點上存在塊設備Inactive
: 給定節點上不存在塊設備Unknown
:NDM
在塊設備最后被檢測到的節點上停止 / 無法確定狀態- 主機名稱 (
kubernetes.io/hostname
) - 塊設備類型 (
ndm.io/blockdevice-type
) - Managed (
ndm.io/managed
) - 設備路徑
- 設備鏈接
- 供應商和型號信息
WWN
和序列號- 容量
- 扇區和區塊大小
spec
: 如果可用,將更新以下內容labels
:status
: 狀態可以有以下值
過濾器
為要創建塊設備
CR
的塊設備類型配置過濾器。過濾器可以通過供應商類型、設備路徑模式或掛載點進行配置過濾器可以是包含過濾器,也可以是排除過濾器。它們被配置為
configmap
。管理員用戶可以在OpenEBS
安裝時通過更改OpenEBS
操作員yaml
文件或helm
值中的NDM configmap
來配置這些過濾器。yaml
文件。如果這些過濾器需要在安裝后更新,那么可以遵循以下方法之一 :- 使用
operator
方式安裝OpenEBS
。在Yaml
文件中,更新configmap
中的過濾器并應用operator.yaml
- 如果
OpenEBS
是使用helm
安裝的,更新values.yaml
中的configmap
并使用helm
進行升級 - 或者,使用
kubectl
編輯NDM configmap
,更新過濾器
落地實踐
OpenEBS
的 cStor
與 Jiva
引擎由于組件過多,配置相較其他存儲方案繁瑣,生產環境不建議使用,這里我們僅論述 Local PV
引擎。
Local PV
引擎不具備存儲級復制能力,適用于 k8s
有狀態服務的后端存儲(如 : es
、redis
等)
Local PV Hostpath 實踐
對比 Kubernetes Hostpath
卷相比,OpenEBS 本地 PV Hostpath
卷具有以下優勢 :
OpenEBS
本地PV Hostpath
允許您的應用程序通過StorageClass
、PVC
和PV
訪問Hostpath
。這為您提供了更改PV
提供者的靈活性,而無需重新設計應用程序YAML
- 使用
Velero
備份和恢復進行數據保護 - 通過對應用程序
YAML
和pod
完全屏蔽主機路徑來防范主機路徑安全漏洞
環境依賴 :
k8s 1.12
以上OpenEBS 1.0
以上
實踐環境 :
docker 19.03.8
k8s 1.18.6
CentOS7
$ kubectl get node
NAME STATUS ROLES AGE VERSION
node1 Ready master,worker 8m8s v1.18.6
node2 Ready master,worker 7m15s v1.18.6
node3 Ready master,worker 7m15s v1.18.6
創建數據目錄
在將要創建 Local PV Hostpaths
的節點上設置目錄。這個目錄將被稱為 BasePath
。默認位置是 /var/openebs/local
節點 node1
、node2
、node3
創建 /data/openebs/local
目錄 (/data 可以預先掛載數據盤,如未掛載額外數據盤,則使用操作系統 '/' 掛載點存儲空間)
$ mkdir -p /data/openebs/local
下載應用描述文件
yaml 文件[2]
發布 openebs
應用
根據上述配置文件,保證 k8s
集群可訪問到如下鏡像(建議導入本地私有鏡像庫,如 : harbor
)
openebs/node-disk-manager:1.5.0
openebs/node-disk-operator:1.5.0
openebs/provisioner-localpv:2.10.0
更新 openebs-operator.yaml
中鏡像 tag
為實際 tag
image: openebs/node-disk-manager:1.5.
image: openebs/node-disk-operator:1.5.
image: openebs/provisioner-localpv:2.10.
發布
$ kubectl apply -f openebs-operator.yaml
查看發布狀態
$ kubectl get pod -n openebs -w
NAME READY STATUS RESTARTS AGE
openebs-localpv-provisioner-6d6d9cfc99-4sltp 1/1 Running 10s
openebs-ndm-85rng 1/1 Running 10s
openebs-ndm-operator-7df6668998-ptnlq /1 Running 10s
openebs-ndm-qgqm9 1/1 Running 10s
openebs-ndm-zz7ps 1/1 Running 10s
創建存儲類
更改配置文件中的內容
value: "/var/openebs/local/"
發布創建存儲類
$ cat > openebs-hostpath-sc.yaml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: openebs-hostpath
annotations:
openebs.io/cas-type: local
cas.openebs.io/config: |
#hostpath type will create a PV by
# creating a sub-directory under the
# BASEPATH provided below.
- name: StorageType
value: "hostpath"
#Specify the location (directory) where
# where PV(volume) data will be saved.
# A sub-directory with pv-name will be
# created. When the volume is deleted,
# the PV sub-directory will be deleted.
#Default value is /var/openebs/local
- name: BasePath
value: "/data/openebs/local/"
provisioner: openebs.io/local
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
EOF
$ kubectl apply -f openebs-hostpath-sc.yaml
創建 PVC 驗證可用性
$ cat > local-hostpath-pvc.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: local-hostpath-pvc
spec:
storageClassName: openebs-hostpath
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5G
EOF
$ kubectl apply -f local-hostpath-pvc.yaml
查看 pvc
狀態
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
local-hostpath-pvc Pending openebs-hostpath 2m15s
輸出顯示 STATUS
為 Pending
。這意味著 PVC
還沒有被應用程序使用。
創建 Pd
$ cat > local-hostpath-pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: hello-local-hostpath-pod
spec:
volumes:
- name: local-storage
persistentVolumeClaim:
claimName: local-hostpath-pvc
containers:
- name: hello-container
image: busybox
command:
- sh
- -c
- 'while true; do echo "`date` [`hostname`] Hello from OpenEBS Local PV." >> /mnt/store/greet.txt; sleep $(($RANDOM % 5 + 300)); done'
volumeMounts:
- mountPath: /mnt/store
name: local-storage
EOF
發布創建
$ kubectl apply -f local-hostpath-pod.yaml
驗證數據是否寫入卷
$ kubectl exec hello-local-hostpath-pod -- cat /mnt/store/greet.txt
Thu Jun 24 15:10:45 CST 2021 [node1] Hello from OpenEBS Local PV.
驗證容器是否使用 Local PV Hostpath 卷
$ kubectl describe pod hello-local-hostpath-pod
Name: hello-local-hostpath-pod
Namespace: default
Priority:
...
Volumes:
local-storage:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: local-hostpath-pvc
ReadOnly: false
default-token-98scc:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-98scc
Optional: false
...
查看 PVC 狀態
$ kubectl get pvc local-hostpath-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
local-hostpath-pvc Bound pvc-6eac3773-49ef-47af-a475-acb57ed15cf6 5G RWO openebs-hostpath 10m
查看該 PV 卷數據存儲目錄為
$ kubectl get -o yaml pv pvc-6eac3773-49ef-47af-a475-acb57ed15cf6|grep 'path:'
f:path: {}
path: /data/openebs/local/pvc-6eac3773-49ef-47af-a475-acb57ed15cf6
并且 pv
配置了親和性,制定了調度節點為 node2
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 5G
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: local-hostpath-pvc
namespace: default
resourceVersion: "9034"
uid: 6eac3773-49ef-47af-a475-acb57ed15cf6
local:
fsType: ""
path: /data/openebs/local/pvc-6eac3773-49ef-47af-a475-acb57ed15cf6
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node2
persistentVolumeReclaimPolicy: Delete
storageClassName: openebs-hostpath
volumeMode: Filesystem
結果證明數據僅存在于 node2
下。
清理 Pod
$ kubectl delete pod hello-local-hostpath-pod
基準測試
下載基準測試 Job 聲明文件[3]
調整以下內容
image: openebs/perf-test:latest # 調整為內網鏡像庫tag
claimName: dbench # 調整為local-hostpath-pvc
發布運行
$ kubectl create -f fio-deploy.yaml
查看運行狀態
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
dbench-729cw-nqfpt 1/1 Running 24s
查看基準測試結果
$ kubectl logs -f dbench-729cw-nqfpt
...
All tests complete.
==================
= Dbench Summary =
==================
Random Read/Write IOPS: 2144/6654. BW: 131MiB/s / 403MiB/s
Average Latency (usec) Read/Write: 4254.08/3661.59
Sequential Read/Write: 1294MiB/s / 157MiB/s
Mixed Random Read/Write IOPS: 1350/443
清理
$ kubectl delete pvc local-hostpath-pvc
$ kubectl delete sc openebs-hostpath
Local PV Device 實踐
對比 Kubernetes
本地持久卷,OpenEBS
本地 PV
設備卷有以下優點 :
OpenEBS
本地PV
設備卷provider
是動態的,Kubernetes
設備卷provider
是靜態的OpenEBS NDM
更好地管理用于創建本地pv
的塊設備。NDM
提供了發現塊設備屬性、設置設備篩選器、度量集合以及檢測塊設備是否已經跨節點移動等功能
環境依賴 :
k8s 1.12
以上OpenEBS 1.0
以上
實踐環境 :
docker 19.03.8
k8s 1.18.6
CentOS7
$ kubectl get node
NAME STATUS ROLES AGE VERSION
node1 Ready master,worker 8m8s v1.18.6
node2 Ready master,worker 7m15s v1.18.6
node3 Ready master,worker 7m15s v1.18.6
三個節點上的 /dev/sdb
作為塊設備存儲
[root@node1 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 400G disk
├─sda1 8:1 1G part /boot
└─sda2 8:2 399G part
└─centos-root 253:0 399G lvm /
sdb 8:16 20G disk
sr0 11:0 1 4.4G rom
[root@node2 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 400G disk
├─sda1 8:1 1G part /boot
└─sda2 8:2 399G part
└─centos-root 253:0 399G lvm /
sdb 8:16 20G disk
sr0 11:0 1 4.4G rom
[root@node3 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 400G disk
├─sda1 8:1 1G part /boot
└─sda2 8:2 399G part
└─centos-root 253:0 399G lvm /
sdb 8:16 20G disk
sr0 11:0 1 4.4G rom
創建數據目錄
在將要創建 Local PV Hostpaths
的節點上設置目錄。這個目錄將被稱為 BasePath
。默認位置是 /var/openebs/local
節點 node1
、node2
、node3
創建 /data/openebs/local
目錄 (/data 可以預先掛載數據盤,如未掛載額外數據盤,則使用操作系統 '/' 掛載點存儲空間)
$ mkdir -p /data/openebs/local
下載應用描述文件
yaml 文件[4]
發布 openebs 應用
根據上述配置文件,保證 k8s
集群可訪問到如下鏡像(建議導入本地私有鏡像庫,如 : harbor
)
openebs/node-disk-manager:1.5.0
openebs/node-disk-operator:1.5.0
openebs/provisioner-localpv:2.10.0
更新 openebs-operator.yaml
中鏡像 tag
為實際 tag
image: openebs/node-disk-manager:1.5.
image: openebs/node-disk-operator:1.5.
image: openebs/provisioner-localpv:2.10.
發布
$ kubectl apply -f openebs-operator.yaml
查看發布狀態
$ kubectl get pod -n openebs -w
NAME READY STATUS RESTARTS AGE
openebs-localpv-provisioner-6d6d9cfc99-4sltp 1/1 Running 10s
openebs-ndm-85rng 1/1 Running 10s
openebs-ndm-operator-7df6668998-ptnlq /1 Running 10s
openebs-ndm-qgqm9 1/1 Running 10s
openebs-ndm-zz7ps 1/1 Running 10s
創建存儲類
$ cat > local-device-sc.yaml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-device
annotations:
openebs.io/cas-type: local
cas.openebs.io/config: |
- name: StorageType
value: device
provisioner: openebs.io/local
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
EOF
$ kubectl apply -f local-device-sc.yaml
創建 Pod 及 PVC
$ cat > local-device-pod.yaml <<EOF
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: local-device-pvc
spec:
storageClassName: local-device
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5G
---
apiVersion: v1
kind: Pod
metadata:
name: hello-local-device-pod
spec:
volumes:
- name: local-storage
persistentVolumeClaim:
claimName: local-device-pvc
containers:
- name: hello-container
image: busybox
command:
- sh
- -c
- 'while true; do echo "`date` [`hostname`] Hello from OpenEBS Local PV." >> /mnt/store/greet.txt; sleep $(($RANDOM % 5 + 300)); done'
volumeMounts:
- mountPath: /mnt/store
name: local-storage
EOF
發布
$ kubectl apply -f local-device-pod.yaml
查看 pod
狀態
$ kubectl get pod hello-local-device-pod -w
NAME READY STATUS RESTARTS AGE
hello-local-device-pod 1/1 Running 9s
確認 pod
關聯 pvc
是否為 local-device-pvc
$ kubectl describe pod hello-local-device-pod
Name: hello-local-device-pod
Namespace: default
Node: node2/192.168.1.112
...
Volumes:
local-storage:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: local-device-pvc
ReadOnly: false
...
觀察到調度的節點為 node2
,確認 node2
節點 /dev/sdb
是否被使用
[root@node2 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 400G disk
├─sda1 8:1 1G part /boot
└─sda2 8:2 399G part
└─centos-root 253:0 399G lvm /
sdb 8:16 20G disk
sr0 11:0 1 4.4G rom
[root@node2 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 400G disk
├─sda1 8:1 1G part /boot
└─sda2 8:2 399G part
└─centos-root
253:0 399G lvm /
sdb 8:16 20G disk /var/lib/kubelet/pods/266b7b14-5eb7-40ec-bccb-3ac189acf939/volumes/kubernetes.io~local-volume/pvc-9bd89019-13dc-4
sr0 11:0 1 4.4G rom
確實被使用,OpenEBS
強大之處則在于此,極致的簡潔。如上文我們討論的那樣,NDM
負責發現塊設備并過濾掉不應該被 OpenEBS
使用的設備,例如,檢測有 OS
文件系統的磁盤。
基準測試
創建基準測試 pvc
$ cat > dbench-pvc.yaml <<EOF
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: dbench
spec:
storageClassName: local-device
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5G
EOF
下載基準測試 Job 聲明文件[5]
調整以下內容
image: openebs/perf-test:latest # 調整為內網鏡像庫tag
發布運行
$ kubectl create -f dbench-pvc.yaml
$ kubectl create -f fio-deploy.yaml
查看運行狀態
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
dbench-vqk68-f9877 1/1 Running 24s
查看基準測試結果
$ kubectl logs -f dbench-vqk68-f9877
...
All tests complete.
==================
= Dbench Summary =
==================
Random Read/Write IOPS: 3482/6450. BW: 336MiB/s / 1017MiB/s
Average Latency (usec) Read/Write: 2305.77/1508.63
Sequential Read/Write: 6683MiB/s / 2312MiB/s
Mixed Random Read/Write IOPS: 3496/1171
從結果來看,相較 Local PV HostPath
模式性能翻倍
總結
在整個測試驗證過程,OpenEBS
給我的感覺是:極簡的操作,尤其 Local PV
引擎的部署使用。
但 OpenEBS
現階段也存在一些不足:
cStor
與Jiva
數據面組件較多,配置較為繁瑣(第一感覺概念性的組件過多,)cStor
與Jiva
部分組件創建依賴內部定義的鏡像tag
,在離線環境下無法通過調整為私有庫tag
導致組件無法成功運行- 存儲類型單一,多個引擎僅支持塊存儲類型,不支持原生多節點讀寫(需結合
NFS
實現),對比ceph
等稍顯遜色
建議以下場景使用 OpenEBS
作為后端存儲:
- 單機測試環境
- 多機實驗 / 演示環境
引用鏈接
[1]CNCF
博客: https://www.cncf.io/blog/2018/04/19/container-attached-storage-a-primer/
yaml 文件: https://openebs.github.io/charts/openebs-operator-lite.yaml
[3]基準測試 Job 聲明文件: https://github.com/openebs/performance-benchmark/blob/master/fio-benchmarks/fio-deploy.yaml
[4]yaml 文件: https://openebs.github.io/charts/openebs-operator.yaml
[5]基準測試 Job 聲明文件: https://github.com/openebs/performance-benchmark/blob/master/fio-benchmarks/fio-deploy.yaml