简介
OpenEBS是一种开源云原生存储解决方案,托管于CNCF基金会,目前该项目处于沙箱阶段,
OpenEBS是一组存储引擎,允许您为有状态工作负载(StatefulSet)和Kubernetes平台类型选择正确的存储解决方案。 在高层次上,OpenEBS支持两大类卷——本地卷和复制卷
OpenEBS是Kubernetes本地超融合存储解决方案,它管理节点可用的本地存储,并为有状态工作负载提供本地或高可用的分布式持久卷。 作为一个完全的Kubernetes原生解决方案的另一个优势是,管理员和开发人员可以使用kubectl、Helm、 Prometheus、Grafana、Weave Scope等Kubernetes可用的所有优秀工具来交互和管理OpenEBS
OpenEBS是一款使用Go语言编写的基于容器的块存储开源软件。OpenEBS使得在容器中运行关键性任务和需要数据持久化的负载变得更可靠。
OpenEBS由CloudByte研发,这是一家专业做容器化存储的公司,OpenEBS是其一款开源产品,CloudByte将其在企业级容器存储的经验付诸到该项目中。这个项目的愿景也很简单,就是让需要持久化存储的工作负载中的存储服务能够直接集成在环境中,存储服务可以自动管理,将存储的细节隐藏起来,就像存储系统是另一套基础架构一样。
使用OpenEBS,你可以将有持久化数据的容器,像对待其他普通容器一样来对待。OpenEBS本身也是通过容器来部署的,支持Kubernetes、Swarm、Mesos、Rancher编排调度,存储服务可以分派给每个pod、应用程序、集群或者容器级别,包括:
- 跨节点的数据持久化
- 跨可用区和云厂商的数据同步
- 使用商业硬件和容器引擎来提供高可扩展的块存储
- 与容器编排引擎集成,开发者的应用程序可以自动的配置OpenEBS
- 基于CloudByte在BSD的容器化经验,为用户提供OpenEBS的QoS保证
OpenEBS能做什么?

OpenEBS管理k8s节点上存储,并为k8s有状态负载(StatefulSet)提供本地存储卷或分布式存储卷。
- 本地卷(
Local Storage)
-
OpenEBS可以使用宿主机裸块设备或分区,或者使用Hostpaths上的子目录,或者使用LVM、ZFS来创建持久化卷 - 本地卷直接挂载到
Stateful Pod中,而不需要OpenEBS在数据路径中增加任何开销 -
OpenEBS为本地卷提供了额外的工具,用于监控、备份/恢复、灾难恢复、由ZFS或LVM支持的快照等
- 对于分布式卷(即复制卷)
-
OpenEBS使用其中一个引擎(Mayastor、cStor或Jiva)为每个分布式持久卷创建微服务 - 有状态
Pod将数据写入OpenEBS引擎,OpenEBS引擎将数据同步复制到集群中的多个节点。OpenEBS引擎本身作为pod部署,并由Kubernetes进行协调。 当运行Stateful Pod的节点失败时,Pod将被重新调度到集群中的另一个节点,OpenEBS将使用其他节点上的可用数据副本提供对数据的访问 - 有状态的
Pods使用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的精简配置能力可以共享本地存储或云存储,然后根据需要增加有状态应用程序的数据量。 可以动态添加存储,而不会中断暴露给工作负载或应用程序的卷。 某些用户报告说,由于使用了OpenEBS的精简配置,节省了超过60%的资源。
高可用性

由于OpenEBS遵循CAS架构,在节点故障时,Kubernetes将重新调度OpenEBS控制器,而底层数据则通过使用一个或多个副本来保护。 更重要的是——因为每个工作负载都可以利用自己的OpenEBS——不存在因存储丢失而导致系统大范围宕机的风险。 例如,卷的元数据不是集中的,它可能会像许多共享存储系统那样受到灾难性的通用中断的影响。 相反,元数据保持在卷的本地。丢失任何节点都会导致只存在于该节点上的卷副本的丢失。 由于卷数据至少在其他两个节点上进行了同步复制,因此当一个节点出现故障时,这些数据将在相同的性能级别上继续可用
OpenESB架构介绍
OpenESB遵循容器附加存储(CAS)模型,每个卷都有一个专用的控制器POD和一组副本POD。 CAS体系结构的优点在CNCF博客 上进行了讨论。 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模式。控制平面需要与数据平面通信的场景如下所示。
- 对于卷的统计,如
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自定义存储资源 -
CVcStor卷,表示cStor卷自定义资源 -
CVRcStor卷副本 -
SPC 存储池声明,表示cStor池聚合的自定义资源 -
CSPcStor存储池,表示cStor Pool每个节点上的自定义资源
一个SPC对应多个CSP,相应的一个CV对应多个CVR
存储引擎声明
通过指定注释openebs来选择存储引擎。 StorageClass规范中的io/cas-type。StorageClass定义了提供程序的细节。为每个CAS引擎指定单独的供应程序。
cStor存储类规范文件内容
---apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: 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/v1kind: StorageClassmetadata: name: jiva-storageclass annotations: openebs.io/cas-type: jiva cas.openebs.io/config: | - name: StoragePool value: defaultprovisioner: openebs.io/provisioner-iscsi---
当cas类型为Jiva时,StoragePool的default值具有特殊含义。 当pool为默认值时,Jiva引擎将从容器(副本pod)本身的存储空间中为副本pod开辟数据存储空间。 当所需的卷大小很小(比如5G到10G)时,StoragePool default工作得很好,因为它可以容纳在容器本身内。
Local PV存储类规范文件内容-主机路径
---apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: 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/v1kind: StorageClassmetadata: name: localpv-device-sc annotations: openebs.io/cas-type: local cas.openebs.io/config: | - name: StorageType value: "device" - name: FSType value: ext4provisioner: 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自定义资源,具有以下属性:
spec: 如果可用,将更新以下内容
- 设备路径
- 设备链接
- 供应商和型号信息
-
WWN和序列号 - 容量
- 扇区和区块大小
labels:
- 主机名称(
kubernetes.io/hostname) - 块设备类型(
ndm.io/blockdevice-type) - Managed (
ndm.io/managed)
status: 状态可以有以下值
-
Active : 节点上存在块设备 -
Inactive : 给定节点上不存在块设备 -
Unknown :NDM在块设备最后被检测到的节点上停止/无法确定状态
过滤器
- 为要创建块设备
CR的块设备类型配置过滤器。过滤器可以通过供应商类型、设备路径模式或挂载点进行配置 - 过滤器可以是包含过滤器,也可以是排除过滤器。它们被配置为
configmap。 管理员用户可以在OpenEBS安装时通过更改OpenEBS操作员yaml文件或helm值中的NDM configmap来配置这些过滤器。yaml文件。如果这些过滤器需要在安装后更新,那么可以遵循以下方法之一:
- 使用
operator方式安装OpenEBS。在Yaml文件中,更新configmap中的过滤器并应用operator.yaml - 如果
OpenEBS是使用helm安装的,更新values.yaml中的configmap并使用helm进行升级 - 或者,使用
kubectl编辑NDM configmap,更新过滤器
安装
所有K8S计算节点均要安装iSCSI 启动器
yum install iscsi-initiator-utils -y
systemctl enable --now iscsid
systemctl start iscsid.service
systemctl status iscsid.service
安装OpenEBS
kubectl create ns openebs
kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml
kubectl get pods -n openebs
查看启动服务和存储
kubectl get all -n openebs
[root@k8s-master openebs]# kubectl get pod -nopenebs
NAME READY STATUS RESTARTS AGE
maya-apiserver-f9f7c6bb7-qxbnw 1/1 Running 2 3h55m
openebs-admission-server-7b9d59c456-cj5r7 1/1 Running 0 3h55m
openebs-localpv-provisioner-6f67fb4868-wjnwq 1/1 Running 0 3h55m
openebs-ndm-6b5vd 1/1 Running 0 3h55m
openebs-ndm-8tpmt 1/1 Running 0 3h55m
openebs-ndm-ccrk2 1/1 Running 0 3h55m
openebs-ndm-operator-58bc5f4d47-snv7h 1/1 Running 0 3h55m
openebs-ndm-wbskl 1/1 Running 0 3h55m
openebs-provisioner-76cd669b6-tn7d4 1/1 Running 0 3h55m
openebs-snapshot-operator-54d76b9-lwj7s 2/2 Running 0 3h55m
[root@k8s-master openebs]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
openebs-jiva-default openebs.io/provisioner-iscsi Delete Immediate false 3h54m
openebs-snapshot-promoter volumesnapshot.external-storage.k8s.io/snapshot-promoter Delete Immediate false 3h54m
ssd-storage kubernetes.io/no-provisioner Delete WaitForFirstConsumer false 17d

创建动态Local PV的存储类SC
[root@k8s-master openebs]# cat local-device-sc-hostpath.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-hostpath
annotations:
openebs.io/cas-type: local
cas.openebs.io/config: |
- name: StorageType
value: hostpath
- name: BasePath
value: /home/openebs/local ####更改对应的存储路径
provisioner: openebs.io/local
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
[root@k8s-master openebs]# kubectl apply -f local-device-sc-hostpath.yaml
storageclass.storage.k8s.io/local-hostpath unchanged
[root@k8s-master openebs]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-device openebs.io/local Delete WaitForFirstConsumer false 98m
local-hostpath openebs.io/local Delete WaitForFirstConsumer false 76m
openebs-jiva-default openebs.io/provisioner-iscsi Delete Immediate false 4h
openebs-snapshot-promoter volumesnapshot.external-storage.k8s.io/snapshot-promoter Delete Immediate false 4h
ssd-storage kubernetes.io/no-provisioner Delete WaitForFirstConsumer false 17d
设置local-hostpath为默认存储
[root@k8s-master openebs]# kubectl patch storageclass local-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
storageclass.storage.k8s.io/local-hostpath patched
[root@k8s-master openebs]# kubectl describe sc/local-hostpath
Name: local-hostpath
IsDefaultClass: Yes
Annotations: cas.openebs.io/config=- name: StorageType
value: hostpath
- name: BasePath
value: /home/openebs/local
,kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{"cas.openebs.io/config":"- name: StorageType\n value: hostpath\n- name: BasePath\n value: /home/openebs/local\n","openebs.io/cas-type":"local"},"name":"local-hostpath"},"provisioner":"openebs.io/local","reclaimPolicy":"Delete","volumeBindingMode":"WaitForFirstConsumer"}
,openebs.io/cas-type=local,storageclass.kubernetes.io/is-default-class=true
Provisioner: openebs.io/local
Parameters: <none>
AllowVolumeExpansion: <unset>
MountOptions: <none>
ReclaimPolicy: Delete
VolumeBindingMode: WaitForFirstConsumer
Events: <none>创建测试实例验证
[root@k8s-master openebs]# cat local-sc-pod.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: local-hostpath-pvc
spec:
storageClassName: local-hostpath
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5G
---
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








