深色模式
PV/PVC 绑定机制与回收策略
摘要:本文面向集群管理员与 SRE,拆解 PV 与 PVC 从供给、绑定到回收的完整生命周期,重点讲清"为什么是一对一绑定""Retain 与 Delete 的事故差异""PVC/PV 删除保护如何防止误删数据",并给出可落地的生产实践与回滚方案。适用 Kubernetes v1.28+。
适用版本与前提
- Kubernetes:v1.28+(删除保护 finalizer 自 v1.31 引入,见下文)
- 工具:
kubectl - 前提:已理解 存储总览 的分层模型
背景与问题
PVC 是用户对存储的请求,PV 是集群中真实存在的存储资源。二者之间靠"绑定"建立 1:1 关系。理解绑定与回收,是避免误删数据和**盘泄漏(orphan)**这两类生产事故的前提:
Delete策略下,删 PVC 会连同后端盘一起删除——一次误删可能毁掉数据库。Retain策略下,删 PVC 后 PV 进入Released但后端盘不删——若无人回收,存储资产长期泄漏、容量被占。
生命周期总览
核心概念
供给(Provisioning)
- 静态:管理员预先创建若干 PV,携带真实存储细节,等待被消费。
- 动态:没有匹配的静态 PV 时,控制平面依据 PVC 请求的 StorageClass 自动创建 PV(要求
DefaultStorageClassadmission 插件开启,且 class 已配置 provisioner)。
yaml
# 静态 PV 示例(NFS 后端)
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-01
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs-retain
nfs:
server: 10.0.0.10
path: /export/data
mountOptions:
- nfsvers=4.11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
绑定(Binding)
控制平面中的循环监听新 PVC,寻找满足访问模式、容量、storageClassName 的 PV 并绑定。ClaimRef 是 PV 与 PVC 之间的双向引用,绑定是排他的、一对一。
绑定规则
- PVC 请求 100Gi,但集群只有 50Gi 的 PV,则 PVC 永久
Pending,直到出现 ≥100Gi 的 PV。 - PVC 实际得到的容量"至少等于"请求值,可能大于(匹配到更大的 PV)。
- 想让 PVC 绑定到指定 PV,可在 PVC 中设
spec.volumeName。若 PV 存在且未被其他 PVC 占用(claimRef为空),则强制绑定,绕过部分匹配校验(仍校验 class、访问模式、容量合法性)。
预绑定示例
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: foo-pvc
namespace: foo
spec:
storageClassName: "" # 必须显式置空,否则会自动套用默认 StorageClass
volumeName: foo-pv # 强制绑定到指定 PV
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
回收策略(Reclaim Policy)
| 策略 | 行为 | 适用场景 |
|---|---|---|
Retain | 删 PVC 后 PV 变 Released,后端盘保留,需管理员手动清理复用 | 生产数据库、不可重建数据 |
Delete | 删 PVC 同时删 PV 对象与后端存储资产 | 临时/可重建数据,动态供给默认 |
Recycle | 已弃用,不推荐使用 | — |
生产危险
动态供给创建的 PV 默认继承 StorageClass 的回收策略,而 StorageClass 默认 Delete。这意味着删一个数据库 PVC,后端云盘会被立即删除且不可恢复。生产有状态服务务必使用 Retain 或将 StorageClass reclaimPolicy: Retain,并在删除前先快照。
Retain 手动回收步骤
- 删除 PVC(
kubectl delete pvc <name>),PV 进入Released; - 删 PV 对象(
kubectl delete pv <name>),后端资产仍在; - 登录存储后端手动清理数据;
- 如需复用,用相同后端定义重建 PV。
版本相关
Reclaim 的 Released PV 无法直接被新 PVC 复用——因 claimRef 仍指向旧 PVC。需手动 kubectl patch pv <name> --type json -p '[{"op":"remove","path":"/spec/claimRef"}]' 清除旧引用后才能重新绑定。这是 Retain 模式下常见的"盘显示存在却绑不上"根因。
Storage Object in Use Protection
PVC 正被 Pod 使用时删除、或 PV 正绑定 PVC 时删除,Kubernetes 不会立即执行,而是加上 finalizer 延迟删除:
- PVC 被保护时状态为
Terminating,finalizer 含kubernetes.io/pvc-protection; - PV 被保护时 finalizer 含
kubernetes.io/pv-protection。
这避免了"Pod 还在写,盘先被删"导致的数据损坏。
PV 删除保护 finalizer(v1.31+)
为彻底保证 Delete 策略安全,v1.31 起给 PV 加了两个 finalizer:
external-provisioner.volume.kubernetes.io/finalizer:CSI 卷(动态/静态均加);kubernetes.io/pv-controller:动态供给的 in-tree 插件卷。
它们确保先删后端存储、再删 PV 对象,且无论 PV/PVC 删除顺序如何都能正确清理。v1.33 起该特性稳定且无法关闭。
生产实践
- 有状态服务(数据库):StorageClass 设
Retain,删除流程 = 先快照 → 再删 PVC;严禁直接kubectl delete pvc数据库。 - 临时/构建缓存:可用
Delete省成本,但务必确认数据可重建。 - 容量规划:PV 容量创建后不可缩小;扩容需 StorageClass 开
allowVolumeExpansion(见 StorageClass 篇)。 - 命名与租户:用
storageClassName区分"黄金/标准/廉价"档位,配合 ResourceQuota 限制 namespace 的 PVC 数量与总量。
验证
bash
kubectl get pv
kubectl get pvc -n <ns>
kubectl describe pvc <name> # 查看 Events:等待绑定/已绑定/不匹配原因
kubectl describe pv <name> # 查看 Finalizers、ClaimRef、Reclaim Policy1
2
3
4
2
3
4
回滚与清理
生产危险
以下命令会删除 PVC/PV,可能连带删除后端存储。执行前必须确认 namespace、回收策略,并已完成快照备份。
bash
# 查看即将删除对象的回收策略,确认不会误删后端盘
kubectl get pv <pv-name> -o jsonpath='{.spec.persistentVolumeReclaimPolicy}'
# 安全删除:先快照(见快照篇),再删 PVC
kubectl delete pvc <pvc-name> -n <ns>
# 若 PV 卡在 Terminating,检查 finalizer 是否被外部控制器持有
kubectl get pv <pv-name> -o json | jq '.metadata.finalizers'1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
故障排查
- PVC 永久 Pending:
describe pvc看 Events,通常是无匹配 PV(容量/访问模式/class 不符)或动态供给未配置。 - PV 卡 Released 不可复用:清除
spec.claimRef(见上文 warning)。 - 删除 PVC 后盘未释放:检查 finalizer、
Retain策略、或后端 API 限流。
常见坑
- 想关动态供给却只把
storageClassName留空字符串忘了在 PVC 显式声明"",会被默认 class 接管。 Retain+ 不复用 = 存储泄漏,需建立回收巡检(Prometheus 报警 + 定期清理脚本)。- 删 PVC 前不确认回收策略,是生产数据事故头号原因。
参考资料
- Kubernetes 官方文档 - Persistent Volumes,访问日期:2026-10-08。
- Kubernetes 官方文档 - Storage Classes(reclaimPolicy),访问日期:2026-10-08。
- Kubernetes 官方文档 - Volume Snapshots,访问日期:2026-10-08。