跳转至

Rook、Ceph 与 Kubernetes CSI

Kubernetes 通过 Container Storage Interface(CSI)调用外部存储系统。对 Ceph 而言,当前主流驱动是 ceph-csi,分别提供 RBD 块存储和 CephFS 文件存储能力。

Kubernetes 内置的 rbdcephfs 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 和集群参数。
  • CephBlockPoolCephFilesystem 声明 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 中。
  • 希望用 CephClusterCephBlockPoolCephFilesystem 等 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 仍应显式定义。创建 CephBlockPoolCephFilesystem 不表示所有命名空间会自动获得默认 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.comcephfs.csi.ceph.com。实际名称以集群中的 CSIDriver 对象为准:

kubectl get 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 侧同步检查:

ceph -s
ceph health detail
rbd ls <pool>
ceph fs status

常见故障定位

现象 优先检查
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 更新涉及节点挂载路径,应阅读目标版本升级说明。
  • 不使用 canarydevel 或浮动 latest 镜像部署生产 CSI。

参考资料