Kubernetes
Pod
Termination Issue
Cloud Computing
Troubleshooting

Pod not terminating

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

A Kubernetes Pod that stays in Terminating is usually waiting for something to finish or be released. The fix depends on what is blocking shutdown: the application process, a lifecycle hook, a finalizer, attached storage, or the node itself.

How Pod Termination Is Supposed To Work

When a Pod is deleted, Kubernetes does not immediately remove it. The usual sequence is:

  1. the Pod receives a deletion timestamp
  2. containers get SIGTERM
  3. preStop hooks run if configured
  4. Kubernetes waits for terminationGracePeriodSeconds
  5. remaining processes get SIGKILL
  6. the Pod object is removed when cleanup is complete

If that sequence stalls, the Pod remains visible as terminating.

Start With The Pod Description

The first step is to inspect events and status.

bash
kubectl describe pod my-pod
kubectl get pod my-pod -o yaml

Look for:

  • long-running preStop hooks
  • volume unmount issues
  • finalizers on the Pod object
  • container state messages
  • node communication problems

If the Pod belongs to a Deployment, StatefulSet, or Job, also inspect the controller because it may recreate or manage the Pod while you debug it.

Application Shutdown Is Often The Real Cause

A very common reason is that the main process ignores SIGTERM or takes too long to exit.

For example, this Python process shuts down cleanly:

python
1import signal
2import time
3
4running = True
5
6
7def handle_term(signum, frame):
8    global running
9    running = False
10
11
12signal.signal(signal.SIGTERM, handle_term)
13
14while running:
15    time.sleep(1)
16
17print("cleanup finished")

If your container entrypoint is a shell script that does not forward signals, the real application may never see SIGTERM. In that case, fix the container startup first.

Check Lifecycle Hooks And Grace Periods

A preStop hook can delay termination longer than expected.

yaml
1lifecycle:
2  preStop:
3    exec:
4      command: ["/bin/sh", "-c", "sleep 20"]
5terminationGracePeriodSeconds: 30

If the hook blocks or depends on a service that is already unavailable, the Pod may sit in Terminating until the grace period expires. If the grace period is very large, that can look like a hang.

Use a preStop hook only for short, deterministic cleanup.

Finalizers Can Keep The Pod Object Around

Sometimes the containers are already gone, but the Pod object still exists because a finalizer has not completed.

Check the metadata:

bash
kubectl get pod my-pod -o jsonpath='{.metadata.finalizers}'

If a controller added a finalizer and is no longer running correctly, the Pod can remain stuck. In that case, identify why the responsible controller is not clearing it before removing anything manually.

Volumes And Node Problems

Pods attached to persistent volumes can remain terminating if unmount or detach steps are stuck. The same happens when the kubelet on the node is unhealthy or unreachable.

Useful checks are:

bash
kubectl get node
kubectl describe node my-node
kubectl get volumeattachments

If the node is in trouble, deleting the Pod from the API server alone may not solve the underlying resource cleanup problem.

Force Deletion Is A Last Resort

You can force removal with:

bash
kubectl delete pod my-pod --grace-period=0 --force

Use this carefully. Force deletion removes the Pod object from the API server, but it does not guarantee graceful application shutdown or immediate cleanup of external resources.

That makes it useful for recovery, not as the default fix.

Common Pitfalls

The most common mistake is focusing only on Kubernetes and ignoring the application process. If the app does not handle SIGTERM, the Pod may never exit cleanly.

Another mistake is using long or fragile preStop hooks for work that belongs elsewhere.

Teams also force-delete Pods too early and lose the chance to diagnose finalizers, volume detach issues, or node health problems.

Finally, do not assume a terminating Pod is harmless. If the same controller keeps creating replacements while old Pods linger, you can end up with resource pressure or duplicate work.

Summary

  • Start with kubectl describe pod and the full Pod YAML.
  • Verify that the application process handles SIGTERM correctly.
  • Inspect preStop hooks, grace periods, and finalizers.
  • Check storage and node health when cleanup appears stuck.
  • Use force deletion only after you understand what is being bypassed.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.