NovuSpark
All articles
ContainerizationJune 10, 2026 · NovuSpark Team · 5 min read

Kubernetes troubleshooting: a field guide to CrashLoopBackOff, ImagePullBackOff, and Pending pods

Sooner or later every Kubernetes user stares at a pod stuck in CrashLoopBackOff, ImagePullBackOff, or Pending and wonders where to even begin. The good news: these three states cover a large share of everyday failures, and each has a short, repeatable diagnostic path.

The trick is to stop guessing and let Kubernetes tell you what's wrong. It almost always will — if you ask the right command.

get podsread the STATUSdescribe podread Events at thebottomlogscurrent and previousfix and retrychange one thing
Fig. 1 — the same four-step loop solves most pod problems; the status tells you which step matters most

The two commands you'll use constantly

kubectl get pods
kubectl describe pod <pod-name>

describe is the underrated one. Scroll to the Events section at the bottom — scheduler decisions, image pulls, probe failures, and restarts are all recorded there in plain language.

Pending: the pod hasn't been placed anywhere

Pending means the pod was accepted but isn't running yet. Most often the scheduler can't find a node that fits.

kubectl describe pod <pod-name>
# Look for events like:
# 0/3 nodes are available: 3 Insufficient cpu.

Common causes and what to check:

  • Insufficient CPU or memory. The pod's resource requests exceed what any node has free. Lower the requests, add capacity, or fix an accidentally huge value (memory: 16Gi instead of 16Mi is a classic).
  • Node selectors, affinity, or taints. The pod demands a node label that doesn't exist, or nodes carry a taint the pod doesn't tolerate. Compare the pod spec against kubectl get nodes --show-labels and kubectl describe node.
  • Unbound PersistentVolumeClaim. The pod is waiting for storage. Run kubectl get pvc and check whether a matching volume or StorageClass exists. Our storage post covers this in depth.

ImagePullBackOff and ErrImagePull: the image can't be fetched

The node tried to pull the container image and failed, then backs off and retries with increasing delays.

kubectl describe pod <pod-name>
# Events often show: Failed to pull image "myapp:1.2" ... not found
# or: pull access denied / unauthorized

Check, in this order:

  1. Typos. Wrong image name, wrong tag, wrong registry host. It's embarrassingly often this.
  2. The tag really exists. Confirm in the registry. A tag that was never pushed — or a CI job that failed before pushing — looks identical to a typo.
  3. Authentication. Private registries need an image pull secret referenced by the pod or its service account.
kubectl create secret docker-registry regcred \
  --docker-server=registry.example.com \
  --docker-username=<user> \
  --docker-password=<token>
spec:
  imagePullSecrets:
    - name: regcred
  1. Network access. Can the node actually reach the registry? Firewalls, proxies, and missing NAT routes show up here.

CrashLoopBackOff: the container starts, then dies, repeatedly

This one means Kubernetes keeps restarting a container that keeps exiting. The pod is scheduled and the image pulled, so the problem is inside the container — or in how it's being checked.

kubectl logs <pod-name>
kubectl logs <pod-name> --previous   # logs from the last crashed instance
kubectl describe pod <pod-name>      # look at Last State and Exit Code

The --previous flag is the one people forget. The current container may have just restarted and have no logs yet, while the instance that crashed has the answer.

Read the exit code in describe:

Exit codeUsual meaning
1Application error — check the logs
137Killed, commonly out-of-memory (OOMKilled) or forcibly terminated
139Segmentation fault
143Terminated by SIGTERM

Frequent root causes:

  • The app crashes on startup — missing configuration, a bad environment variable, an unreachable dependency. See our post on ConfigMaps, Secrets, and environment configuration.
  • OOMKilled. The container exceeded its memory limit. Raise the limit or fix the leak.
  • A failing liveness probe that kills a perfectly healthy but slow-starting app. If the app needs time to boot, use a startup probe or a longer initial delay.
  • The wrong command or entrypoint, so the process exits immediately with success. A container whose main process finishes is, to Kubernetes, a container that stopped.

A debugging toolkit worth knowing

# Run a throwaway pod to test connectivity from inside the cluster
kubectl run tmp --rm -it --image=busybox -- sh
 
# Open a shell in a running container
kubectl exec -it <pod-name> -- sh
 
# Recent cluster events, newest last
kubectl get events --sort-by=.lastTimestamp
 
# Attach an ephemeral debug container to a running pod
kubectl debug -it <pod-name> --image=busybox --target=<container-name>

The habit that saves the most time

Change one thing at a time and re-check. The fastest way to turn a ten-minute problem into a two-hour one is to alter the image, the config, and the resource limits all at once and then wonder which one mattered.

Practice beats reading

Troubleshooting is a skill built by breaking things on purpose and fixing them under mild pressure — which is exactly how the practical Certified Kubernetes Administrator exam tests it. If you're getting started, begin with Kubernetes 101: Pods, Deployments, and Services, and for a guided, hands-on path see our Kubernetes and DevOps in Practice course.

Ready when you are

Want training built around your team's real work?

Tell us about your team and what you're trying to solve — we'll recommend a program that fits.