在 Kubernetes 环境中运行有状态服务时,如何为 Pod 提供稳定、可迁移且支持快照的块存储,是基础设施搭建的核心问题之一。Ceph RBD(RADOS Block Device)作为 Ceph 分布式存储系统对外提供的块存储接口,能够通过网络将块设备映射为节点上的本地盘,再由 Kubernetes 以标准 PVC 方式挂载给容器。这种方式既保留了 Ceph 的冗余与横向扩展能力,又契合容器平台对存储声明式管理的需求。

Ceph RBD 基础组件与存储准备
要让 Kubernetes 使用 Ceph RBD,首先需要在 Ceph 集群侧完成资源规划。Ceph 中的存储池(pool)是存放对象的逻辑容器,RBD 镜像(image)则是被虚拟出来的块设备,类似于云厂商的云硬盘。通常我们会创建一个专用池,例如叫 kube,并设置合适的副本数或纠删码规则,以保证在节点故障时数据不丢。之后通过 rbd create 命令生成指定大小的镜像,并开启 layering 等特性以便后续做快照和克隆。
除了镜像本身,鉴权也是不可忽略的一环。Ceph 使用 cephx 协议,每个客户端需要有对应的用户和密钥环(keyring)。在对接 Kubernetes 时,我们会新建一个用户如 client.kube,仅赋予对 kube 池的读写权限,然后将它的 key 抽取出来,稍后编码进 Kubernetes 的 Secret 中。这样做能遵循最小权限原则,避免容器平台拿到 Ceph 管理员权限从而引发安全风险。
下面是一段在 Ceph 节点上创建池与镜像并生成密钥的示例。注意命令中的池名和镜像名应根据实际环境调整,且 RBD 特性要兼顾内核客户端支持情况,例如某些老内核不支持 exclusive-lock 特性,需显式关闭。
# 创建存储池并开启 RBD 应用 ceph osd pool create kube 64 64 ceph osd pool application enable kube rbd # 初始化池为 RBD 用途 rbd pool init kube # 创建 10G 镜像,关闭新内核才支持的特性以兼容旧节点 rbd create kube/pvc-test --size 10G --image-feature layering # 生成专用用户并导出密钥 ceph auth get-or-create client.kube mon 'profile rbd' osd 'profile rbd pool=kube' ceph auth get-key client.kube > kube.key
Kubernetes 侧的 Secret 与 StorageClass 配置
完成 Ceph 侧准备后,要在 Kubernetes 中描述如何连接存储后端。早期社区提供过 in-tree 的 kubernetes.io/rbd 卷类型,但目前已废弃,主流方案是 Ceph CSI 驱动(ceph-csi-rbd)。无论哪种方式,核心配置都包含连接信息: monitors 地址、用户 ID、密钥,以及所使用的池和镜像特性。这些信息通过 Secret 对象保存,密钥内容需经过 base64 编码,防止明文落在 YAML 里。
StorageClass 则是动态供给的关键。它告诉 Kubernetes 当 Pod 申请 PVC 时,自动调用 CSI 插件在 Ceph 中创建 RBD 镜像,并格式化、挂载到节点。在 StorageClass 参数里,imageFeatures 必须和 Ceph 端镜像支持的特性匹配,比如只开 layering;csi.storage.k8s.io/fstype 可指定 ext4 或 xfs。此外,reclaimPolicy 决定 PVC 删除后后端镜像是否保留,生产环境常设为 Retain 以防误删数据。
以下示例展示了 Secret 与 StorageClass 的声明方式。其中 monitors 可以是多个 Ceph MON 的 IP 与端口,用逗号分隔;Secret 中的 key 字段来自前面导出的 kube.key 做 base64 后的结果。
apiVersion: v1 kind: Secret metadata: name: ceph-rbd-secret namespace: default type: kubernetes.io/rbd data: userID: Y2xpZW50Lmt1YmU= userKey: <base64_encoded_kube_key> encryptionKey: <base64_encoded_kube_key> --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: ceph-rbd-sc provisioner: rbd.csi.ceph.com parameters: clusterID: <ceph_fsid> pool: kube imageFeatures: layering csi.storage.k8s.io/fstype: ext4 csi.storage.k8s.io/provisioner-secret-name: ceph-rbd-secret csi.storage.k8s.io/node-publish-secret-name: ceph-rbd-secret reclaimPolicy: Retain allowVolumeExpansion: true
Pod 挂载流程与常见故障排查
当应用通过 PVC 使用 RBD 时,Kubernetes 控制平面会先由 CSI 控制器在 Ceph 中创建镜像,接着某个节点上的 kubelet 收到绑定通知,调用节点插件把 RBD 镜像映射到本地(如 /dev/rbd0),再格式化和 bind mount 进 Pod 的目录。整个过程依赖节点装有 rbd 命令与内核模块,或容器化的 node 插件能调用 librbd。如果节点缺模块,会出现 failed to map rbd image 之类报错。
另一个易错点是访问模式。RBD 本质上是单写多读的块设备,因此 Kubernetes 中它的 AccessModes 通常只支持 ReadWriteOnce 和 ReadOnlyMany,不能像 NFS 那样 ReadWriteMany。若强行在 PVC 里声明 RWM,PV 会一直处于 Pending。此外,Ceph 镜像特性若不兼容,也会导致 map 阶段失败,此时需在 Ceph 端用 rbd feature disable 关闭不支持的项。
排查时建议从三层入手:先看 PVC 和 PV 的 Events,确认是 provision 失败还是 attach 失败;再查节点上 rbd ls 与 dmesg | grep rbd 判断映射是否成功;最后核对 Secret 中 key 是否正确、MON 地址是否可达。下面代码演示了在节点手动映射镜像,用于验证底层连通性。
# 使用密钥手动映射镜像到本地块设备 rbd map kube/pvc-test --id client.kube --keyfile ./kube.key --monitors 192.168.0.1:6789 # 查看已映射设备 rbd showmapped # 若需卸载 rbd unmap /dev/rbd/kube/pvc-test
性能权衡与适用场景分析
Ceph RBD 走网络写入 RADOS 对象,延迟天然高于本地 SSD,但它带来的弹性与可靠性在多数有状态场景中物有所值。对于 MySQL、PostgreSQL 等数据库,RBD 配合 WriteBack 缓存与高速网络(如 25GbE 或 RDMA)可接近本地盘表现,同时获得跨节点漂移能力,节点维护时 Pod 能快速在另一台机器拉起并挂上同一块盘。
在快照与克隆方面,RBD 的 layering 特性允许基于快照秒级建克隆,适合 DevOps 中拉起测试库。相比之下,本地存储难以安全迁移,NFS 虽能共享但不保证块级一致性。如果业务是单纯日志或临时缓存,则用 emptyDir 或本地盘更经济。架构上建议将 Ceph 集群与 Kubernetes 计算节点放在同二层网络,减少路由跳数,并在 StorageClass 中开启 volumeBindingMode: WaitForFirstConsumer,让调度器选好节点后再 provision,避免镜像建在远端机房。
综合来看,Ceph RBD 对接 Kubernetes 并非简单改几个 YAML,而是涉及存储权限、内核兼容、挂载语义与网络规划的系统性工作。只有在理解 RADOS 与 CSI 交互边界的基础上,才能构建出既稳又快的容器持久化层。
Ceph_RBDKubernetes持久化存储修改时间:2026-08-18 14:36:41