The Certified Kubernetes Administrator is different from every other exam in this track: there are no multiple-choice questions. You get a terminal, several live clusters, and a list of tasks — create this, fix that, find out why this pod is not scheduling — and two hours to finish as many as you can. It is a test of fluency, not recall. People who know Kubernetes well fail it by being slow; people who practise the specific tasks until they are automatic pass it comfortably. This guide covers the exam environment and rules, the five domains as published by the CNCF with the tasks each one turns into, the speed techniques that decide the outcome, and a six-week plan that is mostly typing. Exam facts were checked against the CNCF and Linux Foundation pages in September 2026; confirm before you book, because the environment version changes quarterly.
- Describe the CKA exam format, environment, rules and scoring
- Map the five domains to the concrete tasks the exam sets
- Work fast in the exam terminal: aliases, imperative commands, generating manifests, using the docs efficiently
- Troubleshoot cluster components, nodes, networking and workloads systematically
- Follow a six-week plan built around timed task practice
The exam at a glance
The CKA is a performance-based exam: two hours, a proctored browser-based environment (PSI's secure browser with a remote desktop and terminal), around fifteen to twenty tasks of varying weight, across several clusters that you switch between with a provided kubectl config use-context command at the start of each task. The passing score is 66%. Registration costs 445 USD and includes one free retake and two sessions of the killer.sh simulator, which reproduces the environment and difficulty closely. The certification is valid for two years. The environment tracks Kubernetes releases; it is currently on v1.35, so practise on a recent version.
| Domain | Weight | What the tasks look like |
|---|---|---|
| Cluster Architecture, Installation & Configuration | 25% | RBAC, kubeadm install and upgrade, etcd backup and restore, managing cluster components, installing a CNI, Helm and Kustomize, operators and CRDs |
| Workloads & Scheduling | 15% | Deployments and rollouts, ConfigMaps and Secrets, scaling and autoscaling, resource requests and limits, node affinity, taints and tolerations, self-healing |
| Services & Networking | 20% | Services and endpoints, Ingress and Gateway API, NetworkPolicy, CoreDNS, pod-to-pod connectivity |
| Storage | 10% | StorageClasses, PersistentVolumes and claims, access and reclaim modes, dynamic provisioning |
| Troubleshooting | 30% | Failed pods, node NotReady, control-plane components, networking, application logs and events |
You may use the official Kubernetes documentation (kubernetes.io and its subdomains) in a browser tab inside the exam environment, and nothing else. Knowing where things are in the docs is a skill to practise, not a fallback.
Speed: the skill that decides the result
Two hours for roughly seventeen tasks is about seven minutes each, including reading, switching context and verifying. Every second spent typing a manifest by hand or scrolling the docs is a second not spent on the next task. The techniques below are what separate passing from failing; make them reflexes before exam day.
alias k=kubectl
export do="--dry-run=client -o yaml"
export now="--force --grace-period=0"
source <(kubectl completion bash) && complete -o default -F __start_kubectl k
# generate manifests instead of writing them
k run web --image=nginx:1.27 --port=80 $do > pod.yaml
k create deploy api --image=ghcr.io/acme/api:1.4 --replicas=3 $do > deploy.yaml
k expose deploy api --port=80 --target-port=8080 --type=ClusterIP $do > svc.yaml
k create cm app-config --from-literal=LOG_LEVEL=info $do > cm.yaml
k create secret generic db --from-literal=password=REPLACE $do > secret.yaml
k create ingress web --rule="shop.example.com/*=web:80" $do > ing.yaml
k create job once --image=busybox -- /bin/sh -c 'echo hi' $do > job.yaml
k create cronjob nightly --image=busybox --schedule='0 2 * * *' -- date $do > cj.yaml- Imperative first: create with
kubectl create/run/expose, thenkubectl editor patch the one field the task needs. Write YAML from scratch only for things with no generator (NetworkPolicy, PV/PVC, RBAC beyond the basics), and copy those from the docs. - Explain, not search:
kubectl explain deploy.spec.template.spec.containers.resources --recursivegives field names faster than the docs. - Verify every task:
k get,k describe,k logs,k exec ... -- curl. Points are for end state, and a typo in a namespace is zero points. - Context and namespace: run the task's
use-contextline every time, and use-nexplicitly; wrong-cluster answers are the most common way to lose easy points. - Triage: read all tasks in the first two minutes, do the quick high-weight ones first, flag the long ones (kubeadm upgrade, etcd restore) for later, and skip anything that stalls you for more than ten minutes.
Use vim with set expandtab tabstop=2 shiftwidth=2 in ~/.vimrc (or type :set et ts=2 sw=2) so pasted YAML indents correctly. Broken indentation is the most common self-inflicted wound.
Cluster architecture, installation and configuration (25%)
This domain has the longest tasks and the most points. RBAC: create Roles, ClusterRoles, RoleBindings and ClusterRoleBindings for users and service accounts, and verify with kubectl auth can-i. kubeadm: initialise a control plane, join a worker, and — a near-certain task — upgrade a node one minor version: drain, upgrade kubeadm, kubeadm upgrade apply (control plane) or upgrade node (worker), upgrade kubelet and kubectl, restart kubelet, uncordon. etcd: take a snapshot with etcdctl using the certificates from the static pod manifest, and restore one to a new data directory, then point the etcd static pod at it. Also: static pods in /etc/kubernetes/manifests, certificate locations, installing a CNI from a manifest, using Helm to install a chart and Kustomize to build overlays, and finding CRDs and their instances.
# --- upgrade control plane to 1.35.x (adjust the version to the task) ---
k drain cp-node --ignore-daemonsets --delete-emptydir-data
sudo apt-mark unhold kubeadm && sudo apt-get install -y kubeadm=1.35.1-1.1 && sudo apt-mark hold kubeadm
sudo kubeadm upgrade plan
sudo kubeadm upgrade apply v1.35.1 -y
sudo apt-mark unhold kubelet kubectl && sudo apt-get install -y kubelet=1.35.1-1.1 kubectl=1.35.1-1.1 && sudo apt-mark hold kubelet kubectl
sudo systemctl daemon-reload && sudo systemctl restart kubelet
k uncordon cp-node
# workers: same, but 'kubeadm upgrade node' instead of 'upgrade apply'
# --- etcd backup ---
sudo ETCDCTL_API=3 etcdctl snapshot save /opt/etcd-backup.db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# --- etcd restore to a new directory, then point the static pod at it ---
sudo ETCDCTL_API=3 etcdctl snapshot restore /opt/etcd-backup.db --data-dir /var/lib/etcd-restored
sudo sed -i 's#/var/lib/etcd#/var/lib/etcd-restored#' /etc/kubernetes/manifests/etcd.yaml # the hostPath volume
# kubelet restarts the etcd static pod; watch with: sudo crictl ps | grep etcdThe certificate paths and flags for etcdctl are in the etcd static pod manifest (/etc/kubernetes/manifests/etcd.yaml); reading them from there is faster and safer than remembering. The docs page "Operating etcd clusters for Kubernetes" has the exact commands and is allowed.
Workloads, networking and storage (15% + 20% + 10%)
Workloads: create and scale Deployments, perform and undo rollouts (rollout status, rollout undo, rollout history), set image versions, configure ConfigMaps and Secrets as environment variables or mounted files, set resource requests and limits (and know that a pod exceeding its memory limit is OOMKilled, while unschedulable requests leave it Pending), add a liveness or readiness probe, schedule with nodeSelector, node affinity, taints and tolerations, and run DaemonSets. Horizontal Pod Autoscaler tasks require the metrics server to be present.
Networking: expose workloads with ClusterIP, NodePort and LoadBalancer Services and confirm endpoints exist (an empty Endpoints list means the selector does not match the pod labels — the most common Service bug); create an Ingress with host and path rules and know that an ingress controller must exist; write a NetworkPolicy that allows only specific ingress or egress (default deny, then allow by pod or namespace selector, and remember DNS egress); check CoreDNS with a busybox nslookup; know the Gateway API resources (GatewayClass, Gateway, HTTPRoute) at the level of creating an HTTPRoute for a host. Storage: create a PersistentVolume (hostPath or local for the exam), a PersistentVolumeClaim that binds to it (matching storage class, access mode and size), mount it in a pod, and understand reclaim policies (Retain versus Delete), access modes (RWO, ROX, RWX) and dynamic provisioning through a StorageClass with volumeBindingMode.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow-frontend
namespace: shop
spec:
podSelector:
matchLabels:
app: api
policyTypes: [Ingress, Egress]
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53Troubleshooting (30%)
The heaviest domain rewards a fixed procedure. For a pod: k get pod -o wide (status, restarts, node), k describe pod (events: image pull, scheduling, probe failures, mounts), k logs --previous (why it crashed), k get events --sort-by=.metadata.creationTimestamp. For a node NotReady: k describe node (conditions, taints), then on the node systemctl status kubelet, journalctl -u kubelet -f, check /var/lib/kubelet/config.yaml and the container runtime (crictl ps, systemctl status containerd). For control-plane components: they are static pods; check crictl ps -a and /etc/kubernetes/manifests/*.yaml for a broken flag or a wrong path, and kubectl may not even work if the API server is down, so use crictl logs. For networking: Service without endpoints (labels), NetworkPolicy blocking traffic (test with a temporary pod), CoreDNS pods and config, kube-proxy DaemonSet.
k get pods -A -o wide | grep -vE 'Running|Completed' # what is unhealthy anywhere
k describe pod POD -n NS | sed -n '/Events/,$p' # the events section only
k logs POD -n NS --previous --tail=50 # crash reason
k get events -n NS --sort-by=.metadata.creationTimestamp | tail -20
k get nodes; k describe node NODE | grep -A8 Conditions # node health
ssh NODE 'sudo systemctl status kubelet --no-pager; sudo journalctl -u kubelet -n 50 --no-pager'
ssh NODE 'sudo crictl ps -a; sudo crictl logs $(sudo crictl ps -a -q --name kube-apiserver | head -1) 2>&1 | tail -20'
k get svc,ep -n NS # empty endpoints = selector mismatch
k run tmp --rm -it --image=busybox:1.36 --restart=Never -- sh # then: nslookup api.shop.svc.cluster.local; wget -qO- http://api.shop:80Do not fix symptoms. A pod stuck Pending with an Insufficient cpu event needs a smaller request or a bigger node, not a restart; a node NotReady because kubelet points at the wrong certificate needs the config fixed, not a reboot. Read the event or log line that names the cause, then change that.
The six-week plan
| Week | Focus | Practice |
|---|---|---|
| 1 | Environment: kind or a two-node kubeadm cluster on VMs; aliases, generators, explain, vim; core objects | 30 timed tasks: pods, deployments, services, configmaps, secrets — under 5 min each |
| 2 | Scheduling, probes, resources, rollouts, DaemonSets, HPA; storage: PV/PVC/StorageClass | Tasks from the curriculum's workloads and storage sections, twice each |
| 3 | Networking: Services, Ingress, Gateway API, NetworkPolicy, CoreDNS | Write five NetworkPolicies from the docs page without copying twice |
| 4 | Cluster admin: RBAC, kubeadm upgrade, etcd backup/restore, static pods, Helm, Kustomize, CRDs | Upgrade a real kubeadm cluster; back up and restore etcd three times |
| 5 | Troubleshooting drills: break the cluster on purpose (kubelet config, API server flag, CNI, Service selector) | Ten breaks, each fixed with the procedure above and timed |
| 6 | Full simulations | Both killer.sh sessions; review every missed task; rest the day before |
Build tasks from the open-source curriculum on GitHub and from the practice repositories the community maintains; the point is volume and timing, not novelty. Keep a log of every task that took over seven minutes and drill it. Schedule the exam for the end of week six at a time of day you are sharp, run the PSI compatibility check a week before, clear the desk, and on the day set up aliases first, read all tasks, and start with the ones you can finish in three minutes.