Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Why a Kubernetes pod is broken

After this lesson: I can read describe and logs and name the fault of a broken pod.

60 min lesson13 commandsKubernetes lab: a one-node k3s cluster for each student on a private Ubuntu VM

A broken pod tells you why

A broken pod is one that never reaches the Running state. Kubernetes records the reason, but you have to read the right place.

The STATUS column names the kind of fault, the pod's events say what Kubernetes tried, and the pod's log says what the program said.

By the end of this lesson

Note

I can read describe and logs and name the fault of a broken pod.

Key words

WordWhat it meansExample
Statusthe state a pod is inPending
Eventsthe list of what Kubernetes did with a pod
Logwhat the program in the pod printed
CrashLoopBackOffthe program keeps stopping and is retried, with longer waits
ImagePullBackOffthe image cannot be fetched, so it waits and retries
Describethe kubectl command that shows one object in full

The cells students fill in are left blank in this preview.

The STATUS column names the kind of fault

Three words cover most broken pods. Pending means no node has taken the pod yet. ImagePullBackOff means the image could not be fetched. CrashLoopBackOff means the program starts, stops, and is tried again.

The word is a clue, not the cause. The cause is in the events or the log.

Worked example: status, meaning, where to look

STATUSWhat has happenedLook at first
PendingNo node has taken the podThe events, in describe
ErrImagePull, ImagePullBackOffThe image was not fetchedThe events, in describe
CrashLoopBackOffThe program started and stoppedThe log

The cells students fill in are left blank in this preview.

Make a namespace for faults

Command
kubectl create namespace faults

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Start a program that always fails

Command
kubectl create deployment crashy -n faults --image=busybox:1.37.0 -- sh -c 'echo cannot open orders.db; exit 2'

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Ask for a tag that does not exist

Command
kubectl create deployment oldtag -n faults --image=busybox:1.99.0 -- sleep 3600

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Start a pod no node suits

Command
kubectl run stuck -n faults --image=busybox:1.37.0 --overrides='{"spec":{"nodeSelector":{"disk":"fast"}}}' -- sleep 3600

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Wait until the crashing pod is backing off

Command
kubectl wait --for=jsonpath='{.status.containerStatuses[0].state.waiting.reason}'=CrashLoopBackOff pod -l app=crashy -n faults --timeout=120s

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Read the STATUS column

Command
kubectl get pods -n faults

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Logs and events say what went wrong

kubectl logs prints what the program wrote. It is the first place to look when the program ran and stopped.

kubectl describe pod prints the pod in full, and its Events at the bottom. They are the first place to look when the program never ran. For a pod stuck in Pending, the last event says why no node took it.

Read the failing program's log

Command
kubectl logs -n faults -l app=crashy

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Read the last events of the stuck pod

Command
kubectl describe pod stuck -n faults | tail -n 3

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think CrashLoopBackOff is the fault. It is only the pattern: start, stop, wait, try again. The fault is whatever made the program stop, and the log has it. Read the log before you change anything.

Fix the fault the events name

A wrong image tag is fixed by giving the Deployment a tag that exists. A pod with a node selector no node meets waits until a node does.

The next Runs give oldtag the image the lab has. Then they label the node disk=fast so stuck can be placed, and take the label away again.

Give oldtag an image that exists

Command
kubectl set image deployment/oldtag busybox=busybox:1.37.0 -n faults

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Label the node for the pod

Command
kubectl label nodes --all disk=fast

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Wait until stuck is ready

Command
kubectl wait --for=condition=Ready pod/stuck -n faults --timeout=60s

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Take the label off the node again

Command
kubectl label nodes --all disk-

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Remove the namespace

Command
kubectl delete namespace faults

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

About this lab and its source: Kubernetes lab: a one-node k3s cluster for each student on a private Ubuntu VM

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.