OpenEBS Jiva 复制卷部署笔记
OpenEBS 管理每个 Kubernetes 节点上可用的存储,并使用该存储为有状态工作负载提供本地或分布式(也称为复制)持久卷。
如果是本地卷:
- OpenEBS 可以使用原始块设备或分区,或使用主机路径上的子目录,或使用 LVM、ZFS 或稀疏文件来创建持久卷。
- 本地卷直接安装到 Stateful Pod 中,数据路径中没有来自 OpenEBS 的任何额外开销,从而减少了延迟。
- OpenEBS 为本地卷提供了额外的工具,用于监控、备份/恢复、灾难恢复、ZFS 或 LVM 支持的快照、基于容量的调度等。
在分布式(又名复制)卷的情况下:
- OpenEBS 使用其引擎之一(Mayastor、cStor 或 Jiva)为每个分布式持久卷创建微服务。
- Stateful Pod 将数据写入 OpenEBS 引擎,这些引擎将数据同步复制到集群中的多个节点。OpenEBS 引擎本身部署为 pod,由 Kubernetes 编排。当运行有状态 pod 的节点发生故障时,该 pod 将被重新调度到集群中的另一个节点,OpenEBS 使用其他节点上的可用数据副本提供对数据的访问。
- Stateful Pod 使用 iSCSI(cStor 和 Jiva)或 NVMeoF(Mayastor)连接到 OpenEBS 分布式持久卷。
- OpenEBS cStor 和 Jiva 专注于存储的易用性和耐用性。这些引擎分别使用定制版本的 ZFS 和 Longhorn 技术将数据写入存储。
- OpenEBS Mayastor 是最新的引擎,以耐用性和性能为设计目标而开发;OpenEBS Mayastor 有效地管理计算(hugepages、内核)和存储(NVMe 驱动器)以提供快速的分布式块存储。
OpenEBS 贡献者更喜欢将分布式块存储卷称为复制卷,以避免与传统的分布式块存储混淆,原因如下:
- 分布式块存储倾向于将卷的数据块分片到集群中的多个节点上。复制卷将卷的所有数据块保存在节点上,并且为了持久性将整个数据复制到集群中的其他节点。
- 在访问卷数据时,分布式块存储依赖于元数据哈希算法来定位块所在的节点,而复制卷可以从任何持久保存数据的节点(也称为副本节点)访问数据。
- 与传统的分布式块存储相比,复制卷的爆炸半径更小。
- 复制卷专为云原生有状态工作负载而设计,这些工作负载需要大量容量的卷,这些容量通常可以从单个节点提供服务,而不是数据在集群中的多个节点之间分片的单个大卷。
- 复制卷是将其数据同步复制到多个节点的卷。复制卷可以承受节点故障。还可以跨可用性区域设置复制,帮助应用程序跨可用性区域移动。
以上内容机器翻译自官方文档
对于我的需求来说,一个 OpenEBS 复制卷能够将数据同时储存至多个节点、满足了高可用需求。
复制卷可以从任何持久保存数据的节点访问数据,满足了同步需求。
然后由 OpenEBS 提供储存类给容器使用。
(发现 Longhorn 也不错,跑去用 Longhorn 了)
储存引擎
OpenEBS 有三种储存引擎,不同的引擎能提供不同的功能。
超链接内有详细介绍。
除了这三种引擎,还有 Local PV,不太算存储引擎。
Local PV 意味着存储只能从单个节点使用。Local PV 表示已挂载的本地存储设备,例如磁盘、分区或目录。
以下表格部分摘自 https://zhuanlan.zhihu.com/p/519172233
特性 | Jiva | cStor | Local PV | Mayastor |
轻量级运行于用户空间 | 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 |
应用需求 | 存储类型 | OpenEBS 卷类型 |
低时延、高可用性、同步复制、快照、克隆、精简配置 | 未格式化的块设备 (SSD/HDD/云硬盘) |
OpenEBS Mayastor |
高可用性、同步复制、快照、克隆、精简配置 | 未格式化的块设备 (SSD/HDD/云硬盘) |
OpenEBS cStor |
高可用性、同步复制、精简配置 | 主机路径或外部挂载存储 | OpenEBS Jiva |
低时延、本地 PV | 主机路径或外部挂载存储 | Dynamic Local PV - Hostpath, Dynamic Local PV - Rawfile |
低时延、本地 PV | 未格式化的块设备 (SSD/HDD/云硬盘) |
Dynamic Local PV - Device |
低延迟,本地 PV,快照,克隆 | 未格式化的块设备 (SSD/HDD/云硬盘) |
OpenEBS Dynamic Local PV - ZFS , OpenEBS Dynamic Local PV - LVM |
对于我的需求来说,Jiva 可以直接使用主机上的已有路径,而其他两个则需要使用空的块设备。
我不需要非常高性能的储存,添加新硬盘也不是想就能有的,所以选择 Jiva 是不错的选择。
先决条件
- Kubernetes 1.18 或更高版本;
- 所有工作节点安装并运行 iscsi-initiator-utils 或 open-iscsi;
- 有权将 RBAC 组件安装到 kube-system 命名空间中;
- OpenEBS localpv-hostpath 2.6.0 或更高版本;
安装 iSCSI initiator utils
RHEL/CentOS 系列
在所有工作节点执行:
sudo yum install iscsi-initiator-utils
sudo systemctl enable --now iscsid
modprobe iscsi_tcp
echo iscsi_tcp >/etc/modules-load.d/iscsi-tcp.conf
通过 Helm 安装
添加源:
helm repo add openebs https://openebs.github.io/charts
helm repo update
如果你访问 github 困难,可以试试 https://github.com/ineo6/hosts
官方文档不太对,不建议使用默认值安装。
使用 CSI 驱动程序安装 Jiva:
helm install openebs openebs/openebs --namespace openebs --create-namespace \
--set legacy.enabled=false \
--set jiva.enabled=true \
--set openebs-ndm.enabled=true \
--set localpv-provisioner.enabled=true \
--set jiva.defaultStoragePath=/var/openebs \
--set image.repository=k8s-gcr.m.daocloud.io
legacy.enabled=false
禁用旧的 out-of-tree 树外组件;jiva.enabled=true
启用 Jiva;openebs-ndm.enabled=true
启用 ndm;localpv-provisioner.enabled=true
启用Local PV provisioner;jiva.defaultStoragePath=<储存路径>
自定义 Jiva 储存目录,默认 /var/openebs;image.repository=<源地址>
自定义源地址,默认为 k8s.gcr.io,此处设置为 Daocloud 镜像;
此命令会在 openebs 命名空间内安装 OpenEBS Jiva 和 Local PV 组件。
更多信息请参阅 https://github.com/openebs/charts/tree/master/charts/openebs
验证 OpenEBS 安装
验证 pod
使用 kubectl get pods -n openebs -o wide
你应该能看到有以下几种 pod 正在全数正常运行。
openebs-jiva-csi-controller-0
openebs-jiva-csi-node
openebs-jiva-operator
openebs-localpv-provisioner
openebs-ndm-operator
openebs-ndm
如果一直 ContainerCreating,大概率是镜像问题。
安装时别忘了设置镜像,默认的 k8s.gcr.io 大陆无法访问。
验证储存类
使用 kubectl get sc
你应该能看到一下几种 StorageClasses
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
openebs-device openebs.io/local Delete WaitForFirstConsumer false 5m15s
openebs-hostpath openebs.io/local Delete WaitForFirstConsumer false 5m15s
openebs-jiva-csi-default jiva.csi.openebs.io Delete Immediate true 5m15s
openebs-jiva-csi-default
用于配置 jiva 卷,此类默认就会复制;openebs-hostpath
用于在主机路径上配置本地 PV,不会复制;openebs-device
用于在设备上配置本地 PV,不会复制;
至此就已安装完毕了,然后你就可以创建 PVC 什么的了。
更多信息请参考 https://openebs.io/blog/provisioning-openebs-jiva-volumes-via-csi
简单测试
创建一个 PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: example-jiva-csi-pvc
spec:
storageClassName: openebs-jiva-csi-default
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
在储存类 openebs-jiva-csi-default 内创建一个 4GiB 的 PVC。
保存到 <文件名>.yaml 中,然后 kubectl apply -f <文件名>.yaml
即可。
然后 kubectl get pvc
应该就能看见此 PVC。
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
example-jiva-csi-pvc Bound pvc-2d9ae46f-c38f-4aef-af33-e82eec7af2b5 4Gi RWO openebs-jiva-csi-default 10s
再查看一下状态:kubectl get jivavolume pvc-2d9ae46f-c38f-4aef-af33-e82eec7af2b5 -n openebs
然后就可以用这个 PVC 了。
更多信息请参阅:https://openebs.io/blog/provisioning-openebs-jiva-volumes-via-csi
卷策略
如果你不想用默认的卷复制策略,或是需要调整资源限制、容忍读、节点选择器等,你可以创建 JivaVolumePolicy(JVP)。
例如:
apiVersion: openebs.io/v1alpha1
kind: JivaVolumePolicy
metadata:
name: example-jivavolumepolicy
namespace: openebs
spec:
replicaSC: openebs-hostpath
target:
# This sets the number of replicas for high-availability
# replication factor <= no. of (CSI) nodes
replicationFactor: 3
# disableMonitor: false
# auxResources:
# tolerations:
# resources:
# affinity:
# nodeSelector:
# priorityClassName:
# replica:
# tolerations:
# resources:
# affinity:
# nodeSelector:
# priorityClassName:
然后使用 JVP 创建新的储存类:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: openebs-jiva-csi-sc
provisioner: jiva.csi.openebs.io
allowVolumeExpansion: true
parameters:
cas-type: "jiva"
policy: "example-jivavolumepolicy"
更多信息请参阅:https://github.com/openebs/jiva-operator/blob/master/docs/tutorials/policies.md
小知识
什么是 In-Tree 树内、Out-Of-Tree 树外、CSI (Container Storage Interface) 容器存储接口
早期 Kubernetes 处理问题比较粗暴,有什么需求就直接写死在里面,比如 Ceph 接口。这叫就做 In-Tree 树内。
时间一长各种各样的接口想要加进来,这么耦合肯定是不行的。
于是另一种方案就来了,就是做成外置插件 external provisioner,这叫就做 Out-Of-Tree 树外。
但这只是个 provisioner 能实现的功能有限。
最后解决方案当然就是制定一个标准规范,大家自己按照规范做个插件即可,这个规范就叫做 CSI (Container Storage Interface) 容器存储接口。
OpenEBS 和 Longhorn 是什么关系
OpenEBS 最初是作为 Longhorn Engine 的一个分支开始的。
然而,OpenEBS Jiva 和 Longhorn 在以下方面存在一些分歧,于是就独立出来了。
- Control Plane functionality
- iSCSI Target implementation
- Quorum
- Backup / Restore
- UI
你可以在这找到旧的仓库 https://github.com/openebs/longhorn
No Comments