已释放的持久化卷应该怎么处理?

73

简述:我不知道在删除PVC之后如何访问数据,也不知道为什么删除了PVC后PV还存在。

我进行的步骤:

  1. 手动在GCE创建了一块磁盘:

gcloud compute disks create --size 5Gi disk-for-rabbitmq --zone europe-west1-b
ran
kubectl apply -f /tmp/pv-and-pvc.yaml

使用以下配置:

# /tmp/pv-and-pvc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-for-rabbitmq
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 5Gi
  gcePersistentDisk:
    fsType: ext4
    pdName: disk-for-rabbitmq
  persistentVolumeReclaimPolicy: Delete
  storageClassName: standard
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-for-rabbitmq
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: standard
  volumeName: pv-for-rabbitmq
  • 手动删除了一个PVC(在高层次上:我在这里模拟一个灾难性的场景,比如意外删除或误配置了一个helm发布):

  • kubectl delete pvc pvc-for-rabbitmq
    
    此时我看到以下内容:

    目前我看到以下内容:

    $ kubectl get pv
    NAME              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                      STORAGECLASS   REASON   AGE
    pv-for-rabbitmq   5Gi        RWO            Delete           Released   staging/pvc-for-rabbitmq   standard                8m
    $
    

    一个旁问,只是为了帮助我理解:即使PV设置了回收策略为Delete,为什么它仍然存在?这不是文档中针对Delete回收策略所说的吗?

    现在如果我尝试重新创建PVC以重新访问PV中的数据:

    $ kubectl apply -f /tmp/pv-and-pvc.yaml
    persistentvolume "pv-for-rabbitmq" configured
    persistentvolumeclaim "pvc-for-rabbitmq" created
    $
    

    我仍然会遇到此类问题,例如PV被卡在“Released”状态中:

    $
    kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                             STORAGECLASS   REASON    AGE
    pv-for-rabbitmq                            5Gi        RWO            Delete           Released   staging/pvc-for-rabbitmq          standard                 15m
    $
    

    ......而我的pvc是这样的:

    $
    kubectl get pvc
    NAME               STATUS    VOLUME            CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pvc-for-rabbitmq   Pending   pv-for-rabbitmq   0                         standard       1m
    $
    

    看起来我的PV处于“已发布”状态,PVC无法访问处于“可用”状态之外的PV。

    那么,为什么同样的PV和PVC不能再次成为朋友呢?我该如何使PVC重新访问现有PV中的数据?


    5
    Kubernetes没有显示如何将你的持久化卷(PV)从“已释放”更改为“可用”,这真的很烦人。如果使用动态供应,情况甚至更糟。 - okandas
    7个回答

    106
    kubectl patch pv pv-for-rabbitmq -p '{"spec":{"claimRef": null}}'
    

    这对我很有效。


    1
    是的,这个方法可行。由于控制台删除无法工作,我接着使用了“kubectl delete -f storage.yml”命令。 - mikelus
    12
    更多关于此的解释,来自 Kubernetes 文档:从 PV 规范中删除 claimRef 条目,以便新的 PVC 可以绑定到它上面。这应该使 PV 可用。 - Micaël Félix
    如此简单,却如此有效。 - bischoje
    1
    当发生 PVC/PV 绑定时,它会更新 PV 的 .spec.claimRef 部分。您可以使用 k get pv pv-name -o jsonpath="{.spec.claimRef}" 来检查此内容。通过将其补丁为 null,意味着擦除此绑定并使其可用。 - P....
    非常好,已修补完成。 执行后, 持久卷/pv名称已修补, 并且Pod状态变为正常。非常感谢。 - Praveen Danagoudru
    显示剩余5条评论

    8
    官方PV文档中有这个答案: Retain 回收策略允许手动回收资源。当删除 PersistentVolumeClaim 时,PersistentVolume 仍然存在,卷被视为“已释放”。但是,由于先前的申请者数据仍然存在于卷上,因此尚不可用于另一个申请。管理员可以通过以下步骤手动回收卷。
    1. 删除 PersistentVolume。在删除 PV 后,与之关联的外部基础设施中的存储资产(例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)仍然存在。
    2. 手动[复制/备份和/或]清理与之关联的存储资产上的数据。
    3. 手动删除关联的存储资产,或者如果要重用相同的存储资产,则创建一个新的 PersistentVolume 并使用存储资产定义。

    5

    这句话的意思是,Pods消耗节点资源,而PVCs消耗PV资源,理解PV和PVC之间的关系可以帮助我们更好地理解这个概念。

    我尝试使用提供的YAML文件完全复制所述的行为,但失败了,并返回了预期的结果。因此,在提供任何进一步的细节之前,以下是我的复制步骤。

    步骤1:在欧洲西部1区创建了PD。

    sunny@dev-lab:~$ gcloud compute disks create --size 5Gi disk-for-rabbitmq --zone europe-west1-b
    
    WARNING: You have selected a disk size of under [200GB]. This may result in poor I/O 
    performance. For more information, see: 
    
    NAME               ZONE            SIZE_GB  TYPE         STATUS
    disk-for-rabbitmq  europe-west1-b  5        pd-standard  READY
    

    步骤2:使用项目YAML文件创建PV和PVC

    sunny@dev-lab:~$  kubectl apply -f pv-and-pvc.yaml
    
    persistentvolume "pv-for-rabbitmq" created
    persistentvolumeclaim "pvc-for-rabbitmq" created
    

    第三步:列出所有可用的PVC
    sunny@dev-lab:~$ kubectl get pvc
    NAME               STATUS    VOLUME            CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pvc-for-rabbitmq   Bound     pv-for-rabbitmq   5Gi        RWO            standard       16s
    

    步骤 4:列出所有可用的 PV

    sunny@dev-lab:~$ kubectl get pv
    NAME              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                      STORAGECLASS   REASON    AGE
    pv-for-rabbitmq   5Gi        RWO            Delete           Bound     default/pvc-for-rabbitmq   standard                 28s
    

    步骤 5:删除 PVC 并验证结果

    sunny@dev-lab:~$  kubectl delete pvc pvc-for-rabbitmq
    persistentvolumeclaim "pvc-for-rabbitmq" deleted
    
    sunny@dev-lab:~$  kubectl get pv
    

    没有找到资源。
    sunny@dev-lab:~$  kubectl get pvc
    

    没有找到资源。
    sunny@dev-lab:~$  kubectl describe pvc-for-rabbitmq
    

    服务器上没有资源类型为 "pvc-for-rabbitmq"

    根据你的问题

    一个旁边的问题,只是为了提高我的理解:即使设置了 Delete 回收策略,为什么 PV 仍然存在?这不是 docs 对于 Delete 回收策略所说的吗?

    你是完全正确的,根据文档,当用户完成卷的使用后,可以从 API 中删除 PVC 对象,以允许资源回收。持久卷的回收策略告诉集群在释放其声明后如何处理该卷。在您的 YAML 中,它被设置为:

    Reclaim Policy:  Delete
    

    这意味着应该立即删除它。目前,存储卷只能被保留、回收或删除。

    为什么没有被删除? 我唯一想到的可能是 PV 仍然被认领,这很可能是由于 PVC 未成功删除导致的,因为其容量显示为 "0",要解决此问题,您需要删除 POD。或者,您可以使用 $ kubectl describe pvc 命令查看为什么 PVC 仍处于挂起状态。

    至于问题,如何使 PVC 重新访问现有 PV 中的数据?

    这是不可能的,因为回收策略的状态为 Reclaim Policy: Delete,要实现这一点,您需要改用 Retain 选项,如 documentation 所述。

    要验证可以删除 PVC 并保留磁盘的理论,请执行以下操作:

    • 将回收策略更改为保留
    • 删除永久卷(PVC)
    • 删除永久卷(PV)

    然后验证磁盘是否被保留。


    5
    与 @Bharat Chhabra 的回答相似,但它将修改 所有 已发布的 PersistentVolumes 的状态为可用:
    kubectl get pv | tail -n+2 | awk '$5 == "Released" {print $1}' | xargs -I{} kubectl patch pv {} --type='merge' -p '{"spec":{"claimRef": null}}
    

    3
    另一种版本: for resource in $(kubectl get pv | grep Released | cut -d' ' -f1); do kubectl patch pv "${resource}" -p '{"spec":{"claimRef": null}}'; done - GuyPaddock

    2

    在删除Deployment后,其他答案提供的补丁才对我有效。
    此后,该终止资源被释放。


    按照以下列出的方式删除所有资源:

    kubectl -n YOURNAMESPACE get all
    

    使用 kubectl -n YOURNAMESPACE <resource> <id> 或者(如果你从上面的输出中复制粘贴)kubectl -n YOURNAMESPACE <resource>/<id>,对于你在那里看到的每个资源都要执行一遍。
    你也可以一次性执行多个操作:kubectl -n YOURNAMESPACE <resource>/<id1> <resource>/<id2> <resource2>/<id3> <resource2>/<id4> <resource3>/<id5> 等等。
    可能你试图删除资源,但由于部署或副本集资源的存在,它们会被重新创建,这会防止命名空间释放依赖资源并进行清理。

    2
    我写了一个简单的自动 PV 释放控制器,它会找到并使“已发布”的 PV 再次“可用”以供新的 PVC 使用,你可以在这里查看:https://github.com/plumber-cd/kubernetes-dynamic-reclaimable-pvc-controllers。但请确保您阅读免责声明,并确保这正是您想要的。Kubernetes 不会自动执行此操作,因为工作负载不应该访问其他工作负载的数据。当它们这样做时,Kubernetes 的惯用方式是使用 StatefulSets,因此 Kubernetes 只保证相同工作负载的副本可以声明旧数据。我的释放程序在某些情况下可能很有用,例如 CI/CD 构建缓存(它就是为此而创建的),但通常 PVC 的意思是“给我一个干净的、可以立即使用的存储空间,我可以在上面保存一些数据”,因此至少要将其作为单独的 StorageClass。

    0

    Bharat的答案对我也起作用了。

    如果您的PV显示为“已发布”,并且您已经通过helm uninstall或其他方法删除了PVC,则除非您删除claim ref,否则无法再次重复使用此PV:

    kubectl patch pv PV_NAME -p '{"spec":{"claimRef": null}}'
    

    请记住,除非 PV 已绑定,否则您无法执行此操作。您必须先删除 PVC,以便 PV 显示为“已释放”,然后才能运行此命令。PV 的状态应显示为“可用”,可以被重复使用。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接