Home › CKA › Topics › Practice tasks › Control Plane Troubleshooting
CKA · Troubleshooting

Fix a Broken Control Plane: Three Static Pod Faults

After a cluster migration, the control plane is completely down. The kube-apiserver, kube-controller-manager, and kube-scheduler static pods are all failing to start.

Check live lab access → All CKA tasks

Live lab access

This task description is public. Its live lab requires full access; six other CKA labs are available in Free Practice with AI Lab Coach.

Create an account to continue →

Explore the six free labs with AI Lab Coach →

Read the brief on any device. Use a desktop or laptop for the terminal lab. Nothing starts until you choose Start.

The task

After a cluster migration, the control plane is completely down. The kube-apiserver, kube-controller-manager, and kube-scheduler static pods are all failing to start.

There are 3 separate problems across the static pod manifests in:

/etc/kubernetes/manifests/

Task: Identify and fix all three issues so the control plane recovers and kubectl get nodes works again.

Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster. Control-plane manifests can take down the whole cluster, so practise on a throwaway kubeadm VM, and break only the test Pod created below, never a real component.

Static Pods: how the kubelet runs the control plane, and how to debug it when kubectl is gone

On a kubeadm control-plane node, kube-apiserver, kube-controller-manager, kube-scheduler and etcd are static Pods: plain Pod manifests on disk that the kubelet runs by itself, with no API server involved. That independence is what lets the API server start at all, and it is also why, when a manifest is wrong, kubectl cannot help. You debug from the node with the file, the runtime and the kubelet's own logs.

/var/lib/kubelet/config.yaml (staticPodPath) ──→ kubelet scans /etc/kubernetes/manifests
   file valid?   no ──→ nothing starts; reason is in the kubelet journal
                 yes ──→ container via CRI ──→ exits? reason is in crictl logs
                       └──→ mirror Pod "<name>-<node>" shown by the API server (read-only)

1. Find the directory and look around (read-only)

grep staticPodPath /var/lib/kubelet/config.yaml
ls -la /etc/kubernetes/manifests/
kubectl -n kube-system get pods -o wide | grep "$(hostname)"

The kubelet processes every file in that directory whose name does not start with a dot, regardless of extension. Mirror Pods in the API carry the node name as a suffix; deleting one with kubectl does not stop the real static Pod. The only way to change a static Pod is to change its file.

2. Watch a valid static Pod appear

Write our own test manifest as /etc/kubernetes/manifests/prepium-static.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: prepium-static
  namespace: default
spec:
  containers:
  - name: ticker
    image: busybox:1.36
    command: ["sh", "-c", "while true; do date; sleep 10; done"]

The kubelet scans the directory periodically, so within a short while crictl ps on the node lists a ticker container, and kubectl get pods shows prepium-static-<node>. Move the file out of the directory and both disappear.

3. Break it two ways and read the evidence

A file the kubelet cannot decode. Indent containers: wrongly, or misspell apiVersion, and save. No container starts and no mirror Pod appears, and nothing in the API explains why. Look for the reason in the kubelet journal:

journalctl -u kubelet --since "10 min ago" | grep -i prepium-static

A container that starts and dies. Restore valid YAML but change the command to run a binary that does not exist in the image. Now the Pod exists, yet the container keeps exiting and its ATTEMPT count rises:

crictl ps -a | grep ticker          # STATE Exited, ATTEMPT increasing
crictl logs <container-id>          # last output before it died

A broken control-plane component behaves the same way: either it never appears in crictl ps -a (look at the kubelet journal) or it appears as Exited with a climbing attempt count (look at crictl logs for whatever the component printed before it exited). Fix the manifest, save, and wait for the kubelet to recreate the container. When the API server is back, kubectl get nodes answers again.

4. Edit safely

Keep backups outside the directory, for example in /root/manifest-backups/. The official docs warn that a copy such as kube-apiserver.yaml.bak left beside the original is read too, and two files defining the same Pod name give undefined behaviour, possibly running the stale copy.

Common mistakes

Example checkEvidence
Kubelet reads the right directorystaticPodPath in the kubelet config
Component container is stablecrictl ps shows it Running; ATTEMPT no longer rising
Control plane answerskubectl get nodes works; mirror Pods Running in kube-system
No stray filesOnly intended manifests in the directory

Cleanup: rm /etc/kubernetes/manifests/prepium-static.yaml; the kubelet removes the Pod. References: Create static Pods, Debugging Kubernetes nodes with crictl, kubeadm implementation details. Next, try container runtimes and CRI or kubeadm upgrades.

Exam
CKA
Domain
Troubleshooting
Grading
Programmatic · partial credit

What this tests

Diagnose failing nodes, control-plane components, the kubelet, and broken cluster networking. On the CKA exam, Troubleshooting tasks are graded purely on what you build in the cluster - not multiple choice - so the only way to get faster is to do them on a real cluster against a clock.

Practice it for real

The public description lets you study the task before signing up. Full access includes every live lab. Six selected CKA scenarios are included in Free Practice, with five shared sessions each week. You solve the task in a real terminal, hit validate, and a programmatic checker scores exactly what you got right and wrong (with partial credit). You can open the solution while practising, then retry and use the failed checks to improve your score.

Related CKA tasks