【问题标题】:Cancel or undo deletion of Persistent Volumes in kubernetes cluster取消或撤消删除 Kubernetes 集群中的 Persistent Volumes
【发布时间】:2018-07-30 00:29:54
【问题描述】:

不小心尝试删除集群中的所有 PV,但幸运的是它们仍然有绑定到它们的 PVC,因此所有 PV 都卡在 Status: Terminating。

我怎样才能让 PV 脱离“终止”状态并恢复到“绑定”到 pvc 并完全工作的健康状态?

这里的关键是我不想丢失任何数据,并且我想确保卷功能正常,并且在索赔消失时不会面临被终止的风险。

以下是 PV 上 kubectl describe 的一些详细信息。

$ kubectl describe pv persistent-vol-1
Finalizers:      [kubernetes.io/pv-protection foregroundDeletion]
Status:          Terminating (lasts 1h)
Claim:           ns/application
Reclaim Policy:  Delete

这是对索赔的描述。

$ kubectl describe pvc application
Name:          application
Namespace:     ns
StorageClass:  standard
Status:        Bound
Volume:        persistent-vol-1

【问题讨论】:

  • @David_Maze 感谢您对我的帖子的帮助!

标签: kubernetes persistent-volumes


【解决方案1】:

事实上,可以通过将Status: TerminatingRetainPolicy 设置为默认(删除)来保存PersistentVolume 中的数据。我们已经在 GKE 上这样做了,不确定AWS 或 Azure,但我猜它们是相似的

我们遇到了同样的问题,我会在这里发布我们的解决方案,以防其他人遇到这样的问题。

您的 PersistenVolumes 将不会被终止,直到有一个 pod、部署或更具体的 - PersistentVolumeClaim 使用它。

我们为修复损坏状态而采取的步骤:

一旦你处于像 OP 这样的情况,你要做的第一件事就是为你的PersistentVolumes 创建一个快照。

在 GKE 控制台中,转到 Compute Engine -> Disks 并在那里找到您的卷(使用 kubectl get pv | grep pvc-name)并为您的卷创建快照。

使用快照创建磁盘:gcloud compute disks create name-of-disk --size=10 --source-snapshot=name-of-snapshot --type=pd-standard --zone=your-zone

此时,停止使用卷的服务并删除卷和卷声明。

使用磁盘中的数据手动重新创建卷:

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: name-of-pv
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 10Gi
  gcePersistentDisk:
    fsType: ext4
    pdName: name-of-disk
  persistentVolumeReclaimPolicy: Retain

现在只需更新您的卷声明以针对特定卷,即 yaml 文件的最后一行:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
  namespace: my-namespace
  labels:
    app: my-app
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  volumeName: name-of-pv

【讨论】:

    【解决方案2】:

    编辑:这仅适用于您删除了 PVC 而不是 PV。如果您删除了 PV 本身,请不要按照这些说明操作,否则磁盘可能会被删除!

    由于一个粗心的错误,我发现自己处于同样的境地。它在 Google Cloud/GKE 上有一个 statefulset。我的 PVC 说终止,因为引用它的 pod 仍在运行,并且 PV 配置了已删除的保留策略。我最终找到了一种更简单的方法来理顺所有内容,同时保留了所有额外的 Google/Kubernetes 元数据和名称。

    首先,我会按照另一个答案的建议对您的磁盘进行快照。您不需要它,但如果出现问题,则可以使用此处的另一个答案从中重新创建磁盘。

    简短的版本是您只需将 PV 重新配置为“保留”,允许 PVC 被删除,然后从 PV 中删除先前的声明。然后可以将新的 PVC 绑定到它,一切都很好。

    详情:

    1. 查找 PV 的全名:
        kubectl get pv
    
    1. 重新配置您的 PV 以将回收策略设置为“保留”:(我在 Windows 上执行此操作,因此您可能需要根据操作系统以不同方式处理引号)
        kubectl patch pv <your-pv-name-goes-here> -p "{\"spec\":{\"persistentVolumeReclaimPolicy\":\"Retain\"}}"
    
    1. 验证 PV 的状态现在是否为 Retain。
    2. 关闭您的 pod/statefulset(并且不允许它重新启动)。完成后,您的 PVC 将被移除,PV(及其引用的磁盘!)将保持原样。
    3. 编辑 PV:
        kubectl edit pv <your-pv-name-goes-here>
    
    1. 在编辑器中,删除整个“claimRef”部分。从(包括)“claimRef:”中删除所有行,直到下一个具有相同缩进级别的标签。要删除的行应大致如下所示:
          claimRef:
            apiVersion: v1
            kind: PersistentVolumeClaim
            name: my-app-pvc-my-app-0
            namespace: default
            resourceVersion: "1234567"
            uid: 12345678-1234-1234-1234-1234567890ab
    
    1. 保存更改并关闭编辑器。检查 PV 的状态,它现在应该显示“可用”。
    2. 现在您可以完全按照原来的方式重新创建 PVC。然后应该找到现在“可用”的 PV 并将其自身绑定到它。在我的例子中,我使用我的 statefulset 将 PVC 定义为 volumeClaimTemplate,所以我所要做的就是“kubectl apply”我的 statefulset。

    【讨论】:

    • 警告:这仅适用于您不小心删除 PVC 而不是 PV。因为,在您的第 4 步之后,PV 将不会绑定到任何 PVC,因此无论其回收策略如何,它都会被删除。
    • 使用Retain reclaim 策略删除 PV 不应该删除底层云盘资源。 Per kubernetes.io/docs/concepts/storage/persistent-volumes/#retain “删除 PV 后,外部基础设施(例如 AWS EBS、GCE PD、Azure 磁盘或 Cinder 卷)中的关联存储资产仍然存在。”
    • 注意:第 6 步(改进):仅从 claimRef 中删除 uid 行,然后将新的 PVC 分配给相同的 PV。否则,如果删除整个部分,PVC 可能会随机分配给现有 PV。
    【解决方案3】:

    你可以查看this tool,它会将etcd中Terminating PV的状态更新回Bound

    Anirudh Ramanathan 在他的回答中提到了它的工作方式。

    请务必先备份您的 PV。

    【讨论】:

      【解决方案4】:

      如果您不知道自己在做什么,请不要尝试这样做

      还有另一种相当老套的方法来取消删除 PV。直接编辑 etcd 中的对象。请注意,仅当您可以控制 etcd 时,以下步骤才有效 - 在某些云提供商或托管产品上可能并非如此。另请注意,您很容易把事情搞砸;因为 etcd 中的对象从不打算直接编辑 - 所以请谨慎处理。

      我们的 PV 有一个 delete 的策略,我不小心在 k8s 1.11 上运行了一个删除其中大部分的命令。多亏了storage-object-in-use的保护,它们并没有立即消失,而是处于危险的状态中徘徊。任何删除或重新启动绑定 PVC 的 pod 都会导致 kubernetes.io/pvc-protection 终结器被删除,从而删除底层卷(在我们的例子中是 EBS)。当资源处于终止状态时,也无法添加新的终结器 - 从 k8s 设计的角度来看,这是防止竞争条件所必需的。

      以下是我遵循的步骤:

      • 备份您关心的存储卷。这只是为了保护自己免受可能的删除 - AWS、GCP、Azure 都提供了执行此操作并创建新快照的机制。
      • 直接访问 etcd - 如果它作为静态 pod 运行,您可以 ssh 进入它并检查 http 服务端口。默认情况下,这是 4001。如果您正在运行多个 etcd 节点,请使用任何一个。
      • 从 pod 将 4001 端口转发到您的计算机。
      kubectl -n=kube-system port-forward etcd-server-ip-x.y.z.w-compute.internal 4001:4001 
      
      • 使用 REST API 或 etcdkeeper 之类的工具连接到集群。

      • 导航到/registry/persistentvolumes/ 并找到相应的 PV。 k8s 中控制器对资源的删除是通过在控制器规范中设置.spec.deletionTimeStamp 字段来完成的。删除此字段以使控制器停止尝试删除 PV。这会将它们恢复到 Bound 状态,这可能是它们在您运行删除之前所处的位置。

      • 您还可以将reclaimPolicy 仔细编辑为Retain,然后将对象保存回etcd。控制器将很快重新读取状态,您很快就会看到它反映在 kubectl get pv 输出中。

      您的 PV 应该回到旧的未删除状态:

      $ kubectl get pv
      
      NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                                             STORAGECLASS                      REASON    AGE
      pvc-b5adexxx   5Gi        RWO            Retain           Bound     zookeeper/datadir-zoo-0                           gp2                                         287d
      pvc-b5ae9xxx   5Gi        RWO            Retain           Bound     zookeeper/datalogdir-zoo-0                        gp2                                         287d
      

      作为一般的最佳实践,最好使用RBAC 和正确的持久卷回收策略来防止意外删除 PV 或底层存储。

      【讨论】:

        【解决方案5】:

        很遗憾,在这种情况下,您无法保存 PV 和数据。 您可以做的就是使用Reclaim Policy: Retain 重新创建 PV - 这将防止将来数据丢失。 您可以阅读更多关于回收政策herehere

        如果我删除 PersistentVolumeClaim (PVC) 会发生什么?如果音量 是动态配置的,则默认回收策略设置为 “删除”。这意味着,默认情况下,当 PVC 被删除时, 基础 PV 和存储资产也将被删除。如果你想 保留存储在卷上的数据,那么您必须更改回收 配置 PV 后从“删除”到“保留”的策略。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-03-17
          • 1970-01-01
          • 2019-12-31
          • 1970-01-01
          • 1970-01-01
          • 2016-09-28
          相关资源
          最近更新 更多