Kubernetes 1.31:防止无序删除时 PersistentVolume 泄漏
PersistentVolume(简称 PV)
具有与之关联的回收策略。
回收策略用于确定在删除绑定到 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 删除的顺序决定了回收策略是否被执行。
如果 PVC 先被删除,则回收策略被执行;但如果在删除 PVC 之前 PV 被删除,
则回收策略不会被执行。因此,外部基础设施中关联的存储资产未被移除。
Kubernetes v1.31 的 PV 回收策略
新的行为确保当用户尝试手动删除 PV 时,下层存储对象会从后端被删除。
如何启用新的行为?
要利用新的行为,你必须将集群升级到 Kubernetes v1.31 版本,并运行
CSI external-provisioner
v5.0.1 或更高版本。
工作方式
对于 CSI 卷,新的行为是通过在新创建和现有的 PV 上添加
Finalizer
external-provisioner.volume.kubernetes.io/finalizer
来实现的。
只有在后端存储被删除后,Finalizer 才会被移除。
下面是一个带 Finalizer 的 PV 示例,请注意 Finalizer 列表中的新 Finalizer:
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
Finalizer 防止此 PersistentVolume 从集群中被移除。如前文所述,Finalizer 仅在从存储后端被成功删除后才会从 PV 对象中被移除。进一步了解 Finalizer, 请参阅使用 Finalizer 控制删除。
同样,Finalizer 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 Storage 系统任何部分的设计和开发,请加入 Kubernetes Storage SIG。 我们正在快速成长,始终欢迎新的贡献者。