CKA Cheat Sheet.
Review the key concepts, then download the PDF for offline study.
Download the PDFQuick facts
the numbers to know before exam dayFull write-up
the complete guide, in proseThe CKA is two hours in a live cluster with no multiple choice — you either produce the object or you don't. Everything below is the working set: the aliases that buy you time, the imperative one-liners that write YAML for you, and the diagnostic sequences for the 30% of the exam that is troubleshooting.
Exam at a glance
| Item | Detail |
|---|---|
| Administered by | CNCF / The Linux Foundation |
| Format | Online, proctored, performance-based tasks in a live cluster |
| Time limit | 2 hours |
| Passing score | 66% |
| Cost | $445, includes a second attempt (one free retake) |
| Scheduling window | 12 months from purchase |
| Certification validity | 2 years |
| Cluster version tested | Kubernetes v1.35 |
| Included simulator | Killer.sh — 2 attempts, 36 hours each |
Domain weights
| Domain | Weight | What it actually means |
|---|---|---|
| Troubleshooting | 30% | Broken nodes, pods, DNS, control plane |
| Cluster Architecture, Installation & Configuration | 25% | kubeadm, etcd, RBAC, upgrades |
| Services & Networking | 20% | Services, Ingress, Gateway API, NetworkPolicy |
| Workloads & Scheduling | 15% | Deployments, rollouts, affinity, taints |
| Storage | 10% | PV, PVC, StorageClass |
Terminal setup: spend the first 60 seconds here
Type this before you touch a task. It pays for itself by question three.
source <(kubectl completion bash)
alias k=kubectl
complete -o default -F __start_kubectl k
export do="--dry-run=client -o yaml"
export now="--force --grace-period=0"
| Shortcut | Expands to | Use |
|---|---|---|
k | kubectl | Saves ~6 keystrokes per command |
$do | --dry-run=client -o yaml | k run nginx --image=nginx $do > pod.yaml |
$now | --force --grace-period=0 | k delete pod nginx $now — no 30s wait |
| Namespace pin | k config set-context --current --namespace=<ns> | Stops -n mistakes |
| Context switch | k config use-context <ctx> | Run the line given in every question |
| Vim | :set et ts=2 sw=2 | YAML indentation survives |
Imperative commands that write your YAML
The core technique: never hand-write a manifest. Generate a skeleton with $do, redirect to a file, edit the two fields the question actually asks for, then k apply -f.
| Object | Command |
|---|---|
| Pod | k run nginx --image=nginx --port=80 --labels=app=web $do > pod.yaml |
| Pod with a command | k run busybox --image=busybox --command $do -- sleep 3600 |
| Throwaway shell | k run tmp -it --rm --restart=Never --image=busybox -- sh |
| Deployment | k create deployment web --image=nginx --replicas=3 --port=80 $do |
| Job | k create job pi --image=busybox -- echo done · --from=cronjob/report |
| CronJob | k create cronjob hello --image=busybox --schedule="*/1 * * * *" -- echo hi |
| Service | k expose deployment web --port=80 --target-port=8080 --type=NodePort --name=web-svc |
| Ingress | k create ingress web --class=nginx --rule="foo.com/bar*=web-svc:80,tls=my-cert" |
| ConfigMap | k create cm app-cfg --from-literal=KEY=val --from-file=./app.conf |
| Secret | k create secret generic db --from-literal=pass=s3cr3t · tls · docker-registry |
| Namespace / SA | k create ns dev · k create sa builder |
| Scale / image | k scale deployment web --replicas=5 · k set image deployment/web nginx=nginx:1.27 |
| Rollout | k rollout status|history|undo deployment/web · --to-revision=2 |
| Edit live | k edit deploy web · k patch svc web -p '{"spec":{"type":"NodePort"}}' |
Reading the cluster fast
| Need | Command |
|---|---|
| Field names you forgot | k explain pod.spec.tolerations --recursive |
| Sort by restarts | k get pods --sort-by='.status.containerStatuses[0].restartCount' |
| Events in time order | k get events -A --sort-by=.metadata.creationTimestamp |
| Resource usage | k top nodes · k top pods --sort-by=cpu |
Troubleshooting — 30% of the exam
Work the same ladder every time: get for state, describe for events, logs for the application, journalctl for the node.
Node NotReady
| Step | Command | Looking for |
|---|---|---|
| 1 | k get nodes -o wide · k describe node <node> | Conditions: MemoryPressure, DiskPressure, PIDPressure; taints |
| 2 | ssh <node>; systemctl status kubelet | Service dead or crash-looping |
| 3 | journalctl -u kubelet -f · journalctl -xeu kubelet | Bad config path, bad cert, runtime down |
| 4 | systemctl status containerd · crictl ps | Runtime socket unavailable |
| 5 | systemctl daemon-reload && systemctl restart kubelet | After fixing /var/lib/kubelet/config.yaml |
Pod stuck in Pending
k describe pod <pod>— read the Events block first; the scheduler writes the reason there.insufficient cpu→ lowerresources.requestsor free capacity.had untolerated taint→ add a toleration, ork taint nodes <node> key=value:NoSchedule-.didn't match Pod's node affinity/selector→ fixnodeSelector, ork label node <node> disk=ssd.unbound immediate PersistentVolumeClaims→ no matching PV; checkk get pvc,pv,sc.- No events at all → scheduler is down:
k get pods -n kube-system.
CrashLoopBackOff
| Command | Purpose |
|---|---|
k logs <pod> --previous | Logs from the container that just died — the most useful flag on the exam |
k logs <pod> -c <container> | Multi-container pods and initContainers |
k describe pod <pod> | Last State: Terminated, Exit Code, OOMKilled |
k get pod <pod> -o yaml | Bad command/args, missing env, failing probes |
k debug <pod> -it --image=busybox --target=<c> | Ephemeral container in a pod with no shell |
ImagePullBackOff / ErrImagePull
k describe pod <pod>→ Events name the exact failure: typo, tag not found, or401 Unauthorized.- Auth failure → create a
docker-registrysecret, then addspec.imagePullSecrets. - Air-gapped node → verify with
crictl pull <image>andcrictl images.
Service not resolving or not routing
| Step | Command | Failure it isolates |
|---|---|---|
| 1 | k get svc <svc> -o yaml | Wrong port/targetPort, wrong type |
| 2 | k get endpointslices -l kubernetes.io/service-name=<svc> | Empty = selector matches no ready pod |
| 3 | k get pods -l <selector> --show-labels | Label mismatch between Service and Pods |
| 4 | k run tmp -it --rm --restart=Never --image=busybox -- nslookup <svc>.<ns>.svc.cluster.local | DNS resolution |
| 5 | k get pods -n kube-system -l k8s-app=kube-dns · k logs -n kube-system <coredns-pod> | CoreDNS down or misconfigured |
| 6 | k get daemonset -n kube-system kube-proxy | kube-proxy not running on the node |
| 7 | wget -qO- <clusterIP>:<port> from a pod | IP works, name doesn't → DNS; neither → NetworkPolicy or CNI |
Control plane down
Control-plane components are static pods. If kubectl itself fails, go to the node.
crictl ps -athencrictl logs <container-id>— the only way to read a kube-apiserver that won't start.- Manifests:
/etc/kubernetes/manifests/—kube-apiserver.yaml,kube-controller-manager.yaml,kube-scheduler.yaml,etcd.yaml. - Edit the file and the kubelet restarts the pod — no
apply. Never keep backups in that directory. - Mirror pod name is
<pod>-<node>; path set bystaticPodPathin/var/lib/kubelet/config.yaml. - Certs:
kubeadm certs check-expiration·kubeadm certs renew all(/etc/kubernetes/pki).
kubeadm cluster lifecycle
| Task | Command |
|---|---|
| Init control plane | kubeadm init --pod-network-cidr=<cidr> --apiserver-advertise-address=<ip> |
| Set up kubeconfig | mkdir -p ~/.kube && cp -i /etc/kubernetes/admin.conf ~/.kube/config |
| Recover a join command | kubeadm token create --print-join-command · kubeadm token list (--ttl 24h0m0s) |
| Join a worker | kubeadm join <endpoint> --token <token> --discovery-token-ca-cert-hash sha256:<hash> |
| Recompute the CA hash | openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //' |
| Join a control plane | add --control-plane --certificate-key <key> |
| Reset a node | kubeadm reset |
Upgrade order — control plane first, one node at a time
| # | Control plane node | Worker node |
|---|---|---|
| 1 | apt-mark unhold kubeadm && apt-get install -y kubeadm='1.35.x-*' && apt-mark hold kubeadm | same |
| 2 | kubeadm upgrade plan | — |
| 3 | kubeadm upgrade apply v1.35.x (first CP only; others use kubeadm upgrade node) | kubeadm upgrade node |
| 4 | kubectl drain <node> --ignore-daemonsets | same (add --delete-emptydir-data if needed) |
| 5 | apt-mark unhold kubelet kubectl && apt-get install -y kubelet='1.35.x-*' kubectl='1.35.x-*' && apt-mark hold kubelet kubectl | same |
| 6 | systemctl daemon-reload && systemctl restart kubelet | same |
| 7 | kubectl uncordon <node> | same |
Do not forget step 7. A node left cordoned is the most common silent point loss on upgrade tasks.
etcd backup and restore
The cert flags are mandatory, and always the same three files under /etc/kubernetes/pki/etcd/.
ETCDCTL_API=3 etcdctl --endpoints=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 \
snapshot save /opt/snapshot.db
| Task | Command |
|---|---|
| Verify a snapshot | same flags + snapshot status /opt/snapshot.db |
| Restore | ETCDCTL_API=3 etcdctl snapshot restore /opt/snapshot.db --data-dir /var/lib/etcd-restore (or etcdutl snapshot restore) |
| Point etcd at restored data | Edit the etcd-data volume hostPath in /etc/kubernetes/manifests/etcd.yaml; kubelet restarts the pod |
| Find the real endpoint/certs | k describe pod etcd-<node> -n kube-system |
Scheduling controls
| Mechanism | Syntax | Behaviour |
|---|---|---|
| Add taint | k taint nodes node1 key1=value1:NoSchedule | Repels pods without a matching toleration |
| Remove taint | k taint nodes node1 key1=value1:NoSchedule- | Trailing - removes |
NoSchedule | effect | Blocks new pods; running pods stay |
PreferNoSchedule | effect | Soft preference only |
NoExecute | effect | Evicts non-tolerating pods immediately; tolerationSeconds delays eviction |
| Toleration | key, operator: Equal|Exists, value, effect, tolerationSeconds | Exists with no key tolerates everything |
| Built-in taints | node.kubernetes.io/ + not-ready, unreachable, memory-pressure, disk-pressure, pid-pressure, unschedulable, network-unavailable | Added by the node controller |
| nodeSelector | spec.nodeSelector: {disk: ssd} | Hard, exact-match only |
| Node affinity (hard) | requiredDuringSchedulingIgnoredDuringExecution | Pod stays Pending if unmatched |
| Node affinity (soft) | preferredDuringSchedulingIgnoredDuringExecution + weight | Tries, then places anywhere |
| Affinity operators | In, NotIn, Exists, DoesNotExist, Gt, Lt | Superset of nodeSelector |
RBAC
| Task | Command |
|---|---|
| Namespaced Role | k create role pod-reader --verb=get,list,watch --resource=pods -n dev |
| ClusterRole | k create clusterrole node-reader --verb=get,list,watch --resource=nodes |
| Restrict to one object | add --resource-name=my-pod |
| Bind to a user | k create rolebinding rb --role=pod-reader --user=jane -n dev |
| Bind to a ServiceAccount | k create rolebinding rb --role=pod-reader --serviceaccount=dev:builder -n dev |
| Cluster-wide binding | k create clusterrolebinding crb --clusterrole=node-reader --group=managers |
| ClusterRole in one namespace | k create rolebinding rb --clusterrole=view --serviceaccount=dev:builder -n dev |
| Test it | k auth can-i list secrets --as=jane -n dev · --as=system:serviceaccount:dev:builder |
Built-in ClusterRoles: view (read-only, no Secrets, no RBAC objects), edit (read/write workloads and Secrets, no RBAC objects), admin (namespace admin including Roles/RoleBindings), cluster-admin (everything).
Storage
| Field | Values |
|---|---|
accessModes | ReadWriteOnce (RWO), ReadOnlyMany (ROX), ReadWriteMany (RWX), ReadWriteOncePod (RWOP) |
persistentVolumeReclaimPolicy | Retain, Delete (default for dynamic), Recycle (deprecated) |
| PV phases | Available → Bound → Released / Failed |
volumeBindingMode (SC) | Immediate, WaitForFirstConsumer |
allowVolumeExpansion (SC) | true — required before you can grow a PVC |
| Binding | A PVC binds only if capacity, accessModes and storageClassName all match; diagnose with k describe pvc |
Services and networking quick reference
| Type | Reach | Note |
|---|---|---|
ClusterIP | In-cluster only | Default |
NodePort | <nodeIP>:<30000-32767> | Also gets a ClusterIP |
LoadBalancer | External | Superset of NodePort |
ExternalName | CNAME | No proxying, no selector |
| Headless | clusterIP: None | DNS returns pod IPs — StatefulSets |
| DNS name | <svc>.<ns>.svc.cluster.local | |
| NetworkPolicy | Additive allow-list; podSelector: {} + policyTypes: [Ingress] denies all ingress | |
Find it in the docs fast
Documentation is allowed: kubernetes.io/docs and its search box, kubernetes.io/blog, helm.sh/docs, and gateway-api.sigs.k8s.io — but you must not open external search results.
| If the task is… | Search this on kubernetes.io/docs |
|---|---|
| Any manifest skeleton | Use k explain instead — faster than the docs |
| etcd snapshot | "Operating etcd clusters for Kubernetes" |
| Cluster upgrade | "Upgrading kubeadm clusters" |
| PV / PVC | "Configure a Pod to Use a PersistentVolume for Storage" |
| NetworkPolicy | "Network Policies" — has a copy-paste default-deny |
| Ingress / Gateway API | "Ingress"; gateway-api.sigs.k8s.io for HTTPRoute |
| Affinity and taints | "Assigning Pods to Nodes", "Taints and Tolerations" |
| RBAC | "Using RBAC Authorization" |
Exam-day checklist
- Run the
kubectl config use-contextline printed with every question — wrong cluster scores zero. - Pin the namespace from the question text with
set-context --current --namespace. - Flag and skip anything over ~7 minutes; tasks are scored independently.
- Verify after every task:
k get <resource> -o wide; for pods wait forRunning/1/1. - Write snapshot and manifest files to the exact path the question specifies.
- After any drain,
k uncordon. After any node fix, confirmk get nodesshowsReady.
Frequently asked questions
How long is the CKA exam and how many tasks will I face?
You get 2 hours (120 minutes) to complete the CKA. In that time you'll work through 15–20 performance-based tasks — there are no multiple-choice questions. Every task is solved from a command line running Linux, and the exam is remotely proctored via streaming audio, video, and screen sharing. Because roughly 120 minutes are split across up to 20 hands-on tasks, budgeting your time is critical: plan for about 5–7 minutes per task on average, flag and skip anything that stalls you, and circle back at the end. Practicing with a fast alias setup (like `alias k=kubectl`) and knowing imperative commands cold will save precious minutes.
What score do I need to pass the CKA, and when will I get my results?
You need to earn a score of 66% or above to pass the CKA. Since the exam is scored on partial credit across 15–20 tasks, you don't have to complete every task perfectly — nailing the domains with the heaviest weighting matters more than finishing everything. Your score report is emailed within 24 hours of completing the exam. And if you don't pass the first time, your registration includes one free retake, so there's a built-in safety net.
Which CKA domains should I study hardest?
The CKA curriculum is organized into 5 domains, and they're not weighted equally. Troubleshooting is the most heavily weighted domain at 30%, followed by Cluster Architecture, Installation & Configuration at 25%, Services & Networking at 20%, Workloads & Scheduling at 15%, and Storage at 10%. Because Troubleshooting and Cluster Architecture together account for 55% of your score, they deserve the deepest practice — drill on diagnosing failing pods, broken kubelets, and node issues, plus cluster setup and upgrades. Storage, at just 10%, still matters but yields the fewest points per hour of study, so weight your prep toward the top three domains.
What does the CKA cost, which Kubernetes version does it use, and how long is it valid?
The CKA exam costs $445 USD, and that price includes one free retake — so a single registration effectively gives you two attempts. The exam environment currently runs Kubernetes v1.35, and the published curriculum aligns with that same version, so you should practice against Kubernetes 1.35 and read the docs for that release to avoid version-specific gotchas. Once you pass, the certification is valid for 2 years, after which you'll need to recertify to keep your credential current. It's an online, proctored, performance-based test administered through PSI's Bridge platform using the PSI Secure Browser, so make sure your machine meets the proctoring requirements before exam day.
Sources
- 1.Certified Kubernetes Administrator (CKA) Certification — Cloud Native Computing Foundation (CNCF) (accessed Jul 18, 2026)
- 2.Certified Kubernetes Administrator (CKA) — Training & Certification — The Linux Foundation (accessed Jul 18, 2026)
- 3.Frequently Asked Questions: CKA, CKAD & CKS (Candidate-Facing Docs) — The Linux Foundation (accessed Jul 18, 2026)
- 4.CNCF Curriculum Repository — CKA_Curriculum_v1.35 — Cloud Native Computing Foundation (CNCF) (accessed Jul 18, 2026)
- 5.Important Instructions: CKA and CKAD (Candidate-Facing Docs) — The Linux Foundation (accessed Jul 18, 2026)
Official sources
Primary documents used to verify the exam details shown on this page.
- Certified Kubernetes Administrator (CKA) CertificationCloud Native Computing Foundation (CNCF)cncf.io
- Frequently Asked Questions: CKA, CKAD & CKS (Candidate-Facing Docs)The Linux Foundationdocs.linuxfoundation.org
- Certified Kubernetes Administrator (CKA) — Training & CertificationThe Linux Foundationtraining.linuxfoundation.org
- CNCF Curriculum Repository — CKA_Curriculum_v1.35Cloud Native Computing Foundation (CNCF)github.com
- Important Instructions: CKA and CKAD (Candidate-Facing Docs)The Linux Foundationdocs.linuxfoundation.org
Last verified against the official exam content outline: