EKS PersistantVolumeClaim cannot be destroy solution terraform

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}}'