PVC 是怎么找到 PV 的?为什么有的 PVC 一直 Pending?PVC 删了数据去哪了?这篇先用手工建的静态 PV 把配对规则逐条验证,再看动态供给的 WaitForFirstConsumer 和 Delete 回收策略。
三个 PV(存储类 manual,RWO):pv-10g=10Gi/Available; pv-2g=2Gi/Available; pv-5g=5Gi/Available PVC c3g 请求 3Gi:phase=Bound;绑定到 k51-pv-5g(容量 5Gi);pv-10g=10Gi/Available; pv-2g=2Gi/Available; pv-5g=5Gi/Bound→c3g PVC c20g 请求 20Gi(没有这么大的 PV):phase=Pending;事件:['storageclass.storage.k8s.io "manual" not found'] PVC crwx 请求 RWX(现有 PV 都只有 RWO):phase=Pending PVC cclass 的 storageClassName 是 other(PV 都是 manual):phase=Pending 现在加一个 RWX 的 PV 之后 7.4 秒:crwx phase=Bound → k51-pv-rwx(Pending 的 PVC 在有匹配的 PV 出现后自动绑定,PV 控制器是周期性同步的,所以有延迟)
PV 控制器把 PVC 和 PV 配对看四件事:容量够、访问模式够、storageClassName 相同、(如果写了)selector 匹配。三个 PV 2Gi/5Gi/10Gi,请求 3Gi 的 PVC 拿到 5Gi 的——候选里最小的。请求 20Gi、ReadWriteMany(现有 PV 只有 RWO)或不同存储类的 PVC 都保持 Pending;新增一个匹配的 PV 之后 7.4 秒,Pending 的 PVC 自动绑上去(PV 控制器是周期性同步的)。
PVC want-gold(selector tier=gold):绑定 k51-pv-labeled PVC plain-small(没有 selector,请求 1Gi):绑定 k51-pv-2g PV k51-pv-reserved 预先写了 claimRef(只给 k51/reserved-for-me),此时集群里没有别的可用 PV:另一个 PVC someone-else 请求 500Mi → phase=Pending(PV 被预留了,别人拿不走);pv-reserved=1Gi/Available→reserved-for-me PVC reserved-for-me 请求 500Mi → phase=Bound k51-pv-reserved
PVC 的 selector.matchLabels 只选带这些标签的 PV(tier=gold 的那个);没有 selector 的 1Gi PVC 拿了 2Gi 的最小 PV。PV 上可以预先写 claimRef,把它只留给指定的 PVC:集群里别的 PV 都用掉后,另一个 PVC 想要它,保持 Pending;预留的 PVC 一创建就绑定。
persistentVolumeReclaimPolicy=Retain 的静态 PV:删除 PVC 之后 phase=Released;spec.claimRef 还在:c1(数据和绑定记录都保留着) 新建 PVC c2(1Gi):phase=Pending(Released 的 PV 不会被别人拿去用) 手动去掉 PV 的 claimRef 之后 4.5 秒:c2 phase=Bound;PV phase=Bound(Released → Available → Bound)
persistentVolumeReclaimPolicy: Retain 的静态 PV,删掉 PVC 后变成 Released,spec.claimRef 还指着已不存在的 PVC——数据和绑定记录都保留,新 PVC 拿不走它(c2 一直 Pending)。要重新使用得手动把 claimRef 去掉,4.5 秒后 c2 就绑定了。动态供给的 StorageClass 默认是 Delete:PVC 一删,PV 和底层数据都没了。
动态供给的 StorageClass standard:reclaimPolicy=Delete volumeBindingMode=WaitForFirstConsumer provisioner=rancher.io/local-path 动态 PVC dyn 创建后立刻 phase=Pending(WaitForFirstConsumer:没有 Pod 用它就不供给);事件:['WaitForFirstConsumer: waiting for first consumer to be created before binding'] 创建用它的 Pod 之后:dyn phase=Bound,自动创建了 PV pvc-7e8d30e7-d16…,所在节点 ['kx-sched-worker3'] 删除 PVC dyn 之后:PV pvc-7e8d30e7-d16… 还在吗:False(reclaimPolicy=Delete:PV 随 PVC 一起被删除)
kind 的 standard 存储类用 rancher.io/local-path、volumeBindingMode: WaitForFirstConsumer:PVC 创建后保持 Pending,事件 waiting for first consumer to be created before binding;创建了使用它的 Pod 之后才供给——自动建出的 PV 带节点亲和,落在 Pod 被调度到的那个节点上(worker3);之后 Pod 只能回到这个节点。删除 PVC,PV 随之被删除(reclaimPolicy: Delete)。