本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 1.31:防止在乱序删除时出现 PersistentVolume 泄漏
PersistentVolume(简称 PV)与回收策略(Reclaim Policy)相关联。回收策略用于确定在删除与 PV 绑定的 PVC 时,存储后端需要采取的操作。当回收策略为 Delete
时,期望存储后端释放为 PV 分配的存储资源。本质上,回收策略需要在删除 PV 时得到遵守。
在最近发布的 Kubernetes v1.31 中,一个 Beta 功能可以让你配置集群以这种方式运行,并遵守所配置的回收策略。
在以前的 Kubernetes 版本中,回收是如何工作的?
PersistentVolumeClaim(简称 PVC)是用户对存储的请求。如果找到了一个新创建的 PV 或一个匹配的 PV,则认为 PV 和 PVC 是绑定的。PV 本身由存储后端分配的卷支持。
通常,如果要删除卷,期望的是删除已绑定的 PV-PVC 对中的 PVC。但是,并没有限制在删除 PVC 之前删除 PV。
首先,我将演示在运行旧版 Kubernetes 的集群上的行为。
检索一个与 PV 绑定的 PVC
检索一个现有的 PVC example-vanilla-block-pvc
kubectl get pvc example-vanilla-block-pvc
以下输出显示了 PVC 及其绑定的 PV;PV 显示在 VOLUME
列下
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
example-vanilla-block-pvc Bound pvc-6791fdd4-5fad-438e-a7fb-16410363e3da 5Gi RWO example-vanilla-block-sc 19s
删除 PV
当我尝试删除一个已绑定的 PV 时,kubectl 会话会阻塞,kubectl
工具不会将控制权返回给 shell;例如
kubectl delete pv pvc-6791fdd4-5fad-438e-a7fb-16410363e3da
persistentvolume "pvc-6791fdd4-5fad-438e-a7fb-16410363e3da" deleted
^C
检索 PV
kubectl get pv pvc-6791fdd4-5fad-438e-a7fb-16410363e3da
可以观察到 PV 处于 Terminating
状态
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-6791fdd4-5fad-438e-a7fb-16410363e3da 5Gi RWO Delete Terminating default/example-vanilla-block-pvc example-vanilla-block-sc 2m23s
删除 PVC
kubectl delete pvc example-vanilla-block-pvc
如果 PVC 成功删除,会看到以下输出
persistentvolumeclaim "example-vanilla-block-pvc" deleted
集群中的 PV 对象也会被删除。当尝试检索 PV 时,会发现 PV 不再存在
kubectl get pv pvc-6791fdd4-5fad-438e-a7fb-16410363e3da
Error from server (NotFound): persistentvolumes "pvc-6791fdd4-5fad-438e-a7fb-16410363e3da" not found
尽管 PV 被删除了,但底层的存储资源并未被删除,需要手动移除。
总而言之,在某些情况下,与 PersistentVolume 关联的回收策略当前被忽略。对于一个 Bound
状态的 PV-PVC 对,PV-PVC 的删除顺序决定了 PV 回收策略是否被遵守。如果先删除 PVC,回收策略会被遵守;然而,如果先于 PVC 删除 PV,回收策略则不会被执行。这种行为导致外部基础设施中关联的存储资产不会被移除。
Kubernetes v1.31 中的 PV 回收策略
新的行为确保了当用户尝试手动删除 PV 时,底层的存储对象会从后端被删除。
如何启用新行为?
要利用这一新行为,你必须将集群升级到 Kubernetes v1.31 版本,并运行 CSI external-provisioner
的 5.0.1
或更高版本。
它是如何工作的?
对于 CSI 卷,新行为通过在新的和现有的 PV 上添加一个终结器(finalizer) external-provisioner.volume.kubernetes.io/finalizer
来实现。只有在后端存储被删除后,这个终结器才会被移除。`
一个带有终结器的 PV 示例,注意终结器列表中的新终结器
kubectl get pv pvc-a7b7e3ba-f837-45ba-b243-dec7d8aaed53 -o yaml
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
pv.kubernetes.io/provisioned-by: csi.vsphere.vmware.com
creationTimestamp: "2021-11-17T19:28:56Z"
finalizers:
- kubernetes.io/pv-protection
- external-provisioner.volume.kubernetes.io/finalizer
name: pvc-a7b7e3ba-f837-45ba-b243-dec7d8aaed53
resourceVersion: "194711"
uid: 087f14f2-4157-4e95-8a70-8294b039d30e
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 1Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: example-vanilla-block-pvc
namespace: default
resourceVersion: "194677"
uid: a7b7e3ba-f837-45ba-b243-dec7d8aaed53
csi:
driver: csi.vsphere.vmware.com
fsType: ext4
volumeAttributes:
storage.kubernetes.io/csiProvisionerIdentity: 1637110610497-8081-csi.vsphere.vmware.com
type: vSphere CNS Block Volume
volumeHandle: 2dacf297-803f-4ccc-afc7-3d3c3f02051e
persistentVolumeReclaimPolicy: Delete
storageClassName: example-vanilla-block-sc
volumeMode: Filesystem
status:
phase: Bound
终结器可防止此 PersistentVolume 从集群中被移除。如前所述,只有在从存储后端成功删除 PV 对象后,终结器才会从该对象中移除。要了解有关终结器的更多信息,请参阅使用终结器控制删除。
类似地,终结器 kubernetes.io/pv-controller
会被添加到动态供应的树内插件卷中。
CSI 迁移的卷呢?
该修复也适用于 CSI 迁移的卷。
一些注意事项
此修复不适用于静态供应的树内插件卷。
参考资料
我如何参与?
Kubernetes Slack 频道 SIG Storage 通信渠道是联系 SIG Storage 和迁移工作组团队的绝佳媒介。
特别感谢以下人员的深刻见解、周详考虑和宝贵贡献
- Fan Baofa (carlory)
- Jan Šafránek (jsafrane)
- Xing Yang (xing-yang)
- Matthew Wong (wongma7)
如果你有兴趣参与 CSI 或 Kubernetes 存储系统任何部分的设计和开发,请加入 Kubernetes 存储特别兴趣小组 (SIG)。我们正在快速发展,并随时欢迎新的贡献者。