Rook、Ceph 与 Kubernetes CSI¶
Kubernetes 通过 Container Storage Interface(CSI)调用外部存储系统。对 Ceph 而言,当前主流驱动是 ceph-csi,分别提供 RBD 块存储和 CephFS 文件存储能力。
Kubernetes 内置的 rbd 和 cephfs Volume Plugin 已在 Kubernetes 1.31 移除。因此,新建或升级后的集群应使用 CSI 驱动,不再编写 kubernetes.io/rbd、内置 cephfs 或旧 FlexVolume 类型的存储配置。
Ceph 和 ceph-csi 的职责¶
Ceph 集群
负责数据存储、副本、CRUSH、Pool、RBD Image 和 CephFS Subvolume
ceph-csi
把 Kubernetes 的 CreateVolume、NodeStage、NodePublish 等 CSI 请求
转换为 Ceph 操作
Kubernetes
通过 StorageClass、PVC、PV、VolumeSnapshot 管理应用所需的卷
ceph-csi 不是另一个 Ceph 集群,也不在 CSI Pod 内保存业务数据。它是 Kubernetes 与已有 Ceph 服务之间的控制和挂载适配层。
两种部署模式¶
Ceph 位于 Kubernetes 内部还是外部,与 CSI 的安装方式相关,但不是绝对的一一对应关系。两种生产模式最终运行的核心驱动仍是 ceph-csi。
我的选择¶
这里讨论的 Ceph 只服务当前 Kubernetes 集群,不给 OpenNebula、Proxmox VE 或其他传统虚拟化平台提供共享存储。基于这个边界,我会优先选择 Rook 管理 Ceph,并由 Rook 部署 ceph-csi。
选择 Rook 不是因为它取代了 ceph-csi,而是因为它把 Ceph 集群和 CSI 的管理方式统一到了 Kubernetes:
- 用
CephCluster声明 MON、MGR、OSD 和集群参数。 - 用
CephBlockPool、CephFilesystem声明 RBD Pool 和 CephFS。 - 由 Operator 持续检查并协调实际状态。
- 通过同一套 YAML、Git 和变更流程管理云原生存储。
- 排障时可以从 Kubernetes CR、Operator、CSI 一直追踪到 Ceph OSD。
我的主线方案
Kubernetes 节点本地数据盘
↓
Rook 管理 Ceph Daemon
↓
RBD / CephFS
↓
Rook 管理 ceph-csi
↓
StorageClass → PVC → Pod
独立 cephadm + ceph-csi 仍保留在本页作为架构边界和已有外部 Ceph 的接入方法,但不是这套环境的首选落地方式。
Rook 管理模式¶
Rook Operator 以 Kubernetes Operator 的方式管理 Ceph 和 CSI 资源,适合以下场景:
- Ceph 的 MON、MGR、OSD、MDS 或 RGW 也运行在 Kubernetes 中。
- 希望用
CephCluster、CephBlockPool、CephFilesystem等 CR 管理 Ceph。 - 希望由 Operator 维护 Ceph Daemon 和 CSI 组件的期望状态。
- 使用 Rook 导入一个外部 Ceph 集群,并由 Rook 管理消费侧连接资源。
典型启动链路:
rook-ceph-operator Deployment
↓ 监听 CR
CephCluster / CephBlockPool / CephFilesystem
↓
Ceph Daemon Pod + ceph-csi Controller/Node Plugin
↓
显式创建 StorageClass
↓
应用创建 PVC
Rook 可以部署和配置 CSI Driver,但业务使用的 StorageClass 仍应显式定义。创建 CephBlockPool 或 CephFilesystem 不表示所有命名空间会自动获得默认 StorageClass。
Rook 也能连接外部 Ceph。此时 Rook 不会把外部物理机上的 OSD 迁入 Kubernetes;它主要导入集群标识、Monitor 地址和 CephX 凭据,并在消费侧部署 CSI 相关资源。
独立 ceph-csi 模式¶
外部 Ceph 已由 cephadm、发行版工具或独立存储团队维护时,可以直接在 Kubernetes 安装 ceph-csi:
- 使用官方 RBD/CephFS Helm Chart。
- 使用 ceph-csi 发布的 Kubernetes Manifest。
- 使用 ceph-csi-operator 管理 Driver 资源。
该方式不要求 Rook,也不会管理外部 Ceph 的 MON、OSD、Pool 和升级。Kubernetes 平台团队负责 CSI 组件,Ceph 团队负责后端集群,双方需要约定 Pool、CephX 权限、容量、版本兼容和故障处理边界。
| 项目 | Rook 管理 | 独立 ceph-csi |
|---|---|---|
| Ceph Daemon 生命周期 | 可由 Rook 管理 | 外部独立管理 |
| CSI 生命周期 | Rook/CSI Operator 管理 | Helm、Manifest 或 CSI Operator 管理 |
| Pool 与文件系统 | 可使用 Rook CR 声明 | 先在外部 Ceph 创建 |
| StorageClass | 仍需显式创建 | 仍需显式创建 |
| 适用场景 | Kubernetes 专用存储、云原生一体化管理 | 既有物理 Ceph 或多个 Kubernetes 集群共享存储平台 |
ceph-csi 在 Kubernetes 中怎样运行¶
无论由 Rook、Helm 还是 Manifest 安装,CSI 通常都由 Controller 和 Node Plugin 两部分组成。
Controller / Provisioner¶
Controller 以 Deployment 运行,负责集群级卷生命周期:
- 根据 PVC 创建或删除 RBD Image/CephFS Subvolume。
- 执行 ControllerPublish/Unpublish 等控制面操作。
- 扩容卷。
- 创建和删除快照、从快照或卷克隆。
一个 Controller Pod 通常包含 ceph-csi 和多个 Kubernetes CSI Sidecar:
| 容器 | 作用 |
|---|---|
csi-provisioner |
监听 PVC/PV 并调用 CreateVolume/DeleteVolume |
csi-attacher |
处理需要的 Attach/Detach 控制流程 |
csi-resizer |
监听 PVC 扩容并调用 ControllerExpandVolume |
csi-snapshotter |
处理 VolumeSnapshot 对应的 CSI 快照调用 |
ceph-csi |
将标准 CSI 请求转换为 RBD 或 CephFS 操作 |
Controller 副本数由 Chart 或 Operator 配置。多副本 Sidecar 通常通过 Leader Election 保证同一控制任务只有一个 Leader 执行,但副本数量不能固定写成两个或三个,应结合安装方式和控制面可用性配置。
使用快照时,除 CSI Pod 中的 csi-snapshotter 外,集群还需要兼容版本的 VolumeSnapshot CRD 和 Snapshot Controller。
Node Plugin¶
Node Plugin 以 DaemonSet 运行在需要使用 Ceph 卷的 Kubernetes 节点上。它通过 CSI Socket 向 Kubelet 注册,并负责:
- 将 RBD Image 映射为节点块设备。
- 挂载 CephFS Subvolume。
- 创建文件系统或执行节点侧扩容。
- 将已 Stage 的卷发布到 Pod 对应目录。
- Pod 删除后卸载,并在不再使用时解除 RBD 映射。
Node Plugin 需要访问宿主机的 Kubelet Plugin 目录、Mount Namespace 和相关内核能力,因此通常以 Privileged Pod 运行。节点安全策略、SELinux/AppArmor、Mount Propagation 和内核模块都可能影响挂载。
PVC 从申请到挂载的完整流程¶
1. 用户创建 PVC,指定 storageClassName
↓
2. external-provisioner 发现未绑定 PVC
↓
3. ceph-csi 读取 StorageClass、Cluster 配置和 Secret
↓
4. 在 Ceph 创建 RBD Image 或 CephFS Subvolume
↓
5. Kubernetes 创建 PV,PVC 状态变为 Bound
↓
6. Scheduler 将使用 PVC 的 Pod 调度到某个 Node
↓
7. Kubelet 调用该节点上的 ceph-csi Node Plugin
↓
8. Node Plugin 映射/挂载卷,并发布到 Pod 目录
↓
9. 容器看到 volumeMounts 或 volumeDevices
删除时方向相反:Pod 卸载 → Node Plugin Unpublish/Unstage → PV 按 reclaimPolicy 保留或删除 → Controller 在 Ceph 删除后端卷。
RBD 的节点挂载方式¶
RBD CSI 常见的 Mapper 有:
- KRBD:通过 Linux 内核 RBD 模块映射块设备,路径短、使用普遍,但支持能力受节点内核版本影响。
- rbd-nbd:通过用户态
rbd-nbd和 NBD 设备映射,可用于需要相关特性的场景;必须核对 ceph-csi 版本、内核、NBD 模块和功能支持状态。
映射后,Node Plugin 根据 volumeMode 处理:
volumeMode: Filesystem
RBD Image → /dev/rbdX → ext4 等文件系统 → 挂载到 Pod
volumeMode: Block
RBD Image → /dev/rbdX → 作为原始块设备交给容器
RBD 通常用于 ReadWriteOnce。需要多个节点同时挂载共享目录时,应优先使用 CephFS;不要把普通 ext4/xfs RBD 卷同时挂载到多台节点。
CephFS 的节点挂载方式¶
CephFS CSI 为每个 PVC 创建或使用 CephFS Subvolume,然后通过以下方式挂载:
- Kernel CephFS Client:使用 Linux 内核客户端,通常是主要选择;功能与兼容性取决于节点内核。
- ceph-fuse:使用用户态 FUSE 客户端,适用于特定兼容场景,但需要考虑额外的进程和性能开销。
CephFS 可提供 ReadWriteMany,多个节点上的 Pod 可以同时访问同一文件系统卷。它是否适合数据库、海量小文件或高频元数据操作,仍需根据 MDS、Metadata Pool 和业务 IO 进行测试。
连接外部 Ceph 需要什么¶
Kubernetes 消费外部 Ceph 至少需要:
| 配置 | 作用 |
|---|---|
| Cluster ID | 通常使用 Ceph FSID,标识后端集群 |
| Monitor 地址 | 让 CSI 找到 Ceph 集群 |
| CephX User/Key | Provisioner 和 Node Plugin 访问后端的身份凭据 |
| Pool 或 CephFS 名称 | 指定卷创建位置 |
| StorageClass | 将 Kubernetes 存储参数映射到 CSI Driver |
| Secret Namespace/Name | 告诉 CSI 在哪里读取对应凭据 |
不要把 client.admin Key 直接用于普通 StorageClass。应分别为 RBD/CephFS Provisioner 与 Node 操作创建满足功能要求的最小权限 CephX 用户,并限制 Kubernetes Secret 的读取权限。Secret 中的 Base64 不是加密,还应启用 Kubernetes Secret 静态加密并控制备份。
StorageClass 关键字段¶
以下片段用于理解字段关系,不是可直接投入生产的完整配置:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-rbd
provisioner: rbd.csi.ceph.com
parameters:
clusterID: <ceph-fsid>
pool: <rbd-pool>
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: <rbd-provisioner-secret>
csi.storage.k8s.io/provisioner-secret-namespace: <csi-namespace>
csi.storage.k8s.io/node-stage-secret-name: <rbd-node-secret>
csi.storage.k8s.io/node-stage-secret-namespace: <csi-namespace>
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate
Rook 默认的 Driver Name 通常带 Operator Namespace 前缀,例如 rook-ceph.rbd.csi.ceph.com;独立 ceph-csi 通常使用 rbd.csi.ceph.com 或 cephfs.csi.ceph.com。实际名称以集群中的 CSIDriver 对象为准:
reclaimPolicy: Delete 会在 PV 回收时删除后端卷;重要数据建议先评估 Retain、备份和人工回收流程。StorageClass 的 Secret 字段还可能包含 ControllerPublish、NodeStage、Expand 等不同操作,必须使用与当前 Chart/Operator 示例一致的完整配置。
选择 RBD 还是 CephFS¶
| 需求 | 推荐方式 |
|---|---|
| 单个节点挂载、虚拟磁盘、数据库盘 | RBD + RWO |
| 多节点共享上传目录或文件数据 | CephFS + RWX |
| 应用直接使用 S3 API | RGW;不经过 RBD/CephFS CSI |
| 原始块设备交给应用 | RBD + volumeMode: Block |
| 需要跨节点共享 POSIX 文件系统 | CephFS |
RGW 是对象存储 API,不通过普通 RBD/CephFS CSI 挂载。应用应使用 S3 SDK,或者另行评估对象存储 CSI/FUSE 方案的语义与稳定性。
运行检查¶
# CSI 驱动是否注册
kubectl get csidriver
# Controller 和 Node Plugin
kubectl -n <csi-namespace> get deploy,ds,pod -o wide
# StorageClass、PVC、PV
kubectl get storageclass
kubectl get pvc -A
kubectl get pv
# PVC 未绑定或 Pod 挂载失败时查看事件
kubectl describe pvc <pvc> -n <namespace>
kubectl describe pod <pod> -n <namespace>
# CSI 日志:标签随安装方式不同
kubectl -n <csi-namespace> logs <provisioner-pod> -c csi-rbdplugin
kubectl -n <csi-namespace> logs <nodeplugin-pod> -c csi-rbdplugin
在 Ceph 侧同步检查:
常见故障定位¶
| 现象 | 优先检查 |
|---|---|
| PVC 一直 Pending | StorageClass 名称、Provisioner、Controller Pod、Secret、Pool/CephFS、Ceph 容量 |
| PVC Bound,Pod Mount 失败 | Node Plugin、节点内核模块、CephX 权限、Monitor 网络、Mount Propagation |
| RBD 仍被占用 | Pod/节点是否异常退出、旧映射、Watcher、节点丢失与 Fencing 流程 |
| CephFS Permission Denied | CephX MDS/OSD Caps、Subvolume、Secret 和挂载路径 |
| 扩容后文件系统没变 | ControllerExpand、NodeExpand、文件系统类型和 Pod 事件 |
| 快照对象 Pending | Snapshot CRD、Snapshot Controller、VolumeSnapshotClass、CSI Snapshotter |
| 节点重启后无法挂载 | Node Plugin 就绪、旧 RBD 映射、内核模块、Kubelet Plugin 目录 |
排障时先区分三个层次:Kubernetes 对象是否正确、ceph-csi 是否完成调用、Ceph 后端是否健康。只看 PVC 状态或只看 ceph -s 都不足以定位完整链路。
版本与升级¶
- 根据 ceph-csi 官方 Support Matrix 同时核对 Kubernetes、ceph-csi 和 Ceph 版本。
- Rook 升级、Ceph 升级和 CSI 升级应分阶段进行,不在存储降级时同时变更。
- 升级前验证现有 PVC 的创建、挂载、扩容、快照和恢复。
- Controller Deployment 更新通常不影响已挂载卷;Node Plugin 更新涉及节点挂载路径,应阅读目标版本升级说明。
- 不使用
canary、devel或浮动latest镜像部署生产 CSI。