3. PersistentVolume 与 PersistentVolumeClaim:PV/PVC 解耦模型、静态供给与动态供给、StorageClass 入门

3.1 存储解耦的核心思想:从“硬编码”到“声明式绑定”

在 Kubernetes 出现之前,应用与存储的关系通常是“硬编码”的:开发者在配置文件中直接写入存储服务器的 IP、挂载路径或卷 ID。这种模式导致应用配置与基础设施强耦合,运维人员无法在不修改应用 YAML 的前提下更换存储后端或调整容量。

PV(PersistentVolume)与 PVC(PersistentVolumeClaim)的引入,将存储的“供给”与“消费”彻底分离:

  • PV:由集群管理员预先创建或通过 StorageClass 动态创建,代表一块真实的存储资源(如 NFS 导出、Ceph RBD 块设备、云磁盘)。
  • PVC:由应用开发者(或命名空间管理员)创建,描述对存储的需求(容量、访问模式、性能等级)。

Kubernetes 控制平面中的 PersistentVolumeController 负责将匹配的 PV 与 PVC 进行绑定,绑定完成后,Pod 即可通过 PVC 名称引用该存储。这种模型实现了“存储资源定义”与“存储使用声明”的解耦,使得应用 YAML 可以在不同集群间移植,而无需修改存储细节。

核心收益: 开发人员只需声明“我需要 10Gi 的读写一次存储”,运维人员则决定背后使用 NFS 还是云 SSD。双方通过 PV/PVC 契约达成协作,互不侵入。

3.2 PV 与 PVC 的生命周期与状态机

PV 和 PVC 各自拥有独立的状态机,理解这些状态是排查存储绑定问题的关键。

资源 状态 含义
PV Available 空闲,尚未被任何 PVC 绑定
Bound 已绑定到某个 PVC
Released 绑定的 PVC 已被删除,但 PV 尚未回收
Failed 自动回收失败
PVC Pending 尚未绑定到 PV(等待匹配或动态供给完成)
Bound 已绑定到某个 PV
Lost 绑定的 PV 丢失或删除

绑定过程遵循 匹配规则:PVC 中声明的 accessModes(ReadWriteOnce / ReadOnlyMany / ReadWriteMany)和 resources.requests.storage 必须与 PV 提供的属性兼容。此外,PVC 可以通过 selector 字段按标签精确匹配 PV,或通过 storageClassName 指定使用某个 StorageClass。

3.3 静态供给 vs 动态供给:两种供给模式对比

Kubernetes 支持两种 PV 供给方式,适用于不同的运维场景。

维度 静态供给(Static Provisioning) 动态供给(Dynamic Provisioning)
操作者 集群管理员手动创建 PV StorageClass 自动创建 PV
适用场景 已有外部存储(如 NFS、iSCSI)需要接入 云环境或支持 API 的存储后端(如 AWS EBS、GCE PD)
容量规划 需提前预分配,容易造成碎片或浪费 按需创建,PVC 删除后 PV 自动回收
运维复杂度 高,需手动管理 PV 生命周期 低,由 Provisioner 插件自动处理
绑定速度 取决于 PV 是否提前就绪 PVC 创建后即时触发创建
最佳实践: 生产环境推荐优先使用动态供给。仅在需要接入已有存储设备(如企业 NAS)或需要精细控制 PV 回收策略时,才使用静态供给。

3.4 StorageClass:动态供给的“配方”

StorageClass 是动态供给的核心抽象,它定义了如何创建 PV 的“模板”。每个 StorageClass 包含以下关键字段:

  • provisioner:指定存储后端插件,如 kubernetes.io/aws-ebs、kubernetes.io/gce-pd、nfs.csi.k8s.io。
  • parameters:传递给 provisioner 的配置参数,如 type: gp3、replication: 3。
  • reclaimPolicy:PV 被释放后的处理策略,可选 Delete(默认)或 Retain。
  • allowVolumeExpansion:是否允许后续扩容。
  • mountOptions:挂载时附加的选项。

以下是一个 AWS EBS 动态供给的 StorageClass 示例:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  fsType: ext4
  iopsPerGB: "10"
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer

当 PVC 引用 storageClassName: fast-ssd 时,Kubernetes 会调用 AWS EBS 的 API 自动创建一个 20Gi 的 gp3 卷,并生成对应的 PV 对象。整个过程无需管理员介入。

3.5 PV/PVC 绑定与使用流程(含 SVG 架构图)

下图展示了从 PVC 创建到 Pod 挂载的完整数据流,涵盖静态供给与动态供给两条路径:

PV/PVC 绑定与使用流程(静态供给 + 动态供给) 用户创建 PVC 声明容量、访问模式 PersistentVolumeController 检查 storageClassName 匹配已有 PV 按容量/访问模式匹配 调用 StorageClass Provisioner 创建 PV PV 状态 → Bound PVC 与 PV 绑定完成 Pod 引用 PVC 挂载到容器路径 关键说明 • 静态供给:PV 需提前创建 • 动态供给:PVC 触发 PV 创建 • 绑定后 PVC 不可更改 • Pod 通过 PVC 名称引用

3.6 回收策略与数据安全

当 PVC 被删除后,PV 的回收行为由 reclaimPolicy 决定:

  • Delete:自动删除底层存储资源(如云磁盘、Ceph RBD 镜像),数据不可恢复。适用于临时数据或可重建环境。
  • Retain:保留 PV 及其底层存储,PV 状态变为 Released。管理员可以手动恢复数据或重新使用该 PV。适用于需要数据保留的场景。
  • Recycle(已弃用):执行基础清理(如 rm -rf)后重新变为 Available。不推荐使用。
注意: 动态供给默认使用 Delete 策略。如果 PVC 被误删除,底层数据会立即丢失。对于有状态应用(如数据库),务必在 StorageClass 中设置 reclaimPolicy: Retain,或使用快照/备份机制。

3.7 访问模式与多节点共享

PV 的 accessModes 决定了存储可以被如何挂载:

访问模式 缩写 说明 典型后端
ReadWriteOnce RWO 单节点读写 云块存储(EBS、GCE PD)、Ceph RBD
ReadOnlyMany ROX 多节点只读 NFS、CephFS、GlusterFS
ReadWriteMany RWX 多节点读写 NFS、CephFS、Longhorn

PVC 在声明时必须指定至少一种访问模式,Kubernetes 会优先匹配完全一致的 PV。如果 PV 支持多种模式(如 NFS 同时支持 RWO 和 RWX),则 PVC 只需声明其中一种即可绑定。

3.8 本章小结

  • PV/PVC 解耦模型将存储资源定义与使用声明分离,是 Kubernetes 存储架构的基石。
  • 静态供给适合已有存储设备接入,动态供给通过 StorageClass 实现自动化,是云原生推荐方式。
  • StorageClass 是动态供给的“配方”,包含 provisioner、参数、回收策略等关键配置。
  • 理解 PV/PVC 状态机、回收策略和访问模式,是正确管理有状态工作负载的前提。