If you are using Kubernetes version >= 1.31 PVC on AWS EKS, by default will add finalizer kubernetes.io/pvc-protection
. This is a safety mechanism that prevents deletion of PVCs that are still in use.
Example destroy EKS infra via Terraform, and stuck…
kubernetes_persistent_volume_claim.test_pvc: Still destroying... [id=default/test-pvc-v2, 50s elapsed]
kubernetes_persistent_volume_claim.test_pvc: Still destroying... [id=default/test-pvc-v2, 1m0s elapsed]
kubernetes_persistent_volume_claim.test_pvc: Still destroying... [id=default/test-pvc-v2, 1m10s elapsed]
kubernetes_persistent_volume_claim.test_pvc: Still destroying... [id=default/test-pvc-v2, 1m20s elapsed]
kubernetes_persistent_volume_claim.test_pvc: Still destroying... [id=default/test-pvc-v2, 1m30s elapsed]
kubernetes_persistent_volume_claim.test_pvc: Still destroying... [id=default/test-pvc-v2, 1m40s elapsed]
Force remove the finalizer to allow the deletion to proceed
Check you pvc yaml confirm that you have the finalizers. If so, we have to force set it to null.
kubectl get pvc test-pvc-v2 -o yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
pv.kubernetes.io/bind-completed: "yes"
pv.kubernetes.io/bound-by-controller: "yes"
volume.beta.kubernetes.io/storage-provisioner: ebs.csi.aws.com
volume.kubernetes.io/selected-node: ip-10-0-6-177.ap-northeast-1.compute.interna
l
volume.kubernetes.io/storage-provisioner: ebs.csi.aws.com
creationTimestamp: "2025-04-03T13:20:22Z"
deletionGracePeriodSeconds: 0
deletionTimestamp: "2025-04-10T02:36:51Z"
finalizers:
- kubernetes.io/pvc-protection <-- THIS
name: test-pvc-v2
namespace: default
resourceVersion: "2418776"
uid: 8ce6ada6-67e9-4f46-9afd-10096c9ed1e3
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: gp3
volumeMode: Filesystem
volumeName: pvc-8ce6ada6-67e9-4f46-9afd-10096c9ed1e3
status:
accessModes:
- ReadWriteOnce
capacity:
storage: 1Gi
phase: Bound
Set finalizer to null
kubectl patch pvc test-pvc-v2 -p '{"metadata":{"finalizers":null}}'