2. Kubernetes 存储基础:PV、PVC、StorageClass、CSI 驱动原理回顾

在深入 Rook Ceph 与 Velero 协同方案之前,必须重新夯实 Kubernetes 存储的核心抽象层。PV(PersistentVolume)、PVC(PersistentVolumeClaim)、StorageClass 与 CSI(Container Storage Interface)共同构成了声明式存储供给与消费的完整链路。理解这四层的关系,是后续拓扑设计与故障恢复剧本的前提。

2.1 四层抽象模型与数据流

Kubernetes 将存储的供给与消费彻底解耦:集群管理员负责 PV(存储资源),应用开发者负责 PVC(存储需求),StorageClass 提供动态供给模板,CSI 驱动则作为真正的存储操作执行层。下图展示了从 PVC 创建到 Pod 挂载的完整数据流。

Kubernetes 存储四层模型与数据流 Kubernetes 存储四层模型与数据流 用户 / 应用 定义存储需求 PVC 存储资源请求 PV / StorageClass 静态供给 / 动态供给模板 绑定与供给策略 CSI 驱动 实际存储操作执行层 后端存储 Ceph RBD / NFS / 云盘 挂载路径 / 设备映射 核心流程: 用户创建 PVC → Kubernetes 控制面查找匹配 PV 或触发 StorageClass 动态供给 → CSI 驱动调用后端存储接口 → 返回挂载信息 → Pod 挂载使用。

2.2 核心概念对比

下表从定义、生命周期、创建者、访问模式四个维度对比 PV、PVC、StorageClass 与 CSI 驱动,帮助运维人员快速区分职责边界。

概念 定义 生命周期 创建者 访问模式示例
PV 集群中的存储资源卷,独立于 Pod 存在 由管理员创建,直到被删除或回收策略生效 集群管理员 ReadWriteOnce / ReadOnlyMany / ReadWriteMany
PVC 用户对存储资源的请求声明(大小、访问模式) 与 Pod 生命周期绑定,Pod 删除后 PVC 可保留 应用开发者 与匹配的 PV 一致
StorageClass 动态供给的模板,定义存储类型、参数、回收策略 集群级资源,长期存在 集群管理员 由 provisioner 决定
CSI 驱动 实现 CSI 接口的插件,负责实际存储操作 以 DaemonSet + Controller 形式运行 集群管理员 / 云厂商 由后端存储决定

2.3 PVC 与 PV 的绑定机制

PVC 与 PV 的绑定遵循精确匹配与容量优先原则。当 PVC 创建后,Kubernetes 控制面会遍历集群中所有可用 PV,筛选出满足以下条件的 PV:

  • 容量匹配:PV 的容量必须大于或等于 PVC 请求的容量。
  • 访问模式匹配:PV 的访问模式必须包含 PVC 请求的模式。
  • StorageClass 匹配:如果 PVC 指定了 StorageClass,PV 的 StorageClass 必须一致;未指定时只匹配未设置 StorageClass 的 PV。
  • 标签选择器:如果 PVC 定义了 selector,PV 的标签必须完全匹配。

运维要点: 绑定是独占的——一个 PV 同一时间只能绑定一个 PVC。绑定后 PV 的状态从 Available 变为 Bound。如果 PVC 被删除,PV 的回收策略(Retain / Delete / Recycle)决定后续行为。在 Rook Ceph 场景中,推荐使用 Retain 策略防止数据被意外清理。

2.4 StorageClass 动态供给原理

StorageClass 使得 PVC 无需预先创建 PV,而是由集群按需自动生成。其核心字段包括:

字段 说明 Rook Ceph 典型值
provisioner 指定 CSI 驱动的名称 rook-ceph.rbd.csi.ceph.com
parameters 传递给 CSI 驱动的参数,如池名称、文件系统类型 clusterID: rook-ceph / pool: replicapool
reclaimPolicy PVC 删除后 PV 的处理方式 Retain 或 Delete
allowVolumeExpansion 是否允许在线扩容 true
mountOptions 挂载时附加的选项 discard / noatime

动态供给的触发流程如下:

  1. 用户创建 PVC 并指定 storageClassName。
  2. Kubernetes 控制面找到对应的 StorageClass 对象。
  3. 调用 StorageClass 中定义的 provisioner(即 CSI 驱动控制器)。
  4. CSI 驱动调用后端存储接口创建卷(如 Ceph RBD 镜像)。
  5. 生成的 PV 自动与 PVC 绑定,状态变为 Bound。

最佳实践: 在 Rook Ceph 环境中,建议为不同性能需求(如 SSD 池、HDD 池、EC 池)分别创建独立的 StorageClass,并通过 PVC 的 storageClassName 字段选择。这可以在不修改应用 YAML 的前提下灵活切换存储后端。

2.5 CSI 驱动架构与操作流程

CSI 驱动是 Kubernetes 存储生态的标准化插件接口。一个完整的 CSI 驱动包含三个核心组件:

  • Controller Plugin:以 Deployment 形式运行,负责卷的创建、删除、快照、扩容等控制面操作。
  • Node Plugin:以 DaemonSet 形式运行在每个节点上,负责卷的挂载、格式化、卸载等数据面操作。
  • Sidecar 容器:与 CSI 驱动容器同 Pod 运行,负责将 Kubernetes 的存储请求转换为 CSI 标准 gRPC 调用。

下图展示了 CSI 驱动在 Kubernetes 集群中的部署架构与调用链路。

CSI 驱动架构与调用链路 CSI 驱动架构与调用链路 Kubernetes 控制面 API Server / Controller Manager 监听 PVC / StorageClass 事件 CSI Controller Plugin Deployment (1 副本) CreateVolume / DeleteVolume / Snapshot 后端存储 Ceph / 云盘 Kubelet (节点) 触发 NodePublishVolume 管理 Pod 挂载路径 CSI Node Plugin DaemonSet (每节点) NodeStageVolume / NodePublishVolume Pod 挂载点 /var/lib/kubelet/pods/... 关键调用链路: 1. PVC 创建 → 控制面调用 CSI Controller → CreateVolume → 后端存储创建卷。 2. Pod 调度到节点 → Kubelet 调用 CSI Node → NodeStageVolume(格式化/挂载)→ NodePublishVolume(绑定到 Pod 命名空间)。 3. 所有 CSI 调用通过 Unix Socket 在 Sidecar 与 CSI 驱动之间传递。

2.6 常见运维场景与避坑指南

常见陷阱:

  • PVC 一直 Pending:检查 StorageClass 是否存在、provisioner 是否正确、后端存储池是否有剩余容量。使用 kubectl describe pvc <name> 查看事件。
  • PV 回收策略误配:如果使用 Delete 策略,PVC 删除后 PV 和后端卷会被直接删除,数据不可恢复。生产环境建议统一使用 Retain。
  • CSI 驱动版本不匹配:Rook Ceph 的 CSI 驱动版本必须与 Kubernetes 版本兼容,否则可能出现挂载超时或卷操作失败。
  • 节点重启后挂载丢失:检查 CSI Node Plugin 是否正常运行,以及 /var/lib/kubelet/plugins 目录下的 CSI socket 文件是否存在。

2.7 本章小结