Worker node failures

What NotReady means, how to read a node's conditions, and the four things that take a worker down on the exam: the kubelet stopped, its config broken, its certificate or kubeconfig wrong, or the container runtime gone.

40 min 3 hands-on tasksTroubleshooting · 30% of the exam

Key ideas in this lesson · tap one for a simple explanation

What you will be able to do

  • Read a node's Conditions and say whether the kubelet, the runtime, the disk or the network is the problem.
  • Bring a NotReady node back with systemctl, journalctl and a one-line fix in /var/lib/kubelet/config.yaml.
  • Predict what happens to the Pods on a node that stays down.

This lesson covers the exam topic Troubleshoot clusters and . The part it is really about is the . A typical task says: node X is NotReady, fix it. You do the whole job on the node, over ssh, with three tools: systemctl, journalctl and a text editor. This lesson shows the order to use them in, and the files that matter.

NotReady and the node conditions

Every 10 seconds the kubelet sends a heartbeat to say it is alive. If the hears nothing for 50 seconds, it sets the node's Ready condition to Unknown. kubectl get nodes then shows NotReady. But NotReady comes in two kinds, and they send you to different places:

Two kinds of NotReady

Ready = False

the kubelet runs and reports a problem

Example

the container runtime is down

Look at

the condition's Message, then the journal

Ready = Unknown

the kubelet has gone silent

Example

the kubelet was stopped

Look at

systemctl status kubelet

Both show as NotReady in kubectl get nodes. kubectl describe node tells you which one it is, with a Reason and a Message.

Here is every node condition, with what to check. For Ready, trouble is False or Unknown. For the other conditions, trouble is True:

ConditionWhat it meansWhat to check
Ready = FalseThe kubelet runs, but something it needs is broken: the , the network plugin, or its own startup checksthe condition's Message, then journalctl -u kubelet
Ready = UnknownNo heartbeat for 50 seconds: the kubelet stopped or keeps crashing, it cannot reach the , or the node is offsystemctl status kubelet on the node. Can it reach the API server?
MemoryPressure = TrueMemory is running out. The kubelet starts evicting kubectl top node: what is using the memory?
DiskPressure = TrueThe node's disk is nearly full. The kubelet evicts Pods and refuses new onesdf -h on the node
PIDPressure = TrueToo many processes on the nodeps on the node: is a workload starting processes without end?
NetworkUnavailable = TrueThe network plugin has not set up the nodethe network plugin's Pod on that node (calico-node in the lab)
First, read the node from your own terminal
kubectl get nodes -o wide
kubectl describe node cka-worker2 | sed -n '/^Conditions:/,/^Addresses:/p'
kubectl describe node cka-worker2 | grep -A3 '^Taints'
kubectl get pods -A -o wide --field-selector spec.nodeName=cka-worker2

The kubelet: stopped, crash-looping, or misconfigured

On the node, the first command is always systemctl status kubelet. Its Active line gives one of three answers:

  • inactive (dead): someone stopped it. systemctl start kubelet brings the node back within seconds. Then run systemctl enable kubelet, so a reboot does not undo it. The exam often checks this.
  • activating (auto-restart): the kubelet starts and exits, again and again. Its journal says why, and it is almost always a wrong path in its config file.
  • active (running), but the node is still NotReady: the kubelet runs but cannot do its job. Again the journal says why: usually the API server address, a certificate, or the container runtime.
On the node (exam: ssh cka-worker2; lab: docker exec -it cka-worker2 bash)
systemctl status kubelet --no-pager
journalctl -u kubelet -n 50 --no-pager          # the last 50 lines; the error repeats near the end
journalctl -u kubelet -f                         # follow while you fix; Ctrl-C to stop
systemctl start kubelet
systemctl enable kubelet
systemctl restart kubelet                        # after editing its configuration
systemctl is-active kubelet; systemctl is-enabled kubelet

Where the kubelet's configuration lives

Two files hold almost everything that breaks:

FileWhat it holdsHow it breaks
/var/lib/kubelet/config.yamlThe kubelet's settings: staticPodPath, clientCAFile, containerRuntimeEndpoint, clusterDNS, cgroupDriverA wrong path or a typo. The kubelet refuses to start
/etc/kubernetes/kubelet.confThe kubelet's : the API server's address and the path of its client certificateA wrong host or port. The kubelet runs, but the node stays NotReady and the journal shows connection refused
Check the two files
grep -nE 'staticPodPath|clientCAFile|containerRuntimeEndpoint|clusterDNS|cgroupDriver' /var/lib/kubelet/config.yaml
grep server: /etc/kubernetes/kubelet.conf

Here is the most common case, a broken config.yaml:

  • Symptom: systemctl status kubelet says activating (auto-restart).
  • Cause: the journal names it. For example: failed to run Kubelet: unable to load client CA file /etc/kubernetes/pki/ca.crtt: open …: no such file or directory. A YAML typo gives an error with a line number instead.
  • Fix: run ls -l on the path it quotes, correct the file, then run systemctl restart kubelet.

An expired kubelet certificate

The kubelet proves who it is to the API server with a client certificate. Normally it renews that certificate by itself, before it expires. But if the node is off for longer than the certificate lasts, the certificate expires:

  • Symptom: the kubelet is active, but the node stays NotReady. The journal shows Unauthorized or x509: certificate has expired.
  • Check: openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates prints the certificate's dates.
  • Fix: the node needs a new client certificate, through the API, or it must join the cluster again. Certificates, kubeconfig and the CSR API covers certificates.

Container runtime down, disk full

ProblemWhat you seeFix
stoppedReady = False, with reason KubeletNotReady. The journal repeats container runtime is down, and crictl ps failssystemctl start containerd, then systemctl enable containerd. The kubelet reconnects by itself
Disk fullDiskPressure. Pods show Evicted, and no new Pods land on the nodedf -h on the node shows which disk is full. crictl rmi --prune removes unused images

What happens to the Pods on a NotReady node

When a node stays down

The kubelet stops

containers keep running

About 50 seconds later

NotReady: tainted, no new Pods

5 minutes after that

Pods evicted, recreated elsewhere

Nothing moves for about six minutes, so a short outage evicts nothing.

  • The first minutes: the keep running. About 50 seconds after the last heartbeat, the node is marked NotReady and gets a NoExecute : node.kubernetes.io/unreachable, or not-ready for Ready = False. The stops placing Pods there, and its Pods drop out of their .
  • About 5 minutes later: every Pod has a default for these taints that lasts 300 seconds. When it runs out, the Pods are deleted, and their create new ones on healthy nodes. The old Pods show Terminating until the kubelet comes back.
  • Exceptions: Pods stay. Bare Pods are deleted and never come back. Pods are not replaced until the old one is really gone, so you must force-delete it.

If a sick node is still reachable, you do not have to wait: kubectl drain moves its Pods away now. Upgrading clusters and draining nodes teaches and .

The node checklist on one screen

SymptomCheckFix
NotReady, Ready = Unknownssh <node>, then systemctl status kubeletsystemctl start kubelet, then systemctl enable kubelet
kubelet activating (auto-restart)journalctl -u kubelet -n 50fix the path or key it quotes in /var/lib/kubelet/config.yaml, then restart the kubelet
kubelet active, node NotReady, connection refused in the journalgrep server: /etc/kubernetes/kubelet.conffix the host or port, then restart the kubelet
kubelet active, Unauthorized or x509 in the journalopenssl x509 -noout -dates -in /var/lib/kubelet/pki/kubelet-client-current.pemget a new kubelet client certificate (CSR, or join again)
Ready = False, KubeletNotReady, runtime downsystemctl status containerd, then crictl pssystemctl start containerd
DiskPressure, Evicted Podsdf -h, then crictl rmi --prunefree up the disk, and find what fills it
Pods Terminating for a long time on a dead nodekubectl get nodesbring the node back, or delete the Pods with --force --grace-period=0

In the official docs· open on exam day too

Hands-on task 1 of 3ts-node-1
~3 min2% weightTroubleshooting

Find a node by role and record its address

Find the node that carries the control-plane role (the label node-role.kubernetes.io/control-plane) and write its InternalIP address, and nothing else, to /tmp/cka/control-plane-ip.txt.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-1/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-1/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-1/cleanup | bash
Hands-on task 2 of 3ts-node-2
~8 min6% weightTroubleshooting

Bring a NotReady node back

The node cka-worker2 is reported as NotReady. Investigate on the node and bring it back to Ready. The fix must survive a reboot of the node.

Cluster:kubectl config use-context kind-cka

Setup breaks part of your lab on purpose, like the exam does. Run the clean-up step when you finish.
  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-2/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-2/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-2/cleanup | bash
Hands-on task 3 of 3ts-node-3
~10 min7% weightTroubleshooting

A kubelet that will not start

The node cka-worker2 went NotReady after a configuration change on the node. The kubelet's configuration file must stay where it is. Find the problem, fix it and make the node Ready again.

Cluster:kubectl config use-context kind-cka

Setup breaks part of your lab on purpose, like the exam does. Run the clean-up step when you finish.
  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-3/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-3/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/ts-node-3/cleanup | bash

Finished this lesson?

0 of 3 tasks passed. Your readiness counts tasks, so run them before you move on.