Kubernetes云原生存储解决方案之 Rook Ceph实践探究
除了手动部署独立的 Ceph 集群并配置与Kubernetes进行对接外,Rook Ceph 支持直接在 Kubernetes 集群上部署 Ceph 集群。
通过Rook Ceph云原生存储编排平台,使得 Kubernetes 集群中启用高可用的 Ceph 存储,为 Kubernetes 应用程序提供块存储、对象存储和文件存储服务。
Rook高可用架构:
1. 准备工作
1.1 前提
1. Kubernetes版本
Rook 可以安装在任何现有的 Kubernetes 集群上,只要它满足最低版本,并且授予 Rook 所需的权限。早期 v1.9.7
版本的 Rook 支持 Kubernetes v1.17
或更高版本;现在的 v1.15
版本支持 Kubernetes v1.25
到 v1.30
版本。
2. CPU 架构
支持的架构:amd64 / x86_64
, arm64
.
3. Ceph 部署前提
要配置 Ceph 存储集群,需要至少一种以下类型的本地存储:
- 原始设备(没有分区或格式化的文件系统)
- 原始分区(没有格式化的文件系统)
- LVM 逻辑卷(没有格式化的文件系统)
- 从
block
模式的存储类中提供的持久卷
使用以下命令确认分区或设备是否已格式化文件系统:
root@k8s-1:~# lsblk -f
NAME FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT
vda
├─vda1
└─vda2 ext4 2ec0411c-1071-4316-bed7-6f0afdf54814 22G 39% /
vdb
vdc
如果 FSTYPE 字段不为空,则表示对应的设备上有文件系统。在此示例中,vdb 、vdc对 Rook 可用,而 vda 及其分区已有文件系统,不可用。
如果需要清理已有磁盘给 Ceph 使用,请使用下面的命令(生产环境请谨慎):
# yum install gdisk
sgdisk --zap-all /dev/sdd
4. LVM需求
在以下情况下,Ceph OSD 依赖于 LVM:
- 如果启用了加密(集群 CR 中的
encryptedDevice: "true"
) - 指定了
metadata
设备 osdsPerDevice
大于 1
在以下情况下,OSD 不需要 LVM:
- OSD 是在原始设备或分区上创建的
- OSD 是在使用
storageClassDeviceSets
的 PVC 上创建的
如果需要 LVM,则需要在将运行 OSD 的主机上提供 LVM。一些 Linux 发行版不自带 lvm2
包。这个包在 Kubernetes 集群的所有存储节点上都是必需的,以便运行 Ceph OSD。没有这个包,即使 Rook 能够成功创建 Ceph OSD,当节点重新启动时,运行在重新启动节点上的 OSD Pod 将 无法启动。请使用 Linux 发行版的包管理器安装 LVM。例如:
CentOS:
sudo yum install -y lvm2
Ubuntu:
sudo apt-get install -y lvm2
5. 内核需求
RBD
Ceph 需要一个构建了 RBD 模块的 Linux 内核,许多较新的 Linux 发行版都包含这个模块,但并非所有。通过运行 modprobe rbd
来测试你的 Kubernetes 节点。如果找不到 rbd 模块,则需要重新构建内核以包含 rbd 模块,安装更新的内核,或者选择不同的 Linux 发行版。
在用于存储节点的机器通过如下命令加载 rbd 模块:
# 加载 rbd 和 nbd 模块
]# modprobe rbd
]# modprobe nbd
# 开机自动加载 rbd 和 nbd 模式
]# echo "rbd" >> /etc/modules-load.d/rook-ceph.conf
]# echo "nbd" >> /etc/modules-load.d/rook-ceph.conf
# 查看rbd模块
]# lsmod | grep rbd
# 正确的输出结果类似如下:
]# lsmod | grep rbd
rbd 106496 0
libceph 327680 1 rbd
Rook 的默认 RBD 配置仅指定了分层功能,以便与较旧的内核广泛兼容。如果你的 Kubernetes 节点运行的是 5.4 或更高版本的内核,可以在存储类中启用其他功能标志。fast-diff
和 object-map
功能尤其有用。
imageFeatures: layering,fast-diff,object-map,deep-flatten,exclusive-lock
CephFS
如果从 Ceph 共享文件系统(CephFS)创建 RWX 卷,推荐的最低内核版本是 4.17。如果内核版本低于 4.17,请求的 PVC 大小将不会被强制执行。存储配额仅在更新的内核上得到强制执行。
1.2 部署环境准备
主机名 | IP | OS | CPU | 内存 | 系统盘 | 数据盘 | 用途 |
---|---|---|---|---|---|---|---|
k8s-1 | 192.168.1.55 | ubuntu 20.04.2 5.4.0-81-generic | 4 | 8 | 40 | KubeSphere/k8s-control-plane | |
k8s-2 | 192.168.1.56 | ubuntu 20.04.2 5.4.0-81-generic | 4 | 8 | 40 | KubeSphere/k8s-control-plane | |
k8s-3 | 192.168.1.57 | ubuntu 20.04.2 5.4.0-81-generic | 4 | 8 | 40 | KubeSphere/k8s-control-plane | |
k8s-4 | 192.168.1.58 | ubuntu 20.04.2 5.4.0-81-generic | 4 | 8 | 40 | 50Gx2 | k8s-worker/Ceph |
k8s-5 | 192.168.1.59 | ubuntu 20.04.2 5.4.0-81-generic | 4 | 8 | 40 | 50Gx2 | k8s-worker/Ceph |
k8s-6 | 192.168.1.60 | ubuntu 20.04.2 5.4.0-81-generic | 4 | 8 | 40 | 50Gx2 | k8s-worker/Ceph |
说明
本文的master节点取消NoSchedule的taint以便用于部署测试应用,正式环境建议部署单独的worker节点承载业务应用。
测试境涉及的软件版本信息如下:
- 操作系统:ubuntu 20.04.2 x86_64
- 内核:5.4.0-81-generic
- Kubernetes:v1.27.4
- Containerd:1.6.4
- Rook:v1.15.2
- Ceph: 18.2.4 reef (stable)
1.3 Rook 部署规划
为了更好地满足生产环境的实际需求,在规划和部署存储基础设施时增加了以下策略:
- 节点扩展:向 Kubernetes 集群中新增三个专用节点,这些节点将专门承载 Ceph 存储服务,确保存储操作的高效性和稳定性。
- 组件隔离:所有 Rook 和 Ceph 组件以及数据卷将被部署在这些专属节点上,实现组件的清晰隔离和专业化管理。
- 节点标签化:为每个存储节点设置了专门的标签,例如
role=storage-node
,以便 Kubernetes 能够智能地调度相关ceph相关管理组件。非存储节点设置标签,例如role=rook-ceph
,用于承载 Ceph CSI 插件,使得运行在这些节点上的业务 Pod 能够利用 Ceph 提供的持久化存储。 - 存储介质配置:在每个存储节点上增加2块 500G 的 Ceph 专用数据盘
/dev/vdb
和/dev/vdc
。为保证最佳性能,该磁盘将采用裸设备形态直接供 Ceph OSD 使用,无需进行分区或格式化。
重要提示:
- 本文提供的配置和部署经验对于理解 Rook-Ceph 的安装和运行机制具有参考价值。强烈建议不要将本文描述的配置直接应用于任何形式的生产环境。
- 在生产环境中,还需进一步考虑使用 SSD、NVMe 磁盘等高性能存储介质;细致规划故障域;制定详尽的存储节点策略;以及进行细致的系统优化配置等。
2. 节点规划
将集群中的三台master节点用作存储节点,下面设置节点标签:
# 管理节点标签,用于安装ceph CSI插件
kubectl label nodes k8s-1 role=rook-ceph
kubectl label nodes k8s-2 role=rook-ceph
kubectl label nodes k8s-3 role=rook-ceph
# 查看label
root@k8s-1:~/rook-ceph/rook-1.15.2/deploy/examples# kubectl get node k8s-3 --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-3 Ready control-plane 22h v1.27.4 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-3,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=,role=rook-ceph
# worker节点标签,用于安装存储节点,ceph管理组件也安装到上面
kubectl label nodes k8s-4 role=storage-node
kubectl label nodes k8s-5 role=storage-node
kubectl label nodes k8s-6 role=storage-node
# 查看label
root@k8s-1:~/rook-ceph/rook-1.15.2/deploy/examples# kubectl get node k8s-6 --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-6 Ready <none> 22h v1.27.4 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-6,kubernetes.io/os=linux,role=storage-node
说明:
测试环境也可以将ceph管理组件部署到k8s控制节点,生产环境中建议专门规划三个存储性能好的节点用于安装部署ceph集群。 CSI 插件仅部署到需要存储功能的业务节点上。
3. 安装配置 Rook Ceph Operator
下面通过Rook Ceph Operator
进行rook ceph的部署测试。
3.1 下载部署代码
这里选用截止本文测试时最新的v1.15.2版本。
mkdir rook-ceph; cd rook-ceph
wget https://github.com/rook/rook/archive/refs/tags/v1.15.2.tar.gz
tar xvf v1.15.2.tar.gz
cd rook-1.15.2/deploy/examples/
3.2 修改镜像地址(可选配置)
如果访问dockerhub、quay.io和registry.k8s.io镜像仓库受限,可以将 Rook-Ceph 需要的镜像离线下载后导入到本地仓库,部署时修改镜像地址。
# 备份源文件operator.yaml
root@k8s-1:~/rook-ceph/rook-1.15.2/deploy/examples# cp operator.yaml operator.yaml.bak
# 查看默认的镜像地址
root@k8s-1:~/rook-ceph/rook-1.15.2/deploy/examples# grep -n "docker.io\|quay.io\|registry.k8s.io" operator.yaml
130: # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.12.2" # 这里注意版本号带v,否则拉去不到镜像
131: # ROOK_CSI_REGISTRAR_IMAGE: "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1"
132: # ROOK_CSI_RESIZER_IMAGE: "registry.k8s.io/sig-storage/csi-resizer:v1.11.1"
133: # ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v5.0.1"
134: # ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.k8s.io/sig-storage/csi-snapshotter:v8.0.1"
135: # ROOK_CSI_ATTACHER_IMAGE: "registry.k8s.io/sig-storage/csi-attacher:v4.6.1"
513: # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.9.1"
607: image: docker.io/rook/ceph:v1.15.2
# 取消镜像注释,并替换镜像地址前缀。根据上述查到的行号进行替换。
sed -i '130,135s/^.*#/ /g' operator.yaml
sed -i '513,513s/^.*#/ /g' operator.yaml
# 替换镜像仓库
sed -i 's#registry.k8s.io#10.210.10.210#g' operator.yaml
sed -i 's#quay.io#10.210.10.210#g' operator.yaml
sed -i 's#docker.io#10.210.10.210#g' operator.yaml
# 查看替换后的镜像地址
root@k8s-1:~/rook-ceph/rook-1.15.2/deploy/examples# grep -n "10.210.10.210" operator.yaml
130: ROOK_CSI_CEPH_IMAGE: "10.210.10.210/cephcsi/cephcsi:v3.12.2"
131: ROOK_CSI_REGISTRAR_IMAGE: "10.210.10.210/sig-storage/csi-node-driver-registrar:v2.11.1"
132: ROOK_CSI_RESIZER_IMAGE: "10.210.10.210/sig-storage/csi-resizer:v1.11.1"
133: ROOK_CSI_PROVISIONER_IMAGE: "10.210.10.210/sig-storage/csi-provisioner:v5.0.1"
134: ROOK_CSI_SNAPSHOTTER_IMAGE: "10.210.10.210/sig-storage/csi-snapshotter:v8.0.1"
135: ROOK_CSI_ATTACHER_IMAGE: "10.210.10.210/sig-storage/csi-attacher:v4.6.1"
513: ROOK_CSIADDONS_IMAGE: "10.210.10.210/csiaddons/k8s-sidecar:v0.9.1"
607: image: 10.210.10.210/rook/ceph:v1.15.2
说明:
上述10.210.10.210为本地的harbor镜像仓库地址,确保本地对应项目下存在对应组件版本的镜像。本次使用到的容器镜像列表如下:
quay.io/cephcsi/cephcsi:v3.12.2 registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1 registry.k8s.io/sig-storage/csi-resizer:v1.11.1 registry.k8s.io/sig-storage/csi-provisioner:v5.0.1 registry.k8s.io/sig-storage/csi-snapshotter:v8.0.1 registry.k8s.io/sig-storage/csi-attacher:v4.6.1 quay.io/csiaddons/k8s-sidecar:v0.9.1 docker.io/rook/ceph:v1.15.2 quay.io/ceph/ceph:v18.2.4
可以提前下载上述镜像并重新打tag推送到内部的镜像仓库。
3.3 修改自定义配置
修改配置文件 operator.yaml
,修改下面亲和性相关配置,和上述的label对应:
# rook-ceph 所有管理组件部署在指定标签节点
CSI_PROVISIONER_NODE_AFFINITY: "role=storage-node"
# k8s 其他节点安装 Ceph CSI Plugin
CSI_PLUGIN_NODE_AFFINITY: "role=rook-ceph"
3.4 部署 Rook Operator
# 部署 Rook operator
kubectl create -f crds.yaml -f common.yaml -f operator.yaml
# 查看rook-ceph-operator容器状态
kubectl -n rook-ceph get pod -o wide
root@k8s-1:~/rook-ceph/rook-1.15.2/deploy/examples# kubectl -n rook-ceph get pod -o wide
rook-ceph-operator-b86bf6d58-t24kr 1/1 Running 0 31m 172.25.173.11 k8s-5 <none> <none>
4. 创建 Ceph 集群
4.1 修改集群配置文件
修改集群配置文件 cluster.yaml
,增加节点亲和配置,取消下面位置的注释,并配置key和vlaues部分的值。
placement:
all:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: role
operator: In
values:
- storage-node
修改集群配置文件 cluster.yaml
,增加存储节点和 OSD 磁盘配置。
storage: # cluster level storage configuration and selection
useAllNodes: false # 生产环境&#