本文已超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否已失效。

Kubernetes 1.23:防止乱序删除时发生 PersistentVolume 泄露

PersistentVolume (简称 PV) 与 回收策略 (Reclaim Policy) 相关联。回收策略用于确定在删除 PV 时存储后端需要执行的操作。如果回收策略是 Delete,则期望存储后端释放为该 PV 分配的存储资源。本质上,在删除 PV 时需要遵循回收策略。

随着近期 Kubernetes v1.23 版本的发布,一个 Alpha 特性允许您配置您的集群,使其以这种方式运行并遵循已配置的回收策略。

在之前的 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 及其 Bound 的 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 工具不会将控制权返回给 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 被删除了,但底层的存储资源并未被删除,需要手动移除。

总而言之,在某些情况下,与 Persistent Volume 相关联的回收策略目前会被忽略。对于已 Bound 的 PV-PVC 对,PV-PVC 删除的顺序决定了是否遵循 PV 回收策略。如果先删除 PVC,则会遵循回收策略;但是,如果在删除 PVC 之前删除 PV,则不会执行回收策略。这种行为导致外部基础设施中关联的存储资产未被移除。

Kubernetes v1.23 的 PV 回收策略

新的行为确保当用户手动删除 PV 时,底层存储对象会从后端删除。

如何启用新行为?

要使用新行为,您的集群必须已升级到 Kubernetes v1.23 版本。您需要确保正在运行 CSI external-provisioner 的版本 4.0.0 或更高版本。您还必须为 external-provisionerkube-controller-manager 启用 HonorPVReclaimPolicy 功能门 (feature gate)

如果您没有使用 CSI 驱动程序与存储后端集成,则此修复不可用。Kubernetes 项目目前没有针对树内存储驱动程序修复此 bug 的计划:这些树内驱动程序的未来是弃用并迁移到 CSI。

它是如何工作的?

新行为是通过在新建和现有的 PV 上添加一个终结器 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

终结器的存在阻止了 PV 对象从集群中移除。如前所述,只有在成功从存储后端删除后,终结器才会从 PV 对象中移除。要了解有关终结器的更多信息,请参阅使用终结器控制删除

CSI 迁移的存储卷怎么办?

此修复也适用于 CSI 迁移的存储卷。然而,当在 1.23 版本中启用 HonorPVReclaimPolicy 功能门并且禁用 CSI Migration 时,如果 PV 对象上存在终结器,则会被移除。

一些注意事项

  1. 此修复仅适用于 CSI 存储卷和迁移的存储卷。树内存储卷将表现出旧的行为。
  2. 此修复作为 Alpha 特性引入了 external-provisioner,位于功能门 HonorPVReclaimPolicy 下。该特性默认禁用,需要显式启用。

参考资料

如何参与贡献?

Kubernetes Slack 频道 SIG Storage 通信渠道 是联系 SIG Storage 和迁移工作组团队的好途径。

特别感谢以下人员的深入评审、周密考虑和宝贵贡献

  • Jan Šafránek (jsafrane)
  • 杨星 (xing-yang)
  • Matthew Wong (wongma7)

如果您有兴趣参与 CSI 或 Kubernetes 存储系统任何部分的设计和开发,请加入 Kubernetes 存储特别兴趣小组 (SIG Storage)。我们正在快速壮大,并且随时欢迎新的贡献者。