如何处理已发布的持久卷?

Posted

技术标签:

【中文标题】如何处理已发布的持久卷?【英文标题】:What to do with Released persistent volume? 【发布时间】:2018-11-13 00:18:57 【问题描述】:

TL;博士。我不知道删除 PVC 后如何访问数据,以及为什么删除 PVC 后 PV 不会消失。

我正在采取的步骤:

    在 GCE 中手动创建了一个磁盘:

    gcloud compute disks create --size 5Gi disk-for-rabbitmq --zone europe-west1-b
    

    跑:

    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 这不是 docs 所说的Delete 回收政策?

现在,如果我尝试重新创建 PVC 以重新获得对 PV 中数据的访问权限:

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

我仍然为pvs 得到这个,例如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
$

...我为pvcs 得到这个:

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

看来我的PV卡在Released状态,PVC无法访问不在Available状态的PV。

那么,为什么同一个 PV 和 PVC 不能再成为朋友呢? 如何使 PVC 重新获得对现有 PV 中数据的访问权限?

【问题讨论】:

kubernetes 没有向您展示如何将您的 PV 从 Released 更改为 Available 真的很烦人。动态配置更糟糕 【参考方案1】:
kubectl patch pv pv-for-rabbitmq -p '"spec":"claimRef": null'

这对我有用。

【讨论】:

是的,这行得通。我跟着 kubectl delete -f storage.yml 因为控制台删除不起作用 更多解释,来自 kubernetes 的文档:“从 PV 规范中删除 claimRef 条目,以便新的 PVC 可以绑定到它。这应该使 PV 可用。” 如此简单,却又如此有效。 当 pvc/pv 绑定发生时,它会更新 pv.spec.claimRef 部分。您可以使用k get pv pv-name -o jsonpath=".spec.claimRef" 进行检查。通过将其修补到 null 意味着删除此绑定并使其可用 在我的情况下,PV 在我修补它们后不久就会重新绑定。所有 PVC 都处于 Terminating 状态。但仍然无法重置 PVC 和 PV 并从头开始重新部署。【参考方案2】:

Pod 消耗节点资源,PVC 消耗 PV 资源这句话可能有助于充分理解 PV 和 PVC 之间的理论和友谊。

我已尝试完全重现使用提供的 YAML 文件记录的行为,但失败了,它返回了预期的结果。因此,在提供任何进一步的细节之前,这里是我的复制品的演练。

第 1 步:在 Europe-west1 区域创建 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

第 3 步:列出所有可用的 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

第五步:删除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”

根据您的问题

一个附带问题,只是加深我的理解:为什么 PV 仍然存在,即使它的 回收策略设置为删除?这不是 docs 所说的吗?删除回收政策?

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

Reclaim Policy:  Delete

这意味着它应该立即被删除。目前,卷可以保留回收删除

为什么它没有被删除?我唯一能想到的可能是 PV 仍然以某种方式被声明,这很可能是因为 PVC 没有成功删除它的容量显示“0”,要解决此问题,您需要删除 POD。或者,您可以使用$ kubectl describe pvc 命令查看 PVC 为何仍处于挂起状态。

对于这个问题,如何使 PVC 重新获得对现有 PV 中数据的访问权限?

这是不可能的,因为回收政策的状态,即Reclaim Policy: Delete,要使这成为可能,您需要根据documentation使用保留选项

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

将回收政策更改为 Retain 删除 PVC 删除 PV

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

【讨论】:

【参考方案3】:

官方文档有答案,希望它可以帮助其他寻找相同的人 (https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistent-volumes)

保留 Retain 回收策略允许手动回收资源。当 PersistentVolumeClaim 被删除时,PersistentVolume 仍然存在并且该卷被认为是“已释放”。但它还不能用于另一个索赔,因为前一个索赔人的数据仍在卷上。管理员可以通过以下步骤手动回收卷。

    删除持久卷。关联的存储资产在 外部基础设施(例如 AWS EBS、GCE PD、Azure 磁盘或 删除 PV 后 Cinder volume) 仍然存在。 手动清理相关存储资产上的数据 相应地。 手动删除关联的存储资产,或者如果您想 重用相同的存储资产,创建一个新的 PersistentVolume 存储资产定义。

【讨论】:

【参考方案4】:

我编写了一个简单的自动 PV 释放器控制器,它会找到并再次生成 Released PVs Available 以获得新的 PVC,请在此处查看 https://github.com/plumber-cd/kubernetes-dynamic-reclaimable-pvc-controllers。

但请务必阅读免责声明并确保这正是您想要的。 Kubernetes 不会自动执行此操作是有原因的——工作负载不应该访问其他工作负载的数据。因为当他们这样做时——Kubernetes 的惯用方式是 StatefulSets,因此 Kubernetes 保证只有相同工作负载的副本才能声明旧数据。我的发布器在某些情况下当然可能有用,例如 CI/CD 构建缓存(它是为它创建的) - 但通常 PVC 意味着“给我一个干净的准备使用的存储,我可以保存一些数据”,所以至少- 使其成为一个单独的 StorageClass。

【讨论】:

【参考方案5】:

您在典型的误解中运行,认为 PV 和 PVC 比它们更相关。

Persistent Volume:在 K8s 中,这个资源有很多选择。例如hostPath 将从运行 pod 的节点保留指定的大小,并将其映射到两者上所需的路径;你的 pod 和你的节点。

Persistent Volume Claim:PVC,尤其是在 GKE 上,将在 Google Cloud Platform 上创建一个物理 Persistent Disk,并将其附加到运行 pod 的节点上,作为辅助磁盘。因此,该声明更具体地针对云提供商。

注意:您不需要手动创建磁盘。只需创建声明,然后检查会发生什么。您将不得不给它一些时间,但最终状态应该是 BOUND,这意味着 Persistent Disk 已创建、附加并可以使用。

如果你使用df -h,它会显示为附加设备,它也会显示为kubectl get pv,因为它最终是一个持久卷

关于删除东西。当您删除 PV 或 PVC 时,什么也没有发生。您仍然可以进入 pod 并转到映射的路径。没问题。由于它没有被删除,因此 pod 仍然可以访问它。现在,如果您的 pod 出现故障并重新创建,而没有该 PV 或 PVC,您将收到错误消息。

【讨论】:

如何从映射的 PD 中检索数据?我所看到的只是一些 pvc-xyz 文件夹而已。我正在向 PD 写入一些文件。我的印象是,如果用户需要,k8s 会保持它们完好无损以便恢复。 你能详细说明一下吗?不确定我是否了解情况。 我有 EFS 作为外部存储。我在 EFS 上创建了文件夹 A。应用程序使用映射到文件夹的 PV,该文件夹将文件写入 EFS 文件夹。当我删除 pvc 和 pv 时,我在文件夹中看不到这些文件。我只在文件夹 A 中看到一些文件夹 pvc-randomtext-。如何从 EFS 中恢复文件?我在 sc 上有 Retain reclaimPolicy 删除PV时,数据丢失是正常的。 PV 对象为因 pod 故障而易受攻击的数据提供持久性。因此,如果删除 PV,则无法恢复数据。如果 pod 发生故障,您可以恢复数据。【参考方案6】:

Bharat 的回答也对我有用。

如果您的 PV 显示为“已发布”并且您已经通过 helm uninstall 或其他方法删除了 PVC,那么您将无法再次重新使用此 PV,除非您删除声明参考:

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

请记住,您不能这样做,除非在绑定 PV 时,您必须先删除 PVC,让 PV 显示“已释放”,然后您才能运行此命令。然后 PV 的状态应显示为“可用”并且可以重复使用。

【讨论】:

【参考方案7】:

其他答案中的补丁仅在删除部署后才对我有用。 之后,终止资源被释放。


删除所有列出的资源:

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>等。

可能您尝试删除资源,但由于 deploymentreplicaset 资源而重新创建资源,从而阻止命名空间释放相关资源并进行清理。

【讨论】:

以上是关于如何处理已发布的持久卷?的主要内容,如果未能解决你的问题,请参考以下文章

面试突击 002 | Redis 是如何处理已过期元素的?

6. Redis在内存用完时会怎么办?以及Redis如何处理已过期的数据?

为啥我的主机路径持久卷可以从所有 pod 访问?

如何处理突然删除 USB 卷?

当返回的对象也可能从持久存储中删除时,如何处理 fetchedResultsController 返回的故障对象

Redis 面试宝典之 Redis 如何处理已经过期的数据?