Online resources that will help you prepare for taking the Kubernetes Certified Administrator Certification exam.
Beyond the curriculum links, these cover method: how to diagnose problems and how to study.
- TROUBLESHOOTING.md - the first-moves reflex, a break-and-fix scenario bank, symptom table and practice questions for the 30% Troubleshooting domain
- Common misconceptions - things study material often gets wrong
- Exam-day tactics - context switching, generating YAML, verifying, and using the simulator sessions well
- Study method - a learn, break, fix, log loop, with note templates
- Linux Foundation LF ACE path - how LFS158, LFS253 and LFS258 map to the CKA domains
Disclaimer: This is not likely a comprehensive list as the exam will be a moving target with the fast pace of k8s development - please make a pull request if there something wrong, should be added, or updated.
I tried to restrict the cross references of resources to kubernetes.io. Youtube videos and other blog resources are optional; however, I still found them useful in my k8s learning journey.
Ensure you have the right version of Kubernetes documentation selected (v1.35 as of the September 2026 exam environment) especially for API objects and annotations.
TL;DR: practice practice practice
These are the exam objectives you review and understand in order to pass the test.
- CNCF Exam Curriculum repository - the authoritative source. The current file is CKA_Curriculum_v1.35.pdf.
| Exam environment | Kubernetes v1.35 |
| Duration | 2 hours |
| Passing score | 66% |
| Included | 2 exam attempts, 2 Killer.sh simulator sessions |
| Validity | 2 years |
The exam environment is aligned with the most recent Kubernetes minor release within roughly 4 to 8 weeks of that release, so confirm the version in the CKA/CKAD/CKS FAQ and on the CKA certification page before you sit it.
If you studied from an older version of this README or an older course, these are the differences that matter. Items marked new were not in the previous curriculum at all.
- Helm and Kustomize are now an explicit, hands-on Cluster Architecture item, not the old "awareness of manifest management and common templating tools" bullet under Workloads.
- CRDs and operators are new: you are expected to install and configure an operator, not just recognise the pattern.
- Extension interfaces (CNI, CSI, CRI) are new as a concept item. The old "choose an appropriate CNI plugin" bullet under Networking was folded into this.
- Gateway API is new under Services and Networking, alongside Ingress rather than replacing it.
- Network Policies are now called out explicitly ("define and enforce"), where previously they were not listed for CKA at all.
- Workload autoscaling (HorizontalPodAutoscaler) is new under Workloads and Scheduling.
- Pod admission and scheduling replaces the narrower "understand how resource limits can affect Pod scheduling".
- Dropped: "provision underlying infrastructure" became "prepare underlying infrastructure", "understand host networking configuration on the cluster nodes" is gone, and the standalone "know how to scale applications" bullet was folded into autoscaling.
Domain weights are unchanged: Troubleshooting 30%, Cluster Architecture 25%, Services and Networking 20%, Workloads and Scheduling 15%, Storage 10%.
-
Prepare underlying infrastructure for installing a Kubernetes cluster
- Container runtimes - cgroup driver, required ports, kernel modules and sysctls
-
Implement and configure a highly-available control plane
- Options for highly available topology - stacked vs external etcd
- Cluster components and architecture
-
Use Helm and Kustomize to install cluster components
- Kustomize - declarative management of objects
- Managing Kubernetes objects
- Non-k8s.io resource: Using Helm and Helm charts
- Installing addons
-
Understand extension interfaces (CNI, CSI, CRI, etc.)
-
Understand CRDs, install and configure operators
The etcd and kubeadm upgrade commands below were run against a real two-node kubeadm cluster built from
labs/kubeadm-cluster, upgrading it from v1.34.11 to v1.35.8 (September 2026). Step 0, the package repository change, is not optional: without itapt-get install kubeadm='1.35.8-1.1'fails withE: Version '1.35.8-1.1' for 'kubeadm' was not found.
sample commands used during backup/restore/update of nodes
# etcd backup and restore
# ETCDCTL_API=3 is the default from etcd 3.4 onwards, but setting it explicitly is harmless
etcdctl snapshot save -h # find save options
etcdutl snapshot restore -h # find restore options
# save a snapshot - against a TLS-enabled etcd you must pass the endpoint AND the ca/cert/key.
# Omitting --endpoints silently falls back to 127.0.0.1:2379, which is not always where etcd listens.
ETCDCTL_API=3 etcdctl --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 \
snapshot save /backup/snapshot.db
# verify the snapshot
etcdutl --write-out=table snapshot status /backup/snapshot.db
# restore into a NEW data directory.
# NOTE: `etcdctl snapshot restore` is deprecated since etcd 3.5 and removed in etcd 3.6 - use etcdutl.
etcdutl --data-dir /var/lib/etcd-restore snapshot restore /backup/snapshot.db
# then point the static pod at the restored data directory and let the kubelet restart it:
# edit /etc/kubernetes/manifests/etcd.yaml and set volumes.hostPath.path
# for the volume named `etcd-data` to /var/lib/etcd-restore
# evicting pods/nodes and bringing a node back into the cluster
kubectl drain <node> --ignore-daemonsets # drain a node (DaemonSet pods cannot be evicted)
kubectl uncordon <node> # return a node to the cluster as schedulable
kubectl cordon <node> # stop scheduling new pods on a node
# upgrade a kubernetes WORKER node (Debian/Ubuntu, run on the node itself unless noted)
# 0. point the package repository at the target minor version.
# pkgs.k8s.io has one repository per MINOR version, so without this
# `apt-get install kubeadm='1.35.x-*'` cannot find the package at all.
# Only needed when crossing a minor version (1.34 -> 1.35), not for
# a patch bump within the same minor (1.35.5 -> 1.35.7).
# On RHEL/Fedora the equivalent file is /etc/yum.repos.d/kubernetes.repo.
# Debian/Ubuntu:
sudo sed -i 's#/v1.34/#/v1.35/#' /etc/apt/sources.list.d/kubernetes.list
# find the exact patch version available in that repository
sudo apt update && sudo apt-cache madison kubeadm
# 1. upgrade kubeadm and kubectl
sudo apt-mark unhold kubeadm kubectl && \
sudo apt-get update && sudo apt-get install -y kubeadm='1.35.x-*' kubectl='1.35.x-*' && \
sudo apt-mark hold kubeadm kubectl
# 2. upgrade the local kubelet config
sudo kubeadm upgrade node
# 3. drain the node (run from a control plane node)
kubectl drain <node-to-drain> --ignore-daemonsets
# 4. upgrade the kubelet
sudo apt-mark unhold kubelet && \
sudo apt-get update && sudo apt-get install -y kubelet='1.35.x-*' && \
sudo apt-mark hold kubelet
# 5. restart the kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet
# 6. uncordon the node (run from a control plane node)
kubectl uncordon <node-to-uncordon>
# kubeadm CONTROL PLANE upgrade steps (one node at a time, first node shown)
# 0. change the package repository to the target minor version (see worker step 0)
# 1. upgrade the kubeadm package FIRST - `kubeadm upgrade plan` is run by the
# new kubeadm binary, so upgrading it is a prerequisite, not an afterthought
sudo apt-mark unhold kubeadm && \
sudo apt-get update && sudo apt-get install -y kubeadm='1.35.x-*' && \
sudo apt-mark hold kubeadm
kubeadm version # confirm the new binary is in place
# 2. plan and apply
sudo kubeadm upgrade plan # shows which versions you can upgrade to
sudo kubeadm upgrade apply v1.35.x # FIRST control plane node only
# every OTHER control plane node: upgrade the kubeadm package, then run
# sudo kubeadm upgrade node
# instead of `kubeadm upgrade apply`
# 3. the control plane node still needs its kubelet and kubectl upgraded,
# exactly like a worker (drain, upgrade, restart, uncordon)
kubectl drain <cp-node> --ignore-daemonsets
sudo apt-mark unhold kubelet kubectl && \
sudo apt-get update && sudo apt-get install -y kubelet='1.35.x-*' kubectl='1.35.x-*' && \
sudo apt-mark hold kubelet kubectl
sudo systemctl daemon-reload
sudo systemctl restart kubelet
kubectl uncordon <cp-node>
- Understand application deployments and how to perform rolling update and rollbacks
- Use ConfigMaps and Secrets to configure applications
- Configure workload autoscaling
- Autoscaling workloads
- HorizontalPodAutoscaler
- HorizontalPodAutoscaler walkthrough - needs metrics-server
- Scaling a StatefulSet
- Understand the primitives used to create robust, self-healing, application deployments
- Configure Pod admission and scheduling (limits, node affinity, etc.)
- Assigning Pods to Nodes - nodeSelector, node affinity, pod affinity and anti-affinity
- Taints and tolerations
- Resource requests and limits
- LimitRange and ResourceQuota
- Admission controllers
- Pod priority and preemption
- Understand connectivity between Pods
- Define and enforce Network Policies
- Use ClusterIP, NodePort, LoadBalancer service types and endpoints
- Use the Gateway API to manage Ingress traffic
- Gateway API
- Non-k8s.io resource: Gateway API guides - GatewayClass, Gateway, HTTPRoute
- Know how to use Ingress controllers and Ingress resources
- Understand and use CoreDNS
- Implement storage classes and dynamic volume provisioning
- Configure volume types, volume mode, access modes and reclaim policies
- Manage persistent volumes and persistent volume claims
StorageClass, PersistentVolume, and PersistentVolumeClaim examples
#### Storage Class example
#
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage-sc
provisioner: kubernetes.io/no-provisioner # local volumes have no dynamic provisioner
volumeBindingMode: WaitForFirstConsumer # bind only when a Pod using the PVC is scheduled
reclaimPolicy: Retain
---
#### Persistent Volume Claim example
#
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: local-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage-sc
resources:
requests:
storage: 100Mi
---
## Persistent Volume example
#
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 200Mi
local:
path: /data/pv/disk021
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage-sc
volumeMode: Filesystem
# A local PersistentVolume is rejected without nodeAffinity:
# "You must set a PersistentVolume nodeAffinity when using local volumes."
# Replace <node-name> with the node holding /data/pv/disk021.
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- <node-name>
---
### Pod using the pvc
#
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: local-persistent-storage
mountPath: /var/www/html
volumes:
- name: local-persistent-storage
persistentVolumeClaim:
claimName: local-pvcFor a full diagnostic method and practice scenarios, see TROUBLESHOOTING.md.
- Troubleshoot clusters and nodes
- Debugging a node with kubectl debug node
- System logs - journalctl -u kubelet
- Troubleshoot cluster components
- static pod manifests in /etc/kubernetes/manifests/, and crictl ps / crictl logs when the API server is down
- Monitor cluster and application resource usage
- kubectl top - needs metrics-server
- System metrics
- Manage and evaluate container output streams
- Troubleshoot services and networking
- Debug pods - pending, crash-looping or terminated pods
- Debug applications
- DNS troubleshooting
practice practice practice
Get familiar with:
-
Familiarize yourself with the documentation, initially concepts and mostly tasks, kubectl explain command, kubectl cheatsheet, and kubectl commands reference
-
kubectl api-versionsandkubectl api-resourceswithgrepfor a specific resource e.g. pv, pvc, deployment, storageclass, ..etc can help figure out the apiVersion, and kind combined with explain below will help in constructing the yaml manifest -
kubectl explain --recursive to construct out any yaml manifest you need and find its specd and details
-
When using kubectl for investigations and troubleshooting utilize the wide output it gives your more details
$kubectl get pods -o wide --show-labels --all-namespaces
or
$kubectl get pods -o wide --show-labels -A # -A is quicker than --all-namespaces
-
In
kubectlutilize--all-namespaces or better -Ato ensure deployments, pods, objects are on the right name space, and right desired state -
for events and troubleshooting utilize kubectl describe if its pod/resource related and logs if it is application issue related
$kubectl describe pods <PODID> # for pod, deployment, other k8s resource issues/events
$kubectl logs <PODID> # for container/application issues like crash loops
- fast with kubectl e.g. the '-o yaml' in conjunction with
--dry-run=clientallows you to create a manifest template from an imperative spec, combined with--editit allows you to modify the object before creation
kubectl create service clusterip my-svc -o yaml --dry-run=client > /tmp/srv.yaml
kubectl create --edit -f /tmp/srv.yaml
- use kubectl aliases to speed up and reduce typo errors, practice these aliases early at your work and study for the exam. some example aliases:
alias k='kubectl'
alias kg='kubectl get'
alias kgpo='kubectl get pod'
alias kcpyd='kubectl run -o yaml --dry-run=client' # `kubectl create pod` is not a valid subcommand - pods are created with `kubectl run`
alias ksysgpo='kubectl --namespace=kube-system get pod'
alias kd='kubectl delete'
alias kdf='kubectl delete -f'
## for quick deletes you can add --force --grace-period=0 **Not sure if it is a good idea if you are in a production cluster**
alias krmgf='kubectl delete --grace-period 0 --force'
alias kgsvcoyaml='kubectl get service -o=yaml'
alias kgsvcwn='watch kubectl get service --namespace'
alias kgsvcslwn='watch kubectl get service --show-labels --namespace'
#example usage of aliases
krmgf nginx-8jk71 # kill pod nginx-8jk71 using grace period 0 and force
- Enable kubectl autocomplete. Autocomplete is the life saviour in any timebound exam as well as our day to day work (e.g. If autocomplete enabled
k -n [Press Tab]will suggest available namespaces). Example command to enable autocomplete is available at official kubectl Cheat Sheet page, you don't have to remember anything.
source <(kubectl completion bash) # setup autocomplete in bash into the current shell, bash-completion package should be installed first.
echo "source <(kubectl completion bash)" >> ~/.bashrc # add autocomplete permanently to your bash shell.
alias k=kubectl
complete -F __start_kubectl k
Double check if the course is uptodate with the latest exam information (e.g. api, or curriculum)
VMware's KubeAcademy has been retired (notice) and its free "How to prepare for the CKA exam" course was removed from this list. The remaining links were last checked in September 2026.
- Mumshad CKA with practice tests and mock exams - Highly recommended
- Killer.sh CKA simulator ⟹ use code walidshaari for 20% discount - they update frequently
- AWS Container hero NANA CKA course
- Pluralsight CKA course by Anthony E. Nocentino
- rx-m online CKA course
- Duffie Cooly hands-on CKA lab notes using KinD (the accompanying k8s.work video is no longer hosted)
- Stilian Stoilov practice questions - 50+ tasks with increasing difficulty.
- Killercoda in-browser CKA Playground and Challenges - FREE
- Learn more about Kubernetes core components from Duffie Cooly TGIK Grokking playlist
- CKAD Certified Kubernetes Application Developer
- CKS Certified Kubernetes Security Specialist
- Klustered: live youtube series of advanced level of internals troubleshooting. fun and interesting to watch Klustered
