4. Kubernetes存储基础对接
在把 Rook Ceph 接入 Kubernetes 之前,必须先理清 Kubernetes 原生存储模型中的四个核心对象:PV(PersistentVolume)、PVC(PersistentVolumeClaim)、StorageClass 与 CSI 驱动。它们共同构成了一条从“应用声明需求”到“后端真正分配存储”的链路。Rook 并不是另起炉灶,而是通过 CSI 驱动把自己伪装成 Kubernetes 认可的存储供给方,从而无缝嵌入这条链路。
一、四个对象各自的职责
PV 是集群级别的存储资源对象,代表一块已经存在的、可供使用的存储卷。它记录容量、访问模式、回收策略以及后端的具体实现细节(例如 Ceph RBD 的 pool、image 名称)。PV 的生命周期独立于任何 Pod。
PVC 是命名空间级别的“存储申请单”。应用不直接引用 PV,而是声明自己需要多大容量、什么访问模式(ReadWriteOnce / ReadOnlyMany / ReadWriteMany),由 Kubernetes 负责匹配或创建对应的 PV。PVC 与 PV 是一对一绑定的关系。
StorageClass 描述“这类存储该怎么供给”。它包含 provisioner(由哪个驱动负责)、reclaimPolicy(删除 PVC 后卷如何处理)、volumeBindingMode(立即绑定还是等 Pod 调度后再绑定)以及一组 parameters。StorageClass 让用户不必手工创建 PV,只需在 PVC 中写 storageClassName 即可触发动态供给。
CSI 驱动是容器存储接口的实现,负责把 Kubernetes 的存储请求翻译成后端存储的实际操作。它通常以 DaemonSet(node 插件)加 Deployment(controller 插件)的形式运行,暴露 Identity、Controller、Node 三组 gRPC 服务。
二、静态供给与动态供给
静态供给是管理员预先创建 PV,用户再创建 PVC 去匹配。匹配依据是容量、访问模式、storageClassName 等字段。这种方式适合已有存储资源、需要精细控制的场景,但扩展性差。
动态供给则是用户只创建 PVC,Kubernetes 发现其 storageClassName 指向某个 StorageClass 后,调用该 StorageClass 的 provisioner(即 CSI 驱动)去后端创建卷,再自动生成 PV 并完成绑定。Rook 场景下几乎总是使用动态供给。
三、Rook 的集成方式
Rook 在部署 Ceph 集群后,会通过 CephBlockPool、CephFilesystem 等 CRD 创建存储池和文件系统,同时部署对应的 CSI 插件(RBD 与 CephFS 各一套)。随后 Rook 会创建名为 rook-ceph-block、rook-cephfs 之类的 StorageClass,其 provisioner 字段指向 rook-ceph.rbd.csi.ceph.com 或 rook-ceph.cephfs.csi.ceph.com。
当用户提交一个引用该 StorageClass 的 PVC 时,流程如下:PVC 被创建 → StorageClass 的 provisioner 被调用 → Rook CSI controller 在指定 pool 中创建 RBD image(或 CephFS subvolume)→ 返回卷信息 → Kubernetes 生成 PV 并绑定 PVC → Pod 挂载时,node 插件在节点上把该卷映射为块设备或挂载为文件系统。
四、关键参数与配置示例
下面是一个典型的 RBD 动态供给 PVC 示例,用于说明各字段如何与 Rook 对接:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data
namespace: default
spec:
storageClassName: rook-ceph-block
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
其中 storageClassName: rook-ceph-block 指向 Rook 创建的 StorageClass。该 StorageClass 的 provisioner 为 rook-ceph.rbd.csi.ceph.com,parameters 中通常包含 clusterID、pool、imageFormat、imageFeatures 等。例如 pool: replicapool 表示卷创建在名为 replicapool 的 Ceph 池中;imageFeatures: layering 表示启用 RBD 分层特性。
访问模式需要与后端能力匹配:RBD 通常支持 ReadWriteOnce 和 ReadOnlyMany,CephFS 支持 ReadWriteMany。如果应用需要多 Pod 同时读写同一卷,应选择 CephFS 对应的 StorageClass。
五、结果观察与判断
PVC 创建后,可用 kubectl get pvc 观察状态。正常流程会从 Pending 变为 Bound。若长时间 Pending,常见原因包括:StorageClass 不存在、provisioner 未就绪、Ceph 集群健康异常、pool 不存在或权限不足。此时可查看 CSI controller 日志:
kubectl -n rook-ceph logs deploy/csi-rbdplugin-provisioner -c csi-provisioner
绑定成功后,kubectl get pv 会看到自动生成的 PV,其 claimRef 指向对应 PVC。Pod 启动后,可通过 kubectl exec 进入容器执行 df -h 或 mount | grep rbd 确认卷已挂载。删除 PVC 时,若 reclaimPolicy 为 Delete,PV 与后端 RBD image 会被一并清理;若为 Retain,则保留后端数据供人工处理。
理解这条链路后,后续排查存储问题就有了清晰的切入点:先看 PVC 状态,再看 StorageClass 与 provisioner,最后看 CSI 日志与 Ceph 集群健康。Rook 的价值在于把 Ceph 的复杂运维封装为 Kubernetes 原生对象,让存储供给像创建 Pod 一样自然。