When a pod won’t start, or keeps restarting, Kubernetes usually tells you why, if you know where to look. The status column (CrashLoopBackOff, Pending, ImagePullBackOff, OOMKilled) points to the category of problem, and kubectl describe plus logs usually give the exact cause.

The three commands to start with

kubectl get pods -o wide                        # status, restarts, node
kubectl describe pod <pod>                      # events at the bottom: the most useful part
kubectl logs <pod> [-c <container>] --previous  # logs of the last crashed instance

Cluster-wide recent events:

kubectl get events -A --sort-by=.lastTimestamp | tail -30

Common statuses and fixes

Pending

The pod can’t be scheduled. describe shows why:

Event message Fix
Insufficient cpu / Insufficient memory Lower requests, or add node capacity
didn't match node selector/affinity Fix nodeSelector/affinity, or label nodes
had untolerated taint Add a toleration, or remove the taint
pod has unbound PersistentVolumeClaims StorageClass/provisioner missing. See persistent volumes

ImagePullBackOff / ErrImagePull

  • Typo in the image name or tag, or the tag doesn’t exist.
  • Private registry without an imagePullSecret.
  • Registry rate limits. See Docker Hub rate limits.
  • Wrong architecture (exec format error happens later, at runtime). See multi-arch images.
kubectl create secret docker-registry regcred --docker-server=registry.example.com --docker-username=u --docker-password=token

CrashLoopBackOff

The container starts and exits repeatedly. Kubernetes waits longer between restarts (backoff).

  1. kubectl logs <pod> --previous: the app’s own error (missing config, bad credentials, can’t reach the database).
  2. kubectl describe pod: Exit Code in “Last State”:
Exit code Meaning
1 / other Application error. Read the logs
137 Killed (SIGKILL), often OOMKilled (check “Reason”)
139 Segmentation fault
143 Terminated (SIGTERM), e.g. a failed liveness probe
  1. Missing ConfigMap or Secret keys show as CreateContainerConfigError. See ConfigMaps and Secrets.

OOMKilled

The container exceeded its memory limit. Raise the limit (and request), or fix the leak. For JVM, Node and similar runtimes, set heap sizes below the container limit. See Linux cgroups.

Running but not receiving traffic

  • Readiness probe failing: describe shows “Readiness probe failed”. The pod is excluded from the Service.
  • Service selector doesn’t match pod labels:
kubectl get endpoints web          # empty = no ready pods match the selector
kubectl get pods --show-labels

See Kubernetes deployments and services and Kubernetes ingress.

Get inside

kubectl exec -it <pod> -- sh
kubectl port-forward pod/<pod> 8080:8080

For minimal images without a shell (distroless), attach an ephemeral debug container:

kubectl debug -it <pod> --image=busybox:1.36 --target=<container>
kubectl debug node/<node> -it --image=ubuntu        # debug a node

Make a copy of a crashing pod with a different command, so you can inspect it:

kubectl debug <pod> -it --copy-to=debug-pod --container=app -- sh

Node-level problems

kubectl get nodes
kubectl describe node <node>        # pressure conditions: MemoryPressure, DiskPressure

DiskPressure (a full disk, often from images or logs) causes evictions. Clean up on the node (crictl rmi --prune), and check log rotation. See disk full troubleshooting.

Tools that help

  • k9s: a terminal UI to browse pods, logs and events quickly. See k9s.
  • stern: tail logs from many pods at once (stern web).

Quick reference

Status First check
Pending describe → scheduling events
ImagePullBackOff Image name, tag, pull secret
CrashLoopBackOff logs --previous, exit code
OOMKilled Memory limit vs usage
Running, no traffic Readiness probe, get endpoints
No shell in image kubectl debug --target

Related: kubectl cheat sheet and Linux troubleshooting methodology.

  • Kubernetes
  • Troubleshooting
  • DevOps