容器文件系统是临时性的,Pod 被删除、节点宕机或滚动更新时,写入容器可写层的数据都会丢失。对于 MySQL、PostgreSQL、Kafka、Elasticsearch 等有状态应用,必须把数据独立保存到持久卷。Ceph 作为分布式存储系统,能同时提供块设备、文件系统和对象存储接口,它的数据副本机制和横向扩展能力使它成为 Kubernetes 集群常用的共享存储方案。本文以 Kubernetes 与 Rook 为核心,梳理 Ceph 作为容器存储后端的部署、配置和排障过程。

一、Ceph 提供两种主要的容器持久化接口
容器平台接入 Ceph 通常使用两种接口:RBD 块设备和 CephFS 文件系统。RBD 是 Ceph 的块存储组件,它把一个虚拟磁盘切分成多个对象分布到集群中,容器节点可以通过内核 rbd 驱动或 librbd 库映射为本地块设备。块设备的特点是只能被一个节点以读写方式挂载,适合数据库、日志系统等需要高 IOPS 和稳定延迟的场景。Kubernetes 中对应的是 ReadWriteOnce 访问模式,同一时间只允许一个 Pod 写入。
CephFS 是 Ceph 的文件系统接口,它基于 MDS(元数据服务器)管理目录树,多个客户端可以同时挂载同一个 CephFS 卷。这种共享读写能力适合多个 Pod 同时访问同一份文件的场景,例如内容管理系统、共享上传目录或者需要多副本读取的应用。Kubernetes 中表现为 ReadWriteMany。需要注意 CephFS 的元数据操作比 RBD 更复杂,在高并发小文件场景下需要专门优化 MDS 和元数据池。
除了接口差异,Ceph 本身支持数据副本和纠删码两种冗余策略。生产环境通常为块存储池配置三副本,文件存储元数据池建议放在 SSD 上,数据池可以使用 HDD 或混合介质。把不同性能需求的存储池分开,是使用 Ceph 作为容器后端时首先要做好的规划。
二、通过 Rook 部署 Ceph 并注册 CSI 驱动
手动部署 Ceph 集群需要配置 MON、OSD、MDS、RGW 等多个组件,并把密钥和配置文件分发到每个 Kubernetes 节点,过程比较繁琐。Rook 是一个专门为云原生环境设计的存储编排器,它能以 Operator 方式在 Kubernetes 中自动部署 Ceph 集群,同时自动创建 CSI 插件所需的驱动注册和密钥资源。CSI 是 Kubernetes 标准的存储接口,RBD 和 CephFS 都通过 CSI 控制器与节点插件完成卷的创建、挂载和卸载。
使用 Rook 时,首先在集群中安装 Rook Operator。它负责监视 CephCluster、CephBlockPool、CephFilesystem 等自定义资源。管理员只需要声明期望的 Ceph 集群规格,Operator 就会自动生成 MON、OSD 和 MDS 服务。下面是一个最简单的 CephCluster 配置示例,它指定了存储节点和设备过滤规则:
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
name: rook-ceph
namespace: rook-ceph
spec:
cephVersion:
image: quay.io/ceph/ceph:v18
dataDirHostPath: /var/lib/rook
mon:
count: 3
allowMultiplePerNode: false
storage:
useAllNodes: true
useAllDevices: false
deviceFilter: "^sd[b-d]$"
dashboard:
enabled: true
上述配置中 deviceFilter 用正则表达式选择节点上的裸盘,避免误用系统盘。dataDirHostPath 是宿主机上保存 Ceph 元数据与日志的路径,必须确保该目录存在且有足够空间。Operator 会根据设备过滤规则自动初始化 OSD,并在集群状态达到健康后把 CSI 驱动注册到 Kubernetes。
Rook 还负责创建 Ceph 的 admin 密钥和各个 CSI 组件需要的 secret。这些 secret 名称和命名空间需要与后续 StorageClass 中的参数保持一致。如果 CSI 插件无法连接 Ceph 集群,通常是 secret 中的 key 与集群实际密钥不匹配,或者节点插件没有权限访问 Rook 命名空间。
三、配置 StorageClass 和 PVC 实现动态供给
Ceph 集群部署完成后,下一步是创建 StorageClass。StorageClass 定义动态卷供给的模板,当用户提交 PVC 时,CSI provisioner 会读取 StorageClass 中的参数,自动在 Ceph 中创建 RBD 镜像或 CephFS 子卷。下面是一个 RBD 类型的 StorageClass:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rook-ceph-block provisioner: rook-ceph.rbd.csi.ceph.com parameters: clusterID: rook-ceph pool: replicapool imageFormat: "2" imageFeatures: layering csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph reclaimPolicy: Delete allowVolumeExpansion: true mountOptions: - discard
pool 参数指定 Ceph 中的 RBD 存储池,需要在创建 StorageClass 前提前建好。可以使用 Ceph 工具箱执行 ceph osd pool create replicapool 128 128 创建存储池,其中两个 128 分别表示 PG 和 PGP 数量。对于大多数中小集群,128 个归置组可以满足初期性能要求,更多的归置组会增加元数据开销。
PVC 的配置则相对简单。用户只需要指定访问模式、存储大小和 StorageClass 名称,Kubernetes 绑定过程会自动触发 CSI provisioner 创建卷。以下是一个申请 20Gi RBD 卷的示例:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: rook-ceph-block
resources:
requests:
storage: 20Gi
Pod 中通过 persistentVolumeClaim 引用这个 PVC,并把它挂载到数据库数据目录。对于数据库类工作负载,建议在 StorageClass 中设置 mountOptions: ["noatime","discard"] 来减少元数据写入并让块设备支持 TRIM。不过 mountOptions 需要节点上的文件系统支持,ext4 和 xfs 对 discard 的处理方式不同,实际使用时应在测试环境验证。
如果应用要求多个 Pod 同时读写同一个卷,则需要创建 CephFS 类型的 StorageClass,并把 provisioner 改为 rook-ceph.cephfs.csi.ceph.com。CephFS PVC 可以设置 ReadWriteMany,但要注意并发写入冲突由应用层自行协调,文件系统只保证数据一致性,不负责加锁语义。
四、常见故障排查与性能调优
把 Ceph 接入容器存储后,最容易出现的问题是 PVC 一直处于 Pending 状态。这通常说明 CSI provisioner 没有成功创建卷。可以先查看 rook-ceph 命名空间中的 CSI provisioner Pod 日志,确认它是否报出连接超时、认证失败或 pool 不存在。另一个常见原因是 StorageClass 中 secret 名称写错,导致 provisioner 无法通过 Ceph 认证。
节点挂载失败也是高频问题。RBD 卷挂载依赖节点上的 rbd 内核模块和 csi-rbdplugin 容器。可以登录节点执行 rbd device list 检查映射状态,或执行 dmesg | tail 查看内核日志。对于 CephFS,还需要确认 MDS 服务处于 active 状态,元数据池没有被写满。部分内核版本对 CephFS 的稳定支持有限,建议使用较新的长期支持内核。
性能调优方面,块存储场景可以关注 Ceph 存储池的归置组数量、对象大小和网络延迟。网络建议使用独立的存储网络,避免业务流量和复制流量互相影响。对于高并发随机写,可以把 RBD 的 imageFeatures 设置为 layering,exclusive-lock,object-map,fast-diff 来支持高级特性,但这些特性会增加少量元数据开销。CephFS 的 MDS 内存和 CPU 资源也需要根据客户端数量调整,默认配置在几十个 Pod 时通常足够,但扩展到数百个客户端后需要增加 MDS 数量或启用多活 MDS。
最后,不要把 Ceph 直接暴露到公网,容器集群和 Ceph 集群之间应使用私有网络或网络策略隔离。密钥文件要放入 Kubernetes Secret,避免硬编码在 Pod 配置中。定期检查集群健康状态、OSD 容量和 PG 状态,是保证容器存储长期稳定的基本动作。
Ceph容器存储Kubernetes CSI修改时间:2026-08-27 00:23:53