**摘要:**本文系统梳理存储技术体系,从传统三大存储 DAS、NAS、SAN 讲起,再到分布式存储与 Ceph 统一存储架构,深入解析 CRUSH 算法与核心组件,并给出基于 cephadm 的完整部署实战,以及 Kubernetes 对接 CephFS 与 RBD 的整合项目,帮助读者建立从理论到实践的完整存储知识框架。
一、传统三大存储 DAS / NAS / SAN
在进入分布式存储之前,先理解传统三大存储形态:DAS、NAS、SAN。它们分别代表直连、文件共享和块设备三种不同的数据访问方式,是理解后续 Ceph 架构的基础。
1. DAS 直连存储
磁盘 / 磁盘柜通过 SAS、SCSI、SATA、USB 直连服务器主板总线,不走网络。
- **优点:**读写速度快
- **缺点:**资源独占,多主机无法共享;扩容困难;数据孤岛;备份容灾麻烦,硬件利用率低
2. NAS 网络附加存储【文件存储】
协议:NFS、CIFS、FTP;通过以太网,对外提供文件 / 目录。
- **优点:**多主机共享文件,部署简单
- **缺点:**网络容易成为 IO 瓶颈;高并发性能弱;不能给数据库裸设备使用;海量文件元数据性能下降
3. SAN 存储区域网络【块存储】
底层 SCSI 协议:
- **FC-SAN:**光纤网络,HBA 卡 + 光纤交换机
- **iSCSI:**以太网承载 SCSI
对外输出裸块设备,客户端需要自行格式化文件系统。
- **优点:**块设备性能好
- **缺点:**FC 硬件成本昂贵;裸块多机同时读写会锁冲突;只能分配 LUN,不能直接共享文件夹;存储网络维护复杂
**对比小结:**DAS:本地直连;NAS:网络文件;SAN:网络裸块。
二、分布式存储
传统存储受限于单机扩展能力,分布式存储应运而生。它把多台服务器的磁盘资源通过网络整合,形成统一大容量存储池,是云原生和超大规模数据场景下的主流方案。
多台服务器磁盘资源通过网络整合,形成统一大容量存储池。数据分片打散存到不同节点,依靠副本实现故障容错,突破单机容量、性能上限。
分布式存储三类
- **文件存储:**POSIX 标准,挂载目录使用;代表:HDFS、CephFS、GlusterFS;场景:大数据、AI、多主机共享文件
- **块存储:**输出裸磁盘;代表:Ceph-RBD;场景:云主机、数据库、虚拟机磁盘
- **对象存储:**对象 = 数据本体 + 元数据 + 全局唯一 ID;扁平化无目录树,REST/S3 API 访问;代表:MinIO、Ceph-RGW、阿里云 OSS;场景:图片、视频、备份海量非结构化数据
三、Ceph 统一分布式存储
Ceph 是目前最流行的开源统一分布式存储之一,其核心设计理念是:用一套底层 RADOS 集群,同时向上提供对象、块、文件三种存储服务,避免为不同存储类型分别搭建独立系统。
开源统一存储,一套底层 RADOS 集群同时提供对象、块、文件三种存储服务。
- **底层 RADOS:**可靠自动化分布式对象存储集群,所有数据以对象(默认 4MB)存储。
- **librados:**RADOS 底层 SDK,多语言开发调用。
上层封装:
- **RGW (RadosGW):**对象存储,S3 兼容 REST 接口
- **RBD:**块存储,模拟裸块设备,K8s 可以对接做 PVC
- **CephFS (CFS):**文件存储,需要 MDS 元数据服务
寻址核心:CRUSH 算法,客户端本地实时计算对象存放位置,无中心化元数据查表,实现高扩展。
核心逻辑链路
文件 → 切分成对象 → 映射 PG → CRUSH 算法算出 OSD → 写入磁盘,副本同步到其他 OSD。
Pool & PG & OSD
- **Pool 存储池:**逻辑隔离分区,存放对象,可设置副本数、纠删码。
- PG 放置组: Pool 内逻辑分组;对象先映射 PG,PG 再映射 OSD;PG 是数据复制、迁移、恢复最小单元。PG 数量需要根据集群规模公式计算。
- **OSD:**一块磁盘对应一个 OSD 进程;真正保存业务数据;负责 IO 读写、副本复制、故障恢复、互相心跳上报状态给 Monitor。
四、Ceph 集群核心组件
一个可用的 Ceph 集群由若干守护进程协作完成。理解每个组件的职责,是后续部署、排障和调优的前提。下面逐一介绍 Monitor、MGR、OSD 和 MDS 四个核心组件。
集群最低要求:Monitor + MGR + OSD;使用 CephFS 额外需要 MDS。
1. Monitor (mon) 监视器【奇数:3/5 台】
- 保存集群元数据:Cluster Map(OSD、PG、CRUSH 规则、认证密钥)
- 使用 Paxos 协议保证元数据强一致
- 客户端首先连接 MON 获取集群地图;鉴权;监控各组件状态;不存业务数据
2. MGR (manager) 管理守护进程【一主一备 active/standby】
- 减轻 MON 压力,后台管理任务
- 指标采集、告警、Dashboard 面板、Prometheus 监控、ceph-orch (cephadm 编排)
- 没有 MGR,cephadm 编排、web 面板不可用
3. OSD 对象存储守护进程
真正存业务数据;磁盘对应 OSD;处理 PG、副本、重平衡、故障恢复;OSD 之间互相心跳检测故障。
4. MDS 元数据服务器
只给 CephFS 文件系统使用,维护文件目录元数据;RBD、RGW 不需要 MDS。
五、CRUSH 算法
CRUSH 是 Ceph 实现无中心化数据寻址的关键算法。它让客户端在本地即可计算出数据存放位置,从而避免传统存储中集中式元数据服务器的性能瓶颈,是 Ceph 高扩展性的核心保障。
全称:Controlled Replication Under Scalable Hashing 可控可复制可伸缩一致性哈希。
**核心:**客户端本地计算数据存放位置,不需要中央元数据查询表,消除中心化瓶颈。
映射两步:
- 对象名称哈希计算映射到 PG
- CRUSH 算法把 PG 映射到一组 OSD(主 OSD + 副本 OSD)
优势:
- 无中心网关,客户端直连 OSD 读写
- 节点增减、故障自动重新计算分布
- 支持故障域隔离(机架、主机),控制副本物理位置
**为什么不直接对象映射 OSD:**OSD 故障增减,会造成大量数据迁移,耦合度太高;增加 PG 做中间缓冲层。
六.部署cephadm(Ceph 官方原生集群部署 & 生命周期编排工具)
实验前提需要有k8s集群以及harbor仓库,参考前面的文章
指定下载版本
root@ceph-node1 \~# export CEPH_RELEASE=19.2.6
解释: 设置环境变量 CEPH_RELEASE 为 19.2.6,用于后续下载对应版本的 cephadm 安装包。
配置本地解析
root@ceph-node1 \~# cat > /etc/hosts << EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.200 ceph-node1
172.25.254.250 reg.timinglee.org
EOF
解释: 在 /etc/hosts 文件中添加主机名解析记录,将 ceph-node1 映射到本机 IP,将 reg.timinglee.org 映射到 Harbor 仓库地址,确保集群节点之间可以通过主机名互相访问。
安装docker环境
root@ceph \~# dnf remove podman -y
root@ceph-node1 \~# cat >> /etc/yum.repos.d/docker.repo <<EOF
docker-ce
name = docker ce
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9.6/x86_64/stable
gpgcheck = 0
EOF
root@ceph \~# echo br_netfilter > /etc/modules-load.d/docekr.conf
root@ceph \~# systemctl restart systemd-modules-load.service
root@ceph \~# cat >> /etc/sysctl.d/docker.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
root@storage-node1 \~# sysctl --system
root@ceph-node1 \~# dnf install docker-ce -y
root@ceph-node1 \~# systemctl enable --now docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/syste m/docker.service.
解释: 先卸载系统自带的 podman 容器工具,然后配置阿里云 Docker 镜像源,加载 br_netfilter 内核模块并设置网络转发参数,最后安装 Docker CE 并设置为开机自启。cephadm 依赖容器运行 Ceph 组件,因此必须先准备好 Docker 环境。
下载对应版本的cephadm
root@ceph-node1 \~# curl --silent --remote-name --location https://download.ceph.com/rpm-${CEPH_RELEASE}/el9/noarch/cephadm
root@ceph-node1 \~# ls
anaconda-ks.cfg cephadm
root@ceph-node1 \~# mv cephadm /usr/local/bin/
这里我是直接导入的安装包
解释: 使用 curl 从 Ceph 官方源下载对应版本的 cephadm 工具,将其移动到 /usr/local/bin/ 目录以便全局调用。cephadm 是 Ceph 集群部署和生命周期管理的核心命令行工具。
cephadm初始化
cephadm --image quay.io/ceph/ceph:v19.2.2 bootstrap \ --mon-ip 172.25.254.200 \ --log-to-file \ --single-host-defaults \ --allow-fqdn-hostname \ --initial-dashboard-user admin \ --initial-dashboard-password lee \ --allow-overwriteroot@ceph-node1 \~# cephadm --image quay.io/ceph/ceph:v19.2.2 bootstrap \
--mon-ip 172.25.254.200 \ #指定第一个 Monitor 守护进程绑定的 IP 地址
#单节点集群就填本机内网 IP;多节点填当前部署节点 IP。
--log-to-file \ #将 cephadm 引导过程日志输出到本地文件,日志默认路径:
#/var/log/ceph/cephadm.log
--single-host-defaults \ #单主机集群专用参数,为单节点环境自动调整集群默认配置
--allow-fqdn-hostname \ #允许主机使用完整 FQDN 长主机名(带域名,如 `ceph01.xxx.local`)
#如果你的机器 hostname 是 fqdn,不加该参数 bootstrap 会直接报错终止
--initial-dashboard-user "admin" \ #初始化 Ceph Dashboard Web UI 的管理员用户名
--initial-dashboard-password "lee" \ #Dashboard 管理员初始密码
--allow-overwrite #允许覆盖已有集群残留数据。
初始化成功后·可以访问web界面
解释: 执行 cephadm bootstrap 命令初始化 Ceph 集群。该命令会拉取 Ceph 镜像并启动第一个 Monitor 和 MGR 守护进程,同时配置 Dashboard Web 管理界面。各参数含义:--mon-ip 指定 Monitor 绑定 IP;--single-host-defaults 适配单节点环境;--allow-fqdn-hostname 允许使用 FQDN 主机名;--initial-dashboard-user/password 设置 Web 界面管理员账号;--allow-overwrite 允许覆盖残留数据。初始化成功后可通过浏览器访问 Dashboard。
安装ceph相关软件
配置ceph源
在安装客户端版本时一定要注意先用cephadm shell 确定集群内使用的ceph 版本然后再确定装什么版本的ceph-common
root@ceph-node1 ceph-v19.2.2# systemctl disable --now firewalld
Removed "/etc/systemd/system/multi-user.target.wants/firewalld.service".
Removed "/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service".
root@ceph-node1 ceph-v19.2.2# docker tag quay.io/ceph/ceph:v19.2.2 quay.io/ceph/ceph:v19
root@ceph-node1 ceph-v19.2.2# cephadm shell -- ceph --version
Inferring fsid c9ef1cb6-a544-11f1-b219-000c29c71969
Inferring config /var/lib/ceph/c9ef1cb6-a544-11f1-b219-000c29c71969/mon.ceph-node1/config
Not using image 'sha256:8214ebff6133ac27d20659038df6962dbf9d77da21c9438a296b2e2059a56af6' as it's not in list of non-dangling images with ceph=True label
ceph version 19.2.2 (0eceb0defba60152a8182f7bd87d164b639885b8) squid (stable)
root@ceph-node1 ceph-v19.2.2#
这里我们是19.2.2版本,那么在安装ceph-common的时候一定要用19.2.2版本
root@ceph-node1 \~# cat > /etc/yum.repos.d/ceph.repo << EOF
ceph
name = ceph
baseurl = https://mirrors.aliyun.com/ceph/rpm-19.2.2/el9/x86_64/
gpgcheck = 0
EOF
解释: 先关闭防火墙避免干扰集群通信,然后通过 cephadm shell -- ceph --version 确认集群实际使用的 Ceph 版本为 19.2.2。接着配置阿里云 Ceph 软件源,注意安装 ceph-common 客户端时必须与集群版本保持一致(19.2.2),否则会出现版本不兼容问题。
安装ceph相关软件
root@ceph-node1 ceph-v19.2.2# dnf install ceph-common -y
正在更新 Subscription Management 软件仓库。
无法读取客户身份
本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。
解释: 使用 dnf 安装 ceph-common 客户端软件包,该包提供 ceph、rbd 等命令行工具,用于在宿主机上直接管理 Ceph 集群。输出中的注册警告不影响安装,可忽略。
测试安装成功与否
root@ceph-node1 ceph-v19.2.2# ceph -s
cluster:
id: c9ef1cb6-a544-11f1-b219-000c29c71969
health: HEALTH_WARN
OSD count 0 < osd_pool_default_size 2
services:
mon: 1 daemons, quorum ceph-node1 (age 14m)
mgr: ceph-node1.pkotix(active, since 10m), standbys: ceph-node1.mhkgzj
osd: 0 osds: 0 up, 0 in
data:
pools: 0 pools, 0 pgs
objects: 0 objects, 0 B
usage: 0 B used, 0 B / 0 B avail
pgs:
解释: 执行 ceph -s 查看集群状态。此时集群健康状态为 HEALTH_WARN,原因是 OSD 数量为 0(尚未添加存储磁盘),Monitor 和 MGR 已正常运行。这是初始化后的正常现象,后续添加 OSD 后集群会转为 HEALTH_OK。
集群初始化如果出现问题:
root@ceph images# docker ps -a | awk 'NR>1{system("docker rm -f " $1)}'
root@ceph images# rm -rf /etc/ceph/*
root@ceph images# rm -rf /var/lib/ceph/*
root@ceph images# rm -rf /var/log/ceph/*
root@ceph images# systemctl daemon-reload
解释: 如果集群初始化失败,可通过此方法彻底清理环境:先删除所有 Docker 容器,再清除 /etc/ceph、/var/lib/ceph、/var/log/ceph 下的残留配置和数据,最后重载 systemd 配置,以便重新执行 bootstrap 初始化。
七.部署ceph
为ceph添加osd
这里需要拥有三块硬盘,不能有分区
root@ceph-node1 ceph-v19.2.2# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 30G 0 disk
sdb 8:16 0 20G 0 disk
sdc 8:32 0 20G 0 disk
sr0 11:0 1 14.5G 0 rom /rhel9.8
nvme0n1 259:0 0 80G 0 disk
├─nvme0n1p1 259:1 0 1G 0 part /boot
└─nvme0n1p2 259:2 0 79G 0 part
├─rhel-root 253:0 0 77G 0 lvm /
└─rhel-swap 253:1 0 2G 0 lvm SWAP
root@ceph-node1 ceph-v19.2.2# ceph orch daemon add osd ceph-node1:/dev/sda
Created osd(s) 0 on host 'ceph-node1'
root@ceph-node1 ceph-v19.2.2# ceph orch daemon add osd ceph-node1:/dev/sdb
Created osd(s) 1 on host 'ceph-node1'
root@ceph-node1 ceph-v19.2.2# ceph orch daemon add osd ceph-node1:/dev/sdc
Created osd(s) 2 on host 'ceph-node1'root@ceph-node1 ceph-v19.2.2# ceph orch device ls
HOST PATH TYPE DEVICE ID SIZE AVAILABLE REFRESHED REJECT REASONS
ceph-node1 /dev/sda hdd ATA_VMware_Virtual_SATA_Hard_Drive_00000000000000000001 30.0G No 47s ago Has a FileSystem, Insufficient space (<10 extents) on vgs, LVM detected
ceph-node1 /dev/sdb hdd ATA_VMware_Virtual_SATA_Hard_Drive_02000000000000000001 20.0G No 47s ago Has a FileSystem, Insufficient space (<10 extents) on vgs, LVM detected
ceph-node1 /dev/sdc hdd ATA_VMware_Virtual_SATA_Hard_Drive_03000000000000000001 20.0G No 47s ago Has a FileSystem, Insufficient space (<10 extents) on vgs, LVM detected
root@ceph-node1 ceph-v19.2.2# ceph orch ps
NAME HOST PORTS STATUS REFRESHED AGE MEM USE MEM LIM VERSION IMAGE ID CONTAINER ID
alertmanager.ceph-node1 ceph-node1 *:9093,9094 running (26m) 72s ago 29m 21.5M - 0.25.0 fd4d9a3dd1fd 4aa3e86d2a2a
ceph-exporter.ceph-node1 ceph-node1 running (29m) 72s ago 29m 4396k - 19.2.2 8214ebff6133 11350ebc6362
crash.ceph-node1 ceph-node1 running (29m) 72s ago 29m 728k - 19.2.2 8214ebff6133 61d6f834313c
grafana.ceph-node1 ceph-node1 *:3000 running (26m) 72s ago 28m 76.6M - 10.4.0 f9811e4e687f 5d1b81ebe6cf
mgr.ceph-node1.mhkgzj ceph-node1 *:8443,8765 running (28m) 72s ago 28m 11.1M - 19.2.2 8214ebff6133 bacfa165ac31
mgr.ceph-node1.pkotix ceph-node1 *:9283,8765,8443 running (31m) 72s ago 31m 78.9M - 19.2.2 8214ebff6133 064d6bcb41d7
mon.ceph-node1 ceph-node1 running (31m) 72s ago 31m 41.7M 2048M 19.2.2 8214ebff6133 d59ba552f61a
root@ceph-node1 ceph-v19.2.2# ceph -s
cluster:
id: c9ef1cb6-a544-11f1-b219-000c29c71969
health: HEALTH_OK
services:
mon: 1 daemons, quorum ceph-node1 (age 32m)
mgr: ceph-node1.pkotix(active, since 27m), standbys: ceph-node1.mhkgzj
osd: 3 osds: 3 up (since 2m), 3 in (since 2m)
data:
pools: 1 pools, 1 pgs
objects: 2 objects, 577 KiB
usage: 80 MiB used, 70 GiB / 70 GiB avail
pgs: 1 active+clean
解释: 首先通过 lsblk 查看磁盘信息,确认系统中有 sda、sdb、sdc 三块未分区的裸盘(30G + 20G + 20G),这是添加 OSD 的前提条件。然后使用 ceph orch daemon add osd 命令依次将三块磁盘添加为 OSD,命令格式为 ceph orch daemon add osd 主机名:/dev/磁盘名,执行成功后分别创建了 osd.0、osd.1、osd.2。接着用 ceph orch device ls 查看设备状态,此时三块磁盘显示 AVAILABLE=No 是因为已被 Ceph 接管。最后通过 ceph orch ps 查看所有守护进程运行状态,并用 ceph -s 确认集群健康状态已从之前的 HEALTH_WARN 转为 HEALTH_OK,OSD 数量显示为 3 up、3 in,说明三块磁盘已成功加入集群并正常工作。
注意:
对于以上状态有问题的进程可以进行重启或重建
ceph orch restart alertmanager.ceph-node1
ceph orch restart ceph-exporter.ceph-node1
ceph orch restart crash.ceph-node1
ceph orch restart grafana.ceph-node1
ceph orch restart mgr.ceph-node1.qlcikdceph orch restart
ceph orch rm alertmanager --force
ceph orch rm crash --force
ceph orch rm grafana --force
ceph orch rm ceph-exporter --forceceph orch apply alertmanager
ceph orch apply crash
ceph orch apply grafana
ceph orch apply ceph-exporterceph orch ls
ceph orch daemon rm mgr.ceph-node1.qlcikd --force
ceph orch apply mgr 2
解释: 当集群中某些守护进程(如 alertmanager、grafana、mgr 等)出现异常时,可以使用 ceph orch restart 进程名.主机名 单独重启某个进程。如果重启无法解决问题,则采用「先删除再重建」的策略:先用 ceph orch rm 服务名 --force 强制删除异常服务,再用 ceph orch apply 服务名 重新编排部署该服务。对于 MGR 管理进程,可以用 ceph orch daemon rm mgr.ceph-node1.qlcikd --force 删除指定 MGR 实例,然后通过 ceph orch apply mgr 2 重新部署 2 个 MGR 实例(一主一备)。ceph orch ls 用于列出当前所有已编排的服务。
建立存储池
#建立元数据池
root@ceph-node1 ceph-v19.2.2# ceph osd pool create metadata_k8s
pool 'metadata_k8s' created
#建立数据池
root@ceph-node1 ceph-v19.2.2# ceph osd pool create data_k8s
pool 'data_k8s' created
#列出建立的pool
root@ceph-node1 ceph-v19.2.2# ceph osd pool ls
.mgr
metadata_k8s
data_k8s
#建立cephfs 绑定数据池
root@ceph-node1 ceph-v19.2.2# ceph fs new k8s metadata_k8s data_k8s
Pool 'data_k8s' (id '3') has pg autoscale mode 'on' but is not marked as bulk.
Consider setting the flag by running
ceph osd pool set data_k8s bulk true
new fs with metadata pool 2 and data pool 3
#部署CephFS 元数据服务CephFS 必须要有 MDS 才能对外提供文件挂载
`--placement 2`:编排部署 2 个 MDS 实例
root@ceph-node1 ceph-v19.2.2# ceph orch apply mds k8s --placement 2
Scheduled mds.k8s update...
#subvolumegroup 子卷组:Ceph‑CSI 的规范约定
#在 `k8s` 这个 CephFS 文件系统下创建名字叫 `csi` 的子卷组
#K8s 的 CephFS‑CSI 驱动,所有 PV 持久化卷都会创建在这个 csi 子卷组内部root@ceph-node1 ceph-v19.2.2# ceph fs subvolumegroup create k8s csi
root@ceph-node1 ceph-v19.2.2# ceph fs subvolumegroup ls k8s
{ "name": "csi" }
解释: 建立存储池是 CephFS 文件系统初始化的关键步骤。首先用 ceph osd pool create metadata_k8s 创建元数据池(存放文件目录、权限等元数据),再用 ceph osd pool create data_k8s 创建数据池(存放实际文件内容),通过 ceph osd pool ls 可确认两个池已创建成功。接着用 ceph fs new k8s metadata_k8s data_k8s 将元数据池和数据池绑定,创建名为 k8s 的 CephFS 文件系统,输出中的提示建议为数据池设置 bulk 标记以优化 PG 自动扩展。由于 CephFS 必须依赖 MDS 元数据服务才能对外提供文件挂载,因此用 ceph orch apply mds k8s --placement 2 编排部署 2 个 MDS 实例(一主一备)。最后按照 Ceph-CSI 的规范约定,用 ceph fs subvolumegroup create k8s csi 在文件系统下创建名为 csi 的子卷组,后续 K8s 的 CephFS-CSI 驱动创建的所有 PV 持久化卷都会存放在这个子卷组内部,通过 ceph fs subvolumegroup ls k8s 可验证子卷组创建成功。
八.kubernetes+Cephfs的整合项目
Ceph-CSI 是 Ceph 官方实现的 Container Storage Interface (CSI)驱动程序,用于将 Ceph 分布式存储(RBD / CephFS)接入 Kubernetes,为 Pod 提供动态持久化存储(PersistentVolume)。它替代了早期 Kubernetes 内置的 in-tree RBD/CephFS 插件,是云原生场景下连接 K8s 与 Ceph 的标准方式。
支持的存储后端
|-------------------------------|-----------------------|-----------------|---------------------|
| 后端 | CSI Driver | 典型访问模式 | 适用场景 |
| CephFS (Ceph File System) | cephfs.csi.ceph.com | RWO / RWX / ROX | 多 Pod 共享读写、CMS、日志目录 |
| NFS (via Ceph MDS/Ganesha) | 部分版本支持 | RWX | 兼容传统 NFS 客户端 |
| | | | |
github地址:
Releases · ceph/ceph-csi · GitHub
Ceph-CSI 插件地址:
https://github.com/ceph/ceph-csi/archive/refs/tags/v3.17.0.tar.gz
1.下载插件
root@k8s-master \~# wget https://github.com/ceph/ceph-csi/archive/refs/tags/v3.17.0.tar.gz
这里安装包是导入的
root@k8s-master \~# unzip ceph-csi-3.17.zip
Archive: ceph-csi-3.17.zip
creating: ceph-csi-3.17/
inflating: ceph-csi-3.17/ceph-cs-images-3.17.0.tar
inflating: ceph-csi-3.17/ceph-csi-3.17.0.tar.gz
inflating: ceph-csi-3.17/ceph-yaml.tar.gz
root@k8s-master \~# cd ceph-csi-3.17
root@k8s-master ceph-csi-3.17# tar zxf ceph-csi-3.17.0.tar.gz
root@k8s-master ceph-csi-3.17# cd ceph-csi-3.17.0/
root@k8s-master ceph-csi-3.17.0# ls
actions charts e2e LICENSE README.md vendor
AGENTS.md cmd examples lychee.toml scripts
api deploy go.mod Makefile tools
assets deploy.sh go.sum PendingReleaseNotes.md troubleshooting
build.env docs internal pkg v3
root@k8s-master ceph-csi-3.17.0#
2.建立插件需要的secrets
k8s如果要访问ceph集群需要想其注入ceph集群的管理账号信息
查看ceph集群账号信息
root@ceph-node1 ceph-v19.2.2# ceph auth ls
mds.k8s.ceph-node1.oqushq
key: AQCGk5VqAuilLBAA9yNW7nJi5Qv65XZzDFYCfg==
caps: mds allow
caps: mon profile mds
caps: osd allow rw tag cephfs *=*
mds.k8s.ceph-node1.phffnt
key: AQCIk5VqJPm7ExAAgMf12T6HbKy6oiCZh+vfMw==
caps: mds allow
caps: mon profile mds
caps: osd allow rw tag cephfs *=*
osd.0
key: AQDYkJVqNqlYEBAAG+RHZIUoL/9/WN/6dhLDSw==
caps: mgr allow profile osd
caps: mon allow profile osd
caps: osd allow *
osd.1
key: AQD7kJVqPct+DBAAx66U0V8a7aewDqVW7zgk9g==
caps: mgr allow profile osd
caps: mon allow profile osd
caps: osd allow *
osd.2
key: AQAfkZVqsW3YFxAANvcfornxjq6XkV9Pt64xgQ==
caps: mgr allow profile osd
caps: mon allow profile osd
caps: osd allow *
client.admin
key: AQAaipVq0GSwMhAAQ95nSGWTtHHznHtkLuvNHw==
caps: mds allow *
caps: mgr allow *
caps: mon allow *
caps: osd allow *
client.bootstrap-mds
key: AQAdipVq/RH8JRAAT3/iNJfZ1p7zJWwQMTj2ZA==
caps: mon allow profile bootstrap-mds
client.bootstrap-mgr
key: AQAdipVqixn8JRAAJi8hrsc+yuJN4YAYqbNhYg==
caps: mon allow profile bootstrap-mgr
client.bootstrap-osd
key: AQAdipVqpSH8JRAA8MmwCBEEmi2UlzE2QOknDA==
caps: mon allow profile bootstrap-osd
client.bootstrap-rbd
key: AQAdipVqBij8JRAA2rEoc+fo5CXzw8SLCRPTww==
caps: mon allow profile bootstrap-rbd
client.bootstrap-rbd-mirror
key: AQAdipVqVy/8JRAAFB4BQSqSsOhEpk72Sv8fZA==
caps: mon allow profile bootstrap-rbd-mirror
client.bootstrap-rgw
key: AQAdipVqLzj8JRAAdw1Hj7WB8uHYkSttUG2rHA==
caps: mon allow profile bootstrap-rgw
client.ceph-exporter.ceph-node1
key: AQCCipVqQUoeNRAA3TiELdBaQnB4TG2fsl7kdA==
caps: mgr allow r
caps: mon profile ceph-exporter
caps: osd allow r
client.crash.ceph-node1
key: AQCEipVqIhr+DxAArffQQe8L/ttLDAFVE+pJ5g==
caps: mgr profile crash
caps: mon profile crash
mgr.ceph-node1.mhkgzj
key: AQDoipVq3AIQHBAAltfByJYCyrhScTjTFOWPyA==
caps: mds allow *
caps: mon profile mgr
caps: osd allow *
mgr.ceph-node1.pkotix
key: AQAbipVqLFrBAxAAyLzCYkhEWAzJMKsNkM+F2w==
caps: mds allow *
caps: mon profile mgr
caps: osd allow *
root@ceph-node1 ceph-v19.2.2#
生成secrets将账号信息注入k8s
root@k8s-master ceph-csi-3.17.0# kubectl create namespace cephfs
namespace/cephfs created
root@k8s-master \~# cd /root/ceph-csi-3.17.0/ceph-csi-3.17/examples/cephfs/
root@k8s-master ceph-csi-3.17.0# ls
actions build.env deploy.sh go.mod lychee.toml README.md v3
AGENTS.md charts docs go.sum Makefile scripts vendor
api cmd e2e internal PendingReleaseNotes.md tools
assets deploy examples LICENSE pkg troubleshooting
root@k8s-master ceph-csi-3.17.0# cd examples/cephfs/
root@k8s-master cephfs# ls
deployment.yaml plugin-deploy.sh pod-rwop.yaml pvc.yaml
exec-bash.sh plugin-teardown.sh pod.yaml secret.yaml
groupsnapshotclass.yaml pod-clone.yaml pvc-clone.yaml snapshotclass.yaml
groupsnapshot.yaml pod-ephemeral.yaml pvc-restore.yaml snapshot.yaml
logs.sh pod-restore.yaml pvc-rwop.yaml storageclass.yaml
root@k8s-master cephfs# vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: csi-cephfs-secret
namespace: cephfs #设定加密认证信息注入的namespace
stringData:Required for statically and dynamically provisioned volumes
The userID must not include the "client." prefix!
userID: admin #以集群管理员身份访问ceph集群
userKey: AQCaF0Nqod89JxAAetU6+barLePZdmgSWYm9zA== #给定client.admin密码Encryption passphrase
encryptionPassphrase: test_passphrase
生成k8s中ceph的配置文件
root@k8s-master ceph-csi-3.17.0# ls
actions build.env deploy.sh go.mod lychee.toml README.md v3
AGENTS.md charts docs go.sum Makefile scripts vendor
api cmd e2e internal PendingReleaseNotes.md tools
assets deploy examples LICENSE pkg troubleshooting
root@k8s-master ceph-csi-3.17.0# cd deploy/
root@k8s-master deploy# vim ceph-conf.yaml
This is a sample configmap that helps define a Ceph configuration as required
by the CSI plugins.
Sample ceph.conf available at
https://github.com/ceph/ceph/blob/master/src/sample.ceph.conf Detailed
documentation is available at
https://docs.ceph.com/en/latest/rados/configuration/ceph-conf/
apiVersion: v1
kind: ConfigMap
data:
ceph.conf: |global
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephxenable ceph librbd,librados logs in rbd/cephfs/nfs container logs
log_to_stderr = true
debug_rbd = 30 # enable debug rbd logs
debug_rados = 30 # enable debug rados logs
debug_rbd_mirror = 30 # enable debugging logs for rbd mirroring daemon
keyring is a required key and its value should be empty
keyring: |
metadata:
name: ceph-config
namespace: cephfs #指定配置配置文件注入namespaceapiVersion: v1
kind: ConfigMap
metadata:
name: ceph-csi-encryption-kms-config #在ceph-csi插件的配置中是要去使用这个名字的CM的,名字一定要注意
namespace: cephfsroot@k8s-master deploy# kubectl apply -f ceph-conf.yaml
configmap/ceph-config created
configmap/ceph-csi-encryption-kms-config created
root@k8s-master deploy# kubectl -n cephfs get cm
NAME DATA AGE
ceph-config 2 7s
ceph-csi-encryption-kms-config 0 7s
kube-root-ca.crt 1 15m
root@k8s-master deploy# kubectl apply -f ceph-conf.yaml
configmap/ceph-config created
configmap/ceph-csi-encryption-kms-config created
root@k8s-master deploy# kubectl -n cephfs get cm
NAME DATA AGE
ceph-config 2 6s
ceph-csi-encryption-kms-config 0 6s
kube-root-ca.crt 1 6m27s
root@k8s-master deploy#
在k8s中安装ceph插件
root@ceph-node1 ceph-v19.2.2# ceph -s
cluster:
id: c9ef1cb6-a544-11f1-b219-000c29c71969
health: HEALTH_OK
services:
mon: 1 daemons, quorum ceph-node1 (age 73m)
mgr: ceph-node1.pkotix(active, since 68m), standbys: ceph-node1.mhkgzj
mds: 1/1 daemons up, 1 standby
osd: 3 osds: 3 up (since 42m), 3 in (since 43m)
data:
volumes: 1/1 healthy
pools: 3 pools, 49 pgs
objects: 24 objects, 587 KiB
usage: 81 MiB used, 70 GiB / 70 GiB avail
pgs: 49 active+clean
root@k8s-master deploy# cd cephfs/kubernetes/
root@k8s-master kubernetes# vim csi-config-map.yaml
root@k8s-master kubernetes# kubectl apply -f csi-config-map.yaml
configmap/ceph-csi-config created
root@k8s-master kubernetes# kubectl get cm -n cephfs
NAME DATA AGE
ceph-config 2 3m22s
ceph-csi-config 1 5s
ceph-csi-encryption-kms-config 0 3m22s
kube-root-ca.crt 1 9m43s
root@k8s-master kubernetes# grep namespace: csi-nodeplugin-rbac.yaml csi-provisioner-rbac.yaml
csi-nodeplugin-rbac.yaml: namespace: default
csi-nodeplugin-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
root@k8s-master kubernetes# sed -i 's/namespace: default/namespace: cephfs/g' csi-nodeplugin-rbac.yaml csi-provisioner-rbac.yaml
root@k8s-master kubernetes# grep namespace: csi-nodeplugin-rbac.yaml csi-provisioner-rbac.yaml
csi-nodeplugin-rbac.yaml: namespace: cephfs
csi-nodeplugin-rbac.yaml: namespace: cephfs
csi-provisioner-rbac.yaml: namespace: cephfs
csi-provisioner-rbac.yaml: namespace: cephfs
csi-provisioner-rbac.yaml: namespace: cephfs
csi-provisioner-rbac.yaml: namespace: cephfs
csi-provisioner-rbac.yaml: namespace: cephfs
root@k8s-master kubernetes# kubectl apply -f csi-nodeplugin-rbac.yaml -f csi-provisioner-rbac.yaml
serviceaccount/cephfs-csi-nodeplugin created
clusterrole.rbac.authorization.k8s.io/cephfs-csi-nodeplugin created
clusterrolebinding.rbac.authorization.k8s.io/cephfs-csi-nodeplugin created
serviceaccount/cephfs-csi-provisioner created
clusterrole.rbac.authorization.k8s.io/cephfs-external-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/cephfs-csi-provisioner-role created
role.rbac.authorization.k8s.io/cephfs-external-provisioner-cfg created
rolebinding.rbac.authorization.k8s.io/cephfs-csi-provisioner-role-cfg created
这里需要下载相应所需的镜像,并上传至创建好的harbor仓库
docker pull quay.io/cephcsi/cephcsi:v3.17.0 docker pull registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.16.0 docker pull registry.k8s.io/sig-storage/csi-provisioner:v6.2.0 docker pull registry.k8s.io/sig-storage/csi-attacher:v4.11.0 docker pull registry.k8s.io/sig-storage/csi-resizer:v2.1.0 docker pull registry.k8s.io/sig-storage/csi-snapshotter:v8.5.0 docker tag quay.io/cephcsi/cephcsi:v3.17.0 reg.timinglee.org/cephcsi/cephcsi:v3.17.0 docker tag registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.16.0 reg.timinglee.org/sig-storage/csi-node-driver-registrar:v2.16.0 docker tag registry.k8s.io/sig-storage/csi-provisioner:v6.2.0 reg.timinglee.org/sig-storage/csi-provisioner:v6.2.0 docker tag registry.k8s.io/sig-storage/csi-attacher:v4.11.0 reg.timinglee.org/sig-storage/csi-attacher:v4.11.0 docker tag registry.k8s.io/sig-storage/csi-resizer:v2.1.0 reg.timinglee.org/sig-storage/csi-resizer:v2.1.0 docker tag registry.k8s.io/sig-storage/csi-snapshotter:v8.5.0 reg.timinglee.org/sig-storage/csi-snapshotter:v8.5.0 docker login reg.timinglee.org docker push reg.timinglee.org/cephcsi/cephcsi:v3.17.0 docker push reg.timinglee.org/sig-storage/csi-node-driver-registrar:v2.16.0 docker push reg.timinglee.org/sig-storage/csi-provisioner:v6.2.0 docker push reg.timinglee.org/sig-storage/csi-attacher:v4.11.0 docker push reg.timinglee.org/sig-storage/csi-resizer:v2.1.0 docker push reg.timinglee.org/sig-storage/csi-snapshotter:v8.5.0
#修改文件内容指定镜像路径
root@k8s-master kubernetes# grep -n image: csi-cephfsplugin.yaml
29: image: cephcsi/cephcsi:v3.17.0
109: image: sig-storage/csi-node-driver-registrar:v2.16.0
128: image: cephcsi/cephcsi:v3.17.0
root@k8s-master kubernetes# grep -n image: csi-cephfsplugin-provisioner.yaml
46: image: cephcsi/cephcsi:v3.17.0
95: image: sig-storage/csi-provisioner:v6.2.0
121: image: sig-storage/csi-attacher:v4.11.0
144: image: sig-storage/csi-resizer:v2.1.0
170: image: sig-storage/csi-snapshotter:v8.5.0
195: image: cephcsi/cephcsi:v3.17.0
216: image: cephcsi/cephcsi:v3.17.0
root@k8s-master kubernetes# kubectl apply -f csi-cephfsplugin.yaml -f csi-cephfsplugin-provisioner.yaml -n cephfs
daemonset.apps/csi-cephfsplugin created
service/csi-metrics-cephfsplugin created
service/csi-cephfsplugin-provisioner created
deployment.apps/csi-cephfsplugin-provisioner created
root@k8s-master kubernetes# kubectl -n cephfs get pods
NAME READY STATUS RESTARTS AGE
csi-cephfsplugin-7dcnw 3/3 Running 0 13h
csi-cephfsplugin-9cx9f 3/3 Running 0 13h
csi-cephfsplugin-provisioner-9857f5957-k7bvm 7/7 Running 0 13h
csi-cephfsplugin-provisioner-9857f5957-lspsv 7/7 Running 2 (113m ago) 13h
root@k8s-master kubernetes#
root@k8s-master kubernetes# vim csidriver.yaml
/!\ DO NOT MODIFY THIS FILE
This file has been automatically generated by Ceph-CSI yamlgen.
The source for the contents can be found in the api/deploy directory, make
your modifications there.
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: "cephfs.csi.ceph.com"
namespace: cephfs
spec:
attachRequired: true
podInfoOnMount: true
fsGroupPolicy: FileseLinuxMount: true
root@k8s-master kubernetes# kubectl apply -f csidriver.yaml
利用ceph为k8s建立存储
建立存储类
在存储类中需要填写ceph集群信息
root@ceph-node1 ceph-v19.2.2# ceph -s
cluster:
id: c9ef1cb6-a544-11f1-b219-000c29c71969
health: HEALTH_OK
services:
mon: 1 daemons, quorum ceph-node1 (age 3h)
mgr: ceph-node1.mhkgzj(active, since 3h), standbys: ceph-node1.pkotix
mds: 1/1 daemons up, 1 standby
osd: 3 osds: 3 up (since 3h), 3 in (since 14h)
data:
volumes: 1/1 healthy
pools: 3 pools, 49 pgs
objects: 24 objects, 589 KiB
usage: 91 MiB used, 70 GiB / 70 GiB avail
pgs: 49 active+clean
root@ceph-node1 ceph-v19.2.2# ceph fs ls
name: k8s, metadata pool: metadata_k8s, data pools: data_k8s
root@k8s-master ceph-csi-3.17.0# ls
actions build.env deploy.sh go.mod lychee.toml README.md v3
AGENTS.md charts docs go.sum Makefile scripts vendor
api cmd e2e internal PendingReleaseNotes.md tools
assets deploy examples LICENSE pkg troubleshooting
root@k8s-master ceph-csi-3.17.0# cd examples/cephfs/
root@k8s-master cephfs# ls
deployment.yaml plugin-deploy.sh pod-rwop.yaml pvc.yaml
exec-bash.sh plugin-teardown.sh pod.yaml secret.yaml
groupsnapshotclass.yaml pod-clone.yaml pvc-clone.yaml snapshotclass.yaml
groupsnapshot.yaml pod-ephemeral.yaml pvc-restore.yaml snapshot.yaml
logs.sh pod-restore.yaml pvc-rwop.yaml storageclass.yaml
root@k8s-master cephfs#
root@k8s-master cephfs# vim storageclass.yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: csi-cephfs-sc provisioner: cephfs.csi.ceph.com parameters: clusterID: c9ef1cb6-a544-11f1-b219-000c29c71969 fsName: k8s pool: data_k8s csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret csi.storage.k8s.io/provisioner-secret-namespace: cephfs csi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secret csi.storage.k8s.io/controller-expand-secret-namespace: cephfs csi.storage.k8s.io/controller-publish-secret-name: csi-cephfs-secret csi.storage.k8s.io/controller-publish-secret-namespace: cephfs csi.storage.k8s.io/node-stage-secret-name: csi-cephfs-secret csi.storage.k8s.io/node-stage-secret-namespace: cephfs reclaimPolicy: Delete allowVolumeExpansion: trueroot@k8s-master cephfs# kubectl apply -f storageclass.yaml
storageclass.storage.k8s.io/csi-cephfs-sc created
root@k8s-master cephfs# kubectl get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
csi-cephfs-sc cephfs.csi.ceph.com Delete Immediate true 8s
root@k8s-master cephfs#
建立pvc
root@k8s-master cephfs# vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-cephfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
storageClassName: csi-cephfs-sc
root@k8s-master cephfs# kubectl apply -f pvc.yaml
persistentvolumeclaim/csi-cephfs-pvc created
root@k8s-master cephfs# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
csi-cephfs-pvc Pending csi-cephfs-sc <unset> 6s
root@k8s-master cephfs#
九.kubernetes+CephRDB的整合项目
在ceph中建立块存储
root@ceph-node1 ceph-v19.2.2# ceph osd pool create rbdstorage
pool 'rbdstorage' created
root@ceph-node1 ceph-v19.2.2# ceph osd pool application enable rbdstorage rbd
enabled application 'rbd' on pool 'rbdstorage'
root@ceph-node1 ceph-v19.2.2# ceph auth add client.rbdadmin mon "profile rbd" osd "profile rbd pool=rbdstorage" mgr "profile rbd pool=rbdstorage"
added key for client.rbdadmin
root@ceph-node1 ceph-v19.2.2# ceph osd pool ls
.mgr
metadata_k8s
data_k8s
rbdstorage
root@ceph-node1 ceph-v19.2.2#
解释: 首先用 ceph osd pool create rbdstorage 创建名为 rbdstorage 的存储池,用于存放 RBD 块设备数据。接着用 ceph osd pool application enable rbdstorage rbd 将该池的应用类型标记为 rbd,告诉 Ceph 这个池专门用于 RBD 块存储。然后通过 ceph auth add client.rbdadmin 创建名为 client.rbdadmin 的认证用户,并授予其 mon 的 profile rbd 权限、osd 和 mgr 上针对 rbdstorage 池的 profile rbd 权限,该账号将用于 K8s 侧访问 Ceph 集群。最后用 ceph osd pool ls 确认 rbdstorage 池已成功创建。
建立独立命名空间
root@k8s-master \~# kubectl create namespace cephrbd
namespace/cephrbd created
root@k8s-master \~#
解释: 在 Kubernetes 中创建名为 cephrbd 的独立命名空间,用于隔离 RBD 相关的 CSI 插件资源(Secret、ConfigMap、RBAC、Deployment 等),避免与 CephFS 或其他业务资源相互干扰。
建立rdbsecret
root@k8s-master ceph-csi-3.17.0# mkdir -p /root/cephrbd
root@k8s-master ceph-csi-3.17.0# cp examples/rbd/secret.yaml /root/cephrbd/1-secret.yamlroot@k8s-master ceph-csi-3.17.0# vim /root/cephrbd/1-secret.yaml
root@k8s-master ceph-csi-3.17.0#
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: cephrbd
stringData:
Key values correspond to a user name and its key, as defined in the
ceph cluster. User ID should have required access to the 'pool'
specified in the storage class
The userID must not include the "client." prefix!
userID: admin
userKey: AQDIToxqYEb5ABAAQg4egTcCSv8OOXrcZOUmCA==
Encryption passphrase
encryptionPassphrase: test_passphrase
解释: 先创建 /root/cephrbd 目录存放 RBD 相关配置文件,并从 Ceph-CSI 示例中复制 secret.yaml 作为模板。编辑后的 Secret 文件在 cephrbd 命名空间下创建名为 csi-rbd-secret 的密钥,其中 userID 填写 admin(注意不能带 client. 前缀),userKey 填写 Ceph 集群中 client.admin 的密钥,用于 CSI 插件认证访问 Ceph。该 Secret 会被后续的 StorageClass 引用,作为动态供给 RBD 卷时的认证凭据。
建立configmap配置配文件
root@master deploy# cp ceph-conf.yaml /root/cephrbd/2-ceph-conf.yaml
root@master cephrbd# vim 2-ceph-conf.yaml#https://docs.ceph.com/en/latest/rados/configuration/ceph-conf/
apiVersion: v1
kind: ConfigMap
data:
ceph.conf: |
global
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
enable ceph librbd,librados logs in rbd/cephfs/nfs container logs
log_to_stderr = true
debug_rbd = 30 # enable debug rbd logs
debug_rados = 30 # enable debug rados logs
debug_rbd_mirror = 30 # enable debugging logs for rbd mirroring daemon
keyring is a required key and its value should be empty
keyring: |
metadata:
name: ceph-config
namespace: cephrbd
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
{}
metadata:
name: ceph-csi-encryption-kms-config
namespace: cephrbd
root@k8s-master ceph-csi-3.17.0# cd deploy/rbd/kubernetes/
root@k8s-master kubernetes# cp * /root/cephrbd/
root@k8s-master kubernetes# cd /root/cephrbd/
root@k8s-master cephrbd# vim csi-config-map.yamlroot@k8s-master cephrbd# kubectl apply -f 1-secret.yaml -f 2-ceph-conf.yaml -f csi-config-map.yaml
secret/csi-rbd-secret created
configmap/ceph-config created
configmap/ceph-csi-encryption-kms-config created
configmap/ceph-csi-config created
root@k8s-master cephrbd# kubectl -n cephrbd get cm
NAME DATA AGE
ceph-config 2 5s
ceph-csi-config 1 5s
ceph-csi-encryption-kms-config 1 5s
kube-root-ca.crt 1 7m6s
root@k8s-master cephrbd#
解释: 将 CephFS 章节用过的 ceph-conf.yaml 复制为 RBD 版本并修改命名空间为 cephrbd。该文件定义了两个 ConfigMap:ceph-config 存放 Ceph 客户端配置(启用 cephx 认证、keyring 为空),ceph-csi-encryption-kms-config 用于 KMS 加密配置(此处为空对象)。接着从 deploy/rbd/kubernetes/ 目录复制 CSI 插件所需的全部 YAML 到 /root/cephrbd/,并编辑 csi-config-map.yaml 填入集群 ID 等信息。最后一次性应用 Secret 和三个 ConfigMap,通过 kubectl -n cephrbd get cm 确认全部创建成功。
建立插件的集群授权
root@k8s-master cephrbd# grep "namespace: default" csi-nodeplugin-rbac.yaml csi-provisioner-rbac.yaml
csi-nodeplugin-rbac.yaml: namespace: default
csi-nodeplugin-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
csi-provisioner-rbac.yaml: namespace: default
root@k8s-master cephrbd# sed -i 's/namespace: default/namespace: cephrbd/g' csi-nodeplugin-rbac.yaml csi-provisioner-rbac.yaml
root@k8s-master cephrbd# grep "namespace:" csi-nodeplugin-rbac.yaml csi-provisioner-rbac.yamlcsi-nodeplugin-rbac.yaml: namespace: cephrbd
csi-nodeplugin-rbac.yaml: namespace: cephrbd
csi-provisioner-rbac.yaml: namespace: cephrbd
csi-provisioner-rbac.yaml: namespace: cephrbd
csi-provisioner-rbac.yaml: namespace: cephrbd
csi-provisioner-rbac.yaml: namespace: cephrbd
csi-provisioner-rbac.yaml: namespace: cephrbd
root@k8s-master cephrbd# kubectl -n cephrbd apply -f csi-nodeplugin-rbac.yaml -f csi-provisioner-rbac.yaml
serviceaccount/rbd-csi-nodeplugin created
clusterrole.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
serviceaccount/rbd-csi-provisioner created
clusterrole.rbac.authorization.k8s.io/rbd-external-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role created
role.rbac.authorization.k8s.io/rbd-external-provisioner-cfg created
rolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role-cfg created
root@k8s-master cephrbd#
解释: CSI 插件的 RBAC 文件默认使用 default 命名空间,需要先用 grep 确认所有 namespace: default 的位置,再用 sed -i 批量替换为 cephrbd,替换后再次 grep 验证修改生效。最后应用两个 RBAC 文件,创建 CSI 插件运行所需的 ServiceAccount、ClusterRole、ClusterRoleBinding、Role 和 RoleBinding,为插件提供访问 Kubernetes API 的权限。
运行插件pod
root@master cephrbd# sed -i 's/namespace: default/namespace: cephrbd/g' csi-rbdplugin-provisioner.yaml csi-rbdplugin.yaml
root@master cephrbd# grep "namespace: " csi-rbdplugin-provisioner.yaml
namespace: cephrbd
namespace: cephrbd
root@master cephrbd# grep "namespace: " csi-rbdplugin.yaml
namespace: cephrbd
namespace: cephrbd
因为harbor仓库,需要更改镜像路径
root@master cephrbd# vim csi-rbdplugin-provisioner.yaml
50: image: cephcsi/cephcsi:v3.17.0
107: image: sig-storage/csi-provisioner:v6.2.0
136: image: sig-storage/csi-snapshotter:v8.5.0
161: image: sig-storage/csi-attacher:v4.11.0
185: image: sig-storage/csi-resizer:v2.1.0
211: image: cephcsi/cephcsi:v3.17.0
232: image: cephcsi/cephcsi:v3.17.0
root@master cephrbd# vim csi-rbdplugin.yaml
31: image: cephcsi/cephcsi:v3.17.0
119: image: sig-storage/csi-node-driver-registrar:v2.16.0
138: image: cephcsi/cephcsi:v3.17.0
root@master cephrbd# kubectl -n cephrbd apply -f csi-rbdplugin.yaml -f csi-rbdplugin-provisioner.yaml
daemonset.apps/csi-rbdplugin created
service/csi-metrics-rbdplugin created
service/csi-rbdplugin-provisioner created
deployment.apps/csi-rbdplugin-provisioner created
root@k8s-master cephrbd# kubectl -n cephrbd get pods
NAME READY STATUS RESTARTS AGE
csi-rbdplugin-8g7z5 3/3 Running 0 3m46s
csi-rbdplugin-provisioner-d4dc965db-2zpp5 7/7 Running 0 3m46s
csi-rbdplugin-provisioner-d4dc965db-p22c7 7/7 Running 3 (117s ago) 3m46s
csi-rbdplugin-provisioner-d4dc965db-rb7xj 0/7 Pending 0 3m46s
csi-rbdplugin-x94wb 3/3 Running 0 3m46s
root@k8s-master cephrbd#
解释: 同样先用 sed 将插件 Deployment/DaemonSet 文件中的命名空间替换为 cephrbd 并验证。由于使用了 Harbor 私有仓库,需要编辑两个 YAML 文件,把其中的镜像路径改为 Harbor 仓库地址(如 reg.timinglee.org/cephcsi/cephcsi:v3.17.0)。应用后创建了 csi-rbdplugin DaemonSet(每个节点运行一个,负责挂载 RBD 卷)和 csi-rbdplugin-provisioner Deployment(负责动态供给 RBD 卷)。通过 kubectl -n cephrbd get pods 查看 Pod 状态,正常情况下插件 Pod 均为 Running,若出现 Pending 需检查镜像拉取或资源调度问题。
建立驱动
root@k8s-master cephrbd# vim csidriver.yaml
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: "rbd.csi.ceph.com"
namespace: cephrbd
spec:
attachRequired: true
podInfoOnMount: true
#seLinuxMount: true
fsGroupPolicy: File
root@k8s-master cephrbd# kubectl apply -f csidriver.yaml
csidriver.storage.k8s.io/rbd.csi.ceph.com created
root@k8s-master cephrbd# kubectl get csidrivers.storage.k8s.io
NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY TOKENREQUESTS REQUIRESREPUBLISH MODES AGE
cephfs.csi.ceph.com true true false <unset> false Persistent 46m
rbd.csi.ceph.com true true false <unset> false Persistent 6s
root@k8s-master cephrbd#
解释: 创建名为 rbd.csi.ceph.com 的 CSIDriver 资源,向 Kubernetes 声明该 CSI 驱动的能力:attachRequired: true 表示卷需要先挂载到节点才能被 Pod 使用;podInfoOnMount: true 表示挂载时向驱动传递 Pod 信息;fsGroupPolicy: File 表示由 CSI 驱动处理 fsGroup 权限。应用后通过 kubectl get csidrivers 可同时看到 CephFS 和 RBD 两个 CSI 驱动均已注册成功。
建立存储类
root@master \~# cp /root/ceph-csi-3.17.0/examples/rbd/storageclass.yaml /root/cephrbd/
更改文件内容
root@master \~# vim /root/cephrbd/storageclass.yaml
19 clusterID: f0d5daa8-9fc3-11f1-9789-000c29083eae
31 pool: rbdstorage
85 csi.storage.k8s.io/provisioner-secret-name: csirbd-secret
86 csi.storage.k8s.io/provisioner-secret-namespace: cephrbd
87 csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
88 csi.storage.k8s.io/controller-expand-secret-namespace: cephrbd
89 csi.storage.k8s.io/controller-publish-secret-name: csi-rbd-secret
90 csi.storage.k8s.io/controller-publish-secret-namespace: cephrbd
91 csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
92 csi.storage.k8s.io/node-stage-secret-namespace: cephrbd
93 # controller-modify-secret
94 csi.storage.k8s.io/controller-modify-secret-name: csi-rbd-secret
95 csi.storage.k8s.io/controller-modify-secret-namespace: cephrbd
root@master \~# kubectl -n cephrbd apply -f /root/cephrbd/storageclass.yaml
storageclass.storage.k8s.io/csi-rbd-sc created
root@master \~# kubectl get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
csi-cephfs-sc cephfs.csi.ceph.com Delete Immediate true 19h
csi-rbd-sc rbd.csi.ceph.com Delete Immediate true 15s
解释: 从 Ceph-CSI 示例中复制 storageclass.yaml 并修改关键参数:clusterID 填写 Ceph 集群的 fsid(通过 ceph -s 查看),pool 指定为 rbdstorage,同时将各阶段使用的 Secret 名称和命名空间统一指向 csi-rbd-secret 和 cephrbd。应用后创建名为 csi-rbd-sc 的 StorageClass,其 provisioner 为 rbd.csi.ceph.com,回收策略为 Delete,支持卷扩容。通过 kubectl get storageclasses 可看到 CephFS 和 RBD 两个存储类均已就绪。
建立pvc验证
root@k8s-master ceph-csi-3.17.0# cp examples/rbd/pvc.yaml /root/cephrbd/
root@k8s-master ceph-csi-3.17.0# cd /root/cephrbd/
root@k8s-master cephrbd# kubectl apply -f pvc.yaml
persistentvolumeclaim/rbd-pvc created
root@k8s-master cephrbd# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
csi-cephfs-pvc Pending csi-cephfs-sc <unset> 36m
rbd-pvc Pending csi-rbd-sc <unset> 5s
test-claim Bound pvc-6a558363-71fb-4df7-b835-f865110109c2 1G RWX nfs-client <unset> 2d21h
www-webserver-0 Bound pvc-9608f2b1-4c72-4ddf-98eb-3d0ec968df71 1Gi RWO nfs-client <unset> 2d21h
www-webserver-1 Bound pvc-c46d5319-cbc5-463a-8825-7cac76597e44 1Gi RWO nfs-client <unset> 2d21h
root@k8s-master cephrbd#
解释: 从示例中复制 pvc.yaml 并应用,创建名为 rbd-pvc 的持久化卷声明,其 StorageClass 指定为 csi-rbd-sc。通过 kubectl get pvc 查看状态,rbd-pvc 显示为 Pending 是因为 CSI 插件正在动态创建 RBD 块设备并绑定 PV,稍等片刻后状态会变为 Bound。列表中其他 PVC 为之前 CephFS 和 NFS 测试遗留的卷,可作对比参考。


