Kubernetes troubleshooting checklist

Troubleshooting is 30% of the CKA. The fastest way through is the same order every time: read what the cluster already tells you, then go one level lower.

Last reviewed . Paths and labels are those of a kubeadm cluster.

A node is NotReady

Usually the kubelet: stopped, misconfigured or unable to reach the API server.

  1. See which node and since when
    kubectl get nodes -o wide
  2. Read the node's conditions and recent events
    kubectl describe node node01
  3. On the node: is the kubelet running?
    systemctl status kubelet
  4. Why it stopped or keeps restarting: read the last lines first
    journalctl -u kubelet --no-pager | tail -30
  5. Check the files it names: config, kubeconfig, certificates
    cat /var/lib/kubelet/config.yaml
  6. Is the container runtime up?
    systemctl status containerd
  7. Fix, then restart and confirm
    systemctl daemon-reload && systemctl restart kubelet

kubectl can't reach the cluster

On kubeadm, the API server and etcd are static Pods. When they're down, kubectl can't tell you why, so go one level lower.

  1. Is it the cluster or your kubeconfig? Check server and context
    kubectl config view --minify
  2. Which control-plane containers are running or exiting?
    crictl ps -a
  3. Why a container exits
    crictl logs <container-id>
  4. If no container exists at all, the manifest may not parse
    journalctl -u kubelet | grep -i error | tail
  5. Compare flags, paths and ports with a known-good value
    grep -n -- '--etcd\|--advertise\|--client-ca' /etc/kubernetes/manifests/kube-apiserver.yaml
  6. Wait for the kubelet to pick up your fix, then confirm
    kubectl get pods -n kube-system

A Pod is Pending

The scheduler can't place it, or something it needs doesn't exist yet.

  1. Read the scheduler's reason in the events
    kubectl describe pod <pod> -n <ns>
  2. Not enough CPU or memory? Compare requests with what's free
    kubectl describe node node01 | grep -A8 Allocated
  3. Taints the Pod doesn't tolerate
    kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
  4. Node selectors or affinity that match no node
    kubectl get nodes --show-labels
  5. An unbound PersistentVolumeClaim
    kubectl get pvc -n <ns>
  6. Is the scheduler itself running?
    kubectl get pods -n kube-system -l component=kube-scheduler

A Pod crashes or won't start

Look at the container's last words before changing anything.

  1. The status tells you the category
    kubectl get pod <pod> -n <ns>
  2. ImagePullBackOff: check the image name, tag and pull secret
    kubectl describe pod <pod> -n <ns>
  3. CrashLoopBackOff: read the log of the previous attempt
    kubectl logs <pod> -n <ns> --previous
  4. OOMKilled: compare the memory limit with real use
    kubectl get pod <pod> -n <ns> -o jsonpath='{.status.containerStatuses[*].lastState}'
  5. Probes failing: check path, port and timing against the app
    kubectl get pod <pod> -n <ns> -o yaml | grep -A6 Probe
  6. Missing ConfigMap, Secret or volume: events say which
    kubectl get events -n <ns> --sort-by=.lastTimestamp

A Service doesn't answer

Work from the Pods outwards: Pods, selector, endpoints, ports, policy.

  1. Are the backing Pods Running and Ready?
    kubectl get pods -n <ns> -o wide --show-labels
  2. Does the Service selector match their labels?
    kubectl get svc <svc> -n <ns> -o wide
  3. Does it have endpoints? None means selector or readiness
    kubectl get endpointslices -n <ns> -l kubernetes.io/service-name=<svc>
  4. Does targetPort match the port the container listens on?
    kubectl get svc <svc> -n <ns> -o yaml
  5. Is a NetworkPolicy blocking it?
    kubectl get netpol -n <ns>
  6. Test from inside the cluster
    kubectl run t --rm -it --image=busybox:1.36 --restart=Never -- wget -qO- -T2 http://<svc>.<ns>

Names don't resolve

Usually CoreDNS isn't running, its Service has no endpoints, or its Corefile is wrong.

  1. Are the CoreDNS Pods running?
    kubectl get pods -n kube-system -l k8s-app=kube-dns
  2. Does the kube-dns Service have endpoints?
    kubectl get endpointslices -n kube-system -l kubernetes.io/service-name=kube-dns
  3. What does CoreDNS log?
    kubectl logs -n kube-system -l k8s-app=kube-dns
  4. Is the Corefile sane?
    kubectl get cm coredns -n kube-system -o yaml
  5. Resolve from a Pod
    kubectl run t --rm -it --image=busybox:1.36 --restart=Never -- nslookup kubernetes.default

Practise on broken clusters

Each of these failures has a lab: we break a real cluster in exactly this way and check that you fixed it.