Kubernetes 存储基础回顾:PV、PVC、StorageClass、VolumeSnapshotClass 的核心概念与关系

在深入 CSI 快照与拓扑回退演练之前,必须重新夯实 Kubernetes 存储的四个核心抽象:PV(PersistentVolume)、PVC(PersistentVolumeClaim)、StorageClass 以及 VolumeSnapshotClass。它们构成了从静态供给到动态供给、从普通卷到快照卷的完整声明式存储体系。

1. 核心概念定义

概念 缩写 API 版本(稳定) 核心职责
PersistentVolume PV v1 集群管理员预置或动态创建的存储资源,独立于 Pod 生命周期
PersistentVolumeClaim PVC v1 用户对存储的请求(大小、访问模式、存储类),绑定到 PV
StorageClass SC storage.k8s.io/v1 定义动态供给的“存储模板”,包含 Provisioner、参数、回收策略
VolumeSnapshotClass VSC snapshot.storage.k8s.io/v1 定义快照动态供给的“快照模板”,指定 CSI 快照驱动与参数
关键认知:PVC 是用户与存储之间的“声明层”,PV 是“资源层”,StorageClass 是“自动化工厂”,VolumeSnapshotClass 则是“快照工厂”。四者共同支撑起 Kubernetes 存储的声明式生命周期管理。

2. 核心关系:绑定、供给与生命周期

下图展示了 PV、PVC、StorageClass 之间的静态与动态供给关系,以及 VolumeSnapshotClass 在快照链路中的位置。

Kubernetes 存储核心抽象关系图 PV / PVC / StorageClass / VolumeSnapshotClass 关系图 用户 / 工作负载 PVC(声明) PV(资源) StorageClass VolumeSnapshotClass 后端存储(CSI) 快照存储目标 使用 绑定(match) 引用 storageClassName 动态供给 挂载/映射 创建快照 说明: PVC 通过 storageClassName 引用 StorageClass 实现动态供给;VolumeSnapshotClass 独立于 StorageClass,专用于快照的声明式创建与恢复。

3. 绑定与供给流程详解

Kubernetes 存储的绑定与供给遵循严格的声明式匹配逻辑,分为静态供给与动态供给两条路径。

3.1 静态供给流程

  1. 管理员预置 PV:手动创建 PV 对象,指定容量、访问模式、存储类型及后端连接信息。
  2. 用户创建 PVC:声明所需容量、访问模式,不指定 storageClassName 或指定为 ""(空字符串)。
  3. 控制平面匹配:Kubernetes 遍历所有 Available 状态的 PV,寻找满足 PVC 容量 >= 请求容量、访问模式兼容、StorageClass 一致的 PV。
  4. 绑定:匹配成功后,PVC 与 PV 进入 Bound 状态,PV 的 claimRef 指向 PVC。

3.2 动态供给流程

  1. 用户创建 PVC:声明容量、访问模式,并指定 storageClassName: "fast-storage"。
  2. 控制平面检测:发现 PVC 引用了 StorageClass,且该 StorageClass 的 provisioner 为 CSI 驱动。
  3. 调用 CSI Provisioner:根据 StorageClass 中的参数(如 type: pd-ssd、replication: 3)调用 CSI 驱动的 CreateVolume 接口。
  4. 创建 PV 并绑定:后端存储返回卷信息后,系统自动创建对应的 PV 对象,并与 PVC 完成绑定。
动态供给最佳实践:生产环境强烈建议使用动态供给。通过 StorageClass 的 allowVolumeExpansion: true 和 reclaimPolicy: Delete 实现存储的弹性伸缩与自动清理,避免手动管理 PV 带来的运维负担。

4. VolumeSnapshotClass 与快照生命周期

VolumeSnapshotClass 是 Kubernetes 1.20 起 GA 的快照管理核心抽象,其结构与 StorageClass 类似,但职责完全不同。

属性 StorageClass VolumeSnapshotClass
API 组 storage.k8s.io snapshot.storage.k8s.io
核心字段 provisioner, parameters, reclaimPolicy driver, deletionPolicy, parameters
驱动类型 CSI Provisioner(创建卷) CSI 快照驱动(创建/删除快照)
回收策略 Delete / Retain(针对 PV) Delete / Retain(针对 VolumeSnapshotContent)
绑定对象 PVC → PV VolumeSnapshot → VolumeSnapshotContent

VolumeSnapshotClass 的典型工作流程如下:

  1. 用户创建 VolumeSnapshot 对象,指定 volumeSnapshotClassName 和源 PVC。
  2. 控制平面根据 VolumeSnapshotClass 的 driver 字段找到对应的 CSI 快照驱动。
  3. 调用 CSI CreateSnapshot 接口,后端存储生成快照。
  4. 系统自动创建 VolumeSnapshotContent 对象(类似 PV 的角色),并与 VolumeSnapshot 绑定。
  5. 用户可通过 PVC 的 dataSource 字段引用 VolumeSnapshot,实现从快照恢复卷。
重要限制:VolumeSnapshotClass 与 StorageClass 是独立的资源。即使 StorageClass 支持动态供给,也不代表其对应的 CSI 驱动支持快照。必须确认 CSI 驱动实现了 CreateSnapshot / DeleteSnapshot 接口,并部署了对应的 VolumeSnapshotClass 对象。

5. 四者协作的完整声明式模型

下图从更高维度展示 PV、PVC、StorageClass、VolumeSnapshotClass 在 Kubernetes 声明式存储模型中的协作关系,突出“声明”与“资源”的分离。

声明式存储模型协作图 声明式存储模型:声明层 vs 资源层 声明层(用户视角) PVC(我要存储) VolumeSnapshot(我要快照) 引用 StorageClass 引用 VSC 资源层(集群视角) PV(存储资源) VSC(快照资源) CSI 后端存储 / 快照存储 绑定 绑定 核心原则: 用户只操作声明层(PVC / VolumeSnapshot),集群自动在资源层创建并绑定对应的 PV / VolumeSnapshotContent。StorageClass 和 VolumeSnapshotClass 是连接声明与资源的“工厂配置”。

6. 常见误区与避坑指南

  • 误区一:StorageClass 与 VolumeSnapshotClass 可以共用同一个 CSI 驱动。 正确:两者需要不同的 CSI 能力集,StorageClass 需要 CreateVolume,VolumeSnapshotClass 需要 CreateSnapshot。即使驱动相同,也必须分别创建对应的 Class 对象。
  • 误区二:PVC 绑定 PV 后无法修改 StorageClass。 正确:PVC 一旦创建,storageClassName 不可修改。如需迁移,需通过克隆或快照恢复的方式创建新 PVC。
  • 误区三:VolumeSnapshot 可以直接作为 Pod 的卷使用。 正确:VolumeSnapshot 不能直接挂载,必须通过 PVC 的 dataSource 字段恢复为新的 PV 后才能使用。
  • 误区四:动态供给的 PV 回收策略只能为 Delete。 正确:StorageClass 的 reclaimPolicy 可设置为 Retain,此时 PVC 删除后 PV 保留,需要管理员手动清理。