Skip to content

Understanding and Managing Finalizers in Kubernetes

Finalizers are an important concept in Kubernetes resource management that can sometimes cause confusion or operational issues. This guide explains what finalizers are, how they work, and provides practical commands for managing them.

Finalizers are metadata keys on Kubernetes resources that prevent resources from being deleted until specific cleanup operations have completed. They act as a protection mechanism to ensure orderly cleanup when resources are deleted.

When you attempt to delete a resource with finalizers:

  1. Kubernetes marks the resource for deletion (sets a deletionTimestamp)
  2. The resource remains in a “Terminating” state
  3. The controllers responsible for each finalizer perform their cleanup operations
  4. Once a controller completes its cleanup, it removes its finalizer
  5. When all finalizers are removed, the resource is finally deleted

Common finalizers include:

  • kubernetes.io/pv-protection
  • foregroundDeletion
  • kubernetes.io/pvc-protection
  • argocd.argoproj.io/finalizer (for ArgoCD resources)

Finalizers can sometimes cause resources to become “stuck” in a terminating state. This typically happens when:

  • The controller responsible for the finalizer is missing or malfunctioning
  • The cleanup process encounters errors
  • Custom controllers have been improperly implemented
  • A CRD has been deleted before its instances
Terminal window
kubectl get <resource-type> <resource-name> -n <namespace> -o jsonpath='{.metadata.finalizers}'

Example:

Terminal window
kubectl get pod my-pod -n default -o jsonpath='{.metadata.finalizers}'

List All Resources with Finalizers in a Namespace

Section titled “List All Resources with Finalizers in a Namespace”
Terminal window
kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 -I{} bash -c "kubectl get {} -n <namespace> -o json | jq '.items[] | select(.metadata.finalizers != null and .metadata.finalizers | length > 0) | \"\(.kind) \(.metadata.name) has finalizers: \(.metadata.finalizers)\"'"

Check If Resources Are Stuck in Terminating State

Section titled “Check If Resources Are Stuck in Terminating State”
Terminal window
kubectl get all -n <namespace> | grep Terminating

⚠️ CAUTION: Forcibly removing finalizers bypasses normal cleanup processes. Only do this when you’re certain the controllers responsible won’t act on them or when a resource is genuinely stuck.

Remove Finalizers from a Specific Resource

Section titled “Remove Finalizers from a Specific Resource”
Terminal window
kubectl patch <resource-type> <resource-name> -n <namespace> --type='json' -p='[{"op":"remove","path":"/metadata/finalizers"}]'

Example:

Terminal window
kubectl patch pod stuck-pod -n default --type='json' -p='[{"op":"remove","path":"/metadata/finalizers"}]'

Remove Finalizers from All Resources of a Specific Type

Section titled “Remove Finalizers from All Resources of a Specific Type”
Terminal window
kubectl get <resource-type> -n <namespace> -o name | xargs -I{} kubectl patch {} -n <namespace> --type='json' -p='[{"op":"remove","path":"/metadata/finalizers"}]'

Example for ApplicationSets in ArgoCD:

Terminal window
kubectl -n argocd get applicationset -o name | xargs -I{} kubectl -n argocd patch {} --type='json' -p='[{"op":"remove","path":"/metadata/finalizers"}]'

Alternative Method: Edit the Resource Directly

Section titled “Alternative Method: Edit the Resource Directly”
Terminal window
kubectl edit <resource-type> <resource-name> -n <namespace>

Then manually remove the finalizers array in the metadata section.

Force Deleting a Namespace with Stuck Resources

Section titled “Force Deleting a Namespace with Stuck Resources”

If a namespace is stuck in Terminating state:

Terminal window
kubectl get namespace <namespace-name> -o json | jq '.spec.finalizers = []' > ns.json
kubectl replace --raw "/api/v1/namespaces/<namespace-name>/finalize" -f ns.json
  1. Investigate First: Before removing finalizers, understand why they’re not being removed normally
  2. Document Actions: Keep a record of manual interventions in your runbooks
  3. Check for Orphaned Resources: Finalizers often protect against orphaned dependent resources
  4. Backup: If possible, take resource manifests or cluster snapshots before force removing finalizers
  5. Review Controllers: Recurring issues may indicate a problem with your controllers or configuration