本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

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-provisioner5.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)。我们正在快速发展,并随时欢迎新的贡献者。