Kubernetes 1.31:防止无序删除时持久卷泄露
PersistentVolume(或简称 PV)与 回收策略 (Reclaim Policy) 相关联。回收策略用于确定存储后端在删除绑定到 PV 的 PVC 时需要执行的操作。当回收策略为 Delete
时,期望是存储后端释放为 PV 分配的存储资源。本质上,在删除 PV 时需要遵守回收策略。
随着最近发布的 Kubernetes v1.31 版本,一个 Beta 特性允许您配置集群以这种方式运行并遵守配置的回收策略。
在以前的 Kubernetes 版本中,回收是如何工作的?
PersistentVolumeClaim(或简称 PVC)是用户对存储的请求。如果找到了新创建的 PV 或匹配的 PV,则认为 PV 和 PVC 处于 绑定 (Bound) 状态。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
来实现。Finalizer 只会在后端存储被删除后移除。`
一个带有 Finalizer 的 PV 示例,注意 Finalizers 列表中的新 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
被添加到动态供应的 in-tree 插件卷上。
CSI 迁移的卷呢?
这个修复也适用于 CSI 迁移的卷。
一些注意事项
这个修复不适用于静态供应的 in-tree 插件卷。
参考资料
我如何参与?
Kubernetes Slack 频道和 SIG Storage 沟通渠道 是联系 SIG Storage 和迁移工作组的绝佳途径。
特别感谢以下人员的富有洞见的评审、周全的考虑和宝贵的贡献
- 范保发 (carlory)
- Jan Šafránek (jsafrane)
- 杨星 (xing-yang)
- Matthew Wong (wongma7)
如果您有兴趣参与 CSI 或 Kubernetes 存储系统的任何部分的设计和开发,请加入 Kubernetes 存储特别兴趣小组 (SIG)。我们发展迅速,随时欢迎新的贡献者。