Sign In

Curriculum 9: Deleting Resources

Finalizers

12 min · 15 XP

Finalizers -- Controlling Resource Cleanup

Finalizers are a mechanism that prevents a resource from being deleted until specific cleanup tasks are completed. They are the most common reason a resource gets stuck in the "Terminating" state.

What Are Finalizers?

A finalizer is a string stored in a resource's metadata.finalizers list. When you delete a resource that has finalizers, Kubernetes marks it for deletion but does not actually remove it. The resource stays in a Terminating state until all finalizers are removed.

# Check if a resource has finalizers
kubectl get namespace stuck-namespace -o jsonpath='{.metadata.finalizers}'

How Finalizers Work

The lifecycle of a resource with finalizers:

  1. You run kubectl delete
  2. Kubernetes sets metadata.deletionTimestamp on the resource
  3. A controller that registered the finalizer performs cleanup work
  4. The controller removes its finalizer from the list
  5. Once the finalizer list is empty, Kubernetes deletes the resource

Common Kubernetes finalizers include:

  • kubernetes.io/pv-protection -- prevents deleting PersistentVolumes that are in use
  • foregroundDeletion -- used by the garbage collector for foreground cascading deletes

Stuck Resources

The most common problem with finalizers is resources that get stuck in Terminating. This happens when:

  • The controller responsible for the finalizer is not running
  • The controller cannot complete its cleanup task
  • A custom finalizer was added but no controller handles it

Diagnosing Stuck Resources

When a resource is stuck, check its finalizers:

# For a stuck namespace
kubectl get namespace stuck-namespace -o yaml

# Look for the finalizers field and deletionTimestamp
# metadata:
#   deletionTimestamp: "2025-01-15T10:00:00Z"
#   finalizers:
#   - kubernetes

Removing Finalizers

If you are sure the cleanup is no longer needed, you can remove finalizers manually to unblock deletion.

Method 1: kubectl edit

kubectl edit namespace stuck-namespace
# Remove the entries from the finalizers list, save, and exit

Method 2: kubectl patch

# Remove all finalizers from a namespace
kubectl patch namespace stuck-namespace -p '{"metadata":{"finalizers":null}}' --type=merge

# Remove all finalizers from a PV
kubectl patch pv stuck-pv -p '{"metadata":{"finalizers":null}}' --type=merge

Method 3: API call (for stubborn namespaces)

Some namespaces require a direct API call:

kubectl get namespace stuck-namespace -o json | \
  jq '.spec.finalizers = []' | \
  kubectl replace --raw "/api/v1/namespaces/stuck-namespace/finalize" -f -

Safety Considerations

Removing finalizers bypasses the cleanup that was supposed to happen. Before removing a finalizer, consider:

  • Will removing it leave orphaned resources?
  • Is there data that needs to be flushed or backed up?
  • Is the associated controller simply down and could be restarted?

Try restarting the responsible controller first. Remove finalizers manually only as a last resort.

Key Takeaways

  • Finalizers prevent resource deletion until cleanup tasks are complete
  • Resources with pending finalizers stay in the Terminating state
  • Stuck resources usually mean the responsible controller is not running
  • Remove finalizers with kubectl patch or kubectl edit when cleanup is not needed
  • Always investigate why a finalizer is stuck before forcibly removing it