如何处理已发布的持久卷?
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
$
我仍然为pv
s 得到这个,例如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
s 得到这个:
$
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>
等。
可能您尝试删除资源,但由于 deployment
或 replicaset
资源而重新创建资源,从而阻止命名空间释放相关资源并进行清理。
【讨论】:
以上是关于如何处理已发布的持久卷?的主要内容,如果未能解决你的问题,请参考以下文章
6. Redis在内存用完时会怎么办?以及Redis如何处理已过期的数据?