深色模式
K8s 存储体系总览:Volume、PV 与 PVC
摘要:本文面向生产 SRE / 平台工程师,梳理 Kubernetes 存储子系统的整体架构与核心抽象(Volume、PersistentVolume、PersistentVolumeClaim、StorageClass、CSI)。覆盖 v1.28+,讲清"为什么"和"边界",并给出系列文章的导航。后续 6 篇将分别深入绑定回收、StorageClass、CSI 选型、快照备份、排障与本地存储。
适用版本与前提
- Kubernetes:v1.28+(文内标注版本相关特性另述;卷快照 GA 见 v1.20+)
- 角色:集群管理员 / SRE,需具备
kubectl与 etcd 访问权限 - 前置:理解 Pod 生命周期、调度、CRD 基本概念
背景与问题
容器内的文件系统是临时的:容器崩溃重启后写入的数据会丢失,多容器/多 Pod 之间也无法直接共享磁盘。早期可以直接用 hostPath,但它把"节点机器上的路径"硬编码进 Pod,既不可移植,也没有生命周期管理。Kubernetes 因此需要一套把"存储如何实现"与"存储如何被消费"解耦的抽象。
核心矛盾在于:
- 用户只关心"我要 10Gi 的读写盘",不关心背后是 EBS、NFS 还是 Ceph;
- 管理员需要按性能等级、备份策略、成本来提供多种存储,但不应让用户感知底层细节。
Kubernetes 用三层抽象解决:Volume(使用侧)、PV/PVC(供给侧)、StorageClass(供给策略)。
核心概念与分层模型
各对象职责:
- Volume:Pod 级使用原语,声明"容器挂载什么、挂哪里"。可以是临时(
emptyDir)、配置(configMap/secret),也可以是持久化引用(persistentVolumeClaim、csi)。 - PersistentVolume (PV):集群级别的存储资源对象,生命周期独立于任何 Pod。它把"真实存储(NFS/EBS/Ceph…)"的实现细节封装起来。
- PersistentVolumeClaim (PVC):用户对存储的请求(规格 + 访问模式),类似 Pod 请求 CPU/Memory。PVC 消费 PV 资源。
- StorageClass (SC):管理员定义的"存储类别",描述供给器(provisioner)、参数、回收策略、绑定模式。它是动态供给的开关。
- CSI:Container Storage Interface,连接 Kubernetes 与第三方存储插件的统一标准;绝大多数现代存储走 CSI。
心智模型
Pod 消费 PVC,PVC 绑定 PV,PV 由 StorageClass 动态创建(或管理员静态预创建),底层由 CSI 驱动对接真实存储。把"请求—资源—策略—实现"四层分开,是 K8s 存储可扩展性的根基。
为什么这样设计(设计原则)
- 关注点分离:用户写 PVC 不碰后端;管理员用 StorageClass 统一供给策略。
- 多态供给:同一集群可提供"高速云盘""共享 NFS""分布式 Ceph"多档,用户在 PVC 里选 class 即可。
- 生命周期独立于 Pod:PV 不会随 Pod 销毁而删除,实现数据持久化。
- 标准化接口 (CSI):存储厂商只需实现一套 CSI 接口,Kubernetes 不必为每个后端写 in-tree 代码(旧 in-tree 插件如
awsElasticBlockStore已在 v1.27 移除,全面迁移到 CSI)。
生命周期关键节点
- Provisioning:静态(管理员建 PV)或动态(PVC 匹配 StorageClass 自动建 PV)。
- Binding:控制平面循环把 PVC 与匹配 PV 一对一绑定(
ClaimRef双向引用)。若无匹配 PV,PVC 永久Pending。 - Using:Pod 通过
persistentVolumeClaim卷类型挂载绑定后的 PV。 - Reclaiming:PVC 删除后,PV 按回收策略
Retain/Delete(Recycle已弃用)处理。 - Storage Object in Use Protection:PVC 正被 Pod 使用时删除会被延迟(
kubernetes.io/pvc-protectionfinalizer),PV 绑定 PVC 时删除同理(kubernetes.io/pv-protection),防止数据丢失。
版本相关
PV 删除保护 finalizer(external-provisioner.volume.kubernetes.io/finalizer 与 kubernetes.io/pv-controller)自 v1.31 引入,确保 Delete 策略的 PV 在后端存储真正删除后才移除对象。v1.33 起该特性默认开启且不可关闭。
访问模式(Access Modes)
| 模式 | 含义 | 典型后端 |
|---|---|---|
ReadWriteOnce (RWO) | 单节点读写 | 云盘、本地盘、RBD |
ReadOnlyMany (ROX) | 多节点只读 | NFS、CephFS |
ReadWriteMany (RWX) | 多节点读写 | NFS、CephFS、EFS |
ReadWriteOncePod (RWOP) | 单 Pod 读写(v1.22+) | 块设备 |
生产危险
RWO 卷只能挂在一个节点。节点故障后若卷仍"附着"在旧节点,新 Pod 在别的节点会报 Multi-Attach error 而无法启动。这是生产最频繁的存储事故之一,详见排障篇。
系列导航(后续 6 篇)
- PV/PVC 绑定与回收策略:生命周期、一对一绑定、Retain/Delete、保护 finalizer
- StorageClass 与动态供给:provisioner、volumeBindingMode、扩容
- 常见 CSI 驱动选型:EBS/阿里云盘/NFS/Rook-Ceph 厂商差异
- 快照与数据备份恢复:VolumeSnapshot GA、备份恢复、限制
- 持久化存储排障:PVC Pending、FailedAttachVolume、zone mismatch
- 本地存储与拓扑感知:local volume、local-static-provisioner、拓扑调度
边界与不适用
- 容器镜像层、未挂载的卷数据不持久;
emptyDir随 Pod 删除而丢失。 - 卷快照只保证"存储层"时间点副本,不保证应用一致性(数据库需先 quiesce/freeze),详见快照篇。
hostPath仅适合单节点开发/测试,生产应避开(无生命周期管理、无调度约束)。- 超大容量、超高 IOPS 场景需单独评估后端,K8s 抽象本身不提供性能保证。
常见坑
- PVC 忘了指
storageClassName会落到默认 class;想禁用动态供给必须显式storageClassName: ""。 - 删除 PVC 前务必确认回收策略;
Delete会连带删后端盘,数据库误删即数据灭失。 - PV/PVC 的
capacity与accessModes一旦创建基本不可改(扩容需allowVolumeExpansion)。
参考资料
- Kubernetes 官方文档 - Persistent Volumes,访问日期:2026-10-08。
- Kubernetes 官方文档 - Storage Classes,访问日期:2026-10-08。
- Kubernetes 官方文档 - Volumes (CSI),访问日期:2026-10-08。
- Kubernetes 官方文档 - Volume Snapshots,访问日期:2026-10-08。
- local-static-provisioner README (kubernetes-sigs),访问日期:2026-10-08。