8 exam tips covering domain areas, tricky scenarios, and commands to memorize.
Certified Kubernetes Administrator — cluster administration and operations
Explanation
In the CKA exam, time is your most precious resource. You only have two hours to complete 15-20 tasks, and writing YAML from scratch for every object will burn through your clock fast. Imperative commands like kubectl run, kubectl create, and kubectl expose let you spin up pods, deployments, services, and other resources in seconds rather than minutes. You should memorize the key flags: --image, --port, --replicas, --dry-run=client, and -o yaml. The --dry-run=client -o yaml pattern is especially powerful because it generates a valid YAML manifest that you can redirect to a file and then edit for more complex configurations. Practice chaining these commands so that creating a deployment and exposing it as a service becomes muscle memory. This alone can save you 20-30 minutes across the entire exam.
Command / YAML
# Create a deployment imperatively with 3 replicas kubectl create deployment nginx-deploy --image=nginx:1.25 --replicas=3 # Expose the deployment as a ClusterIP service on port 80 kubectl expose deployment nginx-deploy --port=80 --target-port=80 --name=nginx-svc # Generate YAML without creating the resource (dry-run) kubectl run redis --image=redis:7 --port=6379 --dry-run=client -o yaml > redis-pod.yaml # Create a configmap from a literal value kubectl create configmap app-config --from-literal=ENV=production --from-literal=LOG_LEVEL=info # Create a secret from literal values kubectl create secret generic db-secret --from-literal=password=S3cur3P@ss
Common Mistake
Candidates waste time writing full YAML manifests from scratch instead of using kubectl create or kubectl run with --dry-run=client -o yaml to generate a base template, then editing only the fields that need customization.
💬 Comments
Explanation
Etcd is the backbone of every Kubernetes cluster — it stores all cluster state, configuration, and secrets. The CKA exam almost always includes a question on backing up and restoring etcd, and it carries significant weight. You need to know how to use etcdctl snapshot save to create a backup and etcdctl snapshot restore to restore from one. The critical detail most candidates miss is that you must set ETCDCTL_API=3 as an environment variable, because etcdctl defaults to API version 2 in some distributions. You also need to provide the correct TLS certificates: the CA certificate, the server certificate, and the server key. These are typically found in /etc/kubernetes/pki/etcd/ on kubeadm-based clusters. After restoring, you must update the etcd manifest to point to the new data directory and restart the etcd pod. Practice this workflow until you can do it confidently in under five minutes.
Command / YAML
# Set the etcdctl API version to 3 export ETCDCTL_API=3 # Create a snapshot backup of etcd 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 # Verify the snapshot status etcdctl snapshot status /opt/etcd-backup.db --write-table # Restore etcd from the snapshot to a new data directory etcdctl snapshot restore /opt/etcd-backup.db \ --data-dir=/var/lib/etcd-restored # Update the etcd static pod manifest to use the restored data directory # Edit /etc/kubernetes/manifests/etcd.yaml and change the volume hostPath # from /var/lib/etcd to /var/lib/etcd-restored
Common Mistake
Candidates forget to set ETCDCTL_API=3 or provide the wrong TLS certificate paths, causing etcdctl commands to fail silently or return confusing errors. Always verify the cert paths from the running etcd pod spec first with kubectl describe pod etcd-controlplane -n kube-system.
💬 Comments
Explanation
RBAC (Role-Based Access Control) is a core security mechanism in Kubernetes and a frequent topic on the CKA exam. You need to be able to create ServiceAccounts, Roles, and RoleBindings quickly and correctly. A Role defines what actions (verbs) are allowed on which resources within a specific namespace, while a RoleBinding associates that Role with a user or ServiceAccount. For cluster-wide permissions, you use ClusterRole and ClusterRoleBinding instead. The imperative approach is fastest: use kubectl create serviceaccount, kubectl create role, and kubectl create rolebinding with the correct flags. Pay careful attention to the namespace — Roles and RoleBindings are namespaced objects, so you must specify the namespace explicitly. Also know the difference between a RoleBinding that references a Role versus one that references a ClusterRole, as the latter grants cluster-level permissions scoped to a namespace. Practice until you can complete the full RBAC chain in under three minutes.
Command / YAML
# Create a service account in the dev namespace kubectl create serviceaccount app-sa -n dev # Create a role that allows get, list, watch on pods and services kubectl create role app-role -n dev \ --verb=get,list,watch \ --resource=pods,services # Bind the role to the service account kubectl create rolebinding app-rb -n dev \ --role=app-role \ --serviceaccount=dev:app-sa # Verify the permissions using auth can-i kubectl auth can-i list pods -n dev --as=system:serviceaccount:dev:app-sa # Create a cluster role for reading nodes (cluster-wide) kubectl create clusterrole node-reader \ --verb=get,list,watch \ --resource=nodes # Bind the cluster role to a user kubectl create clusterrolebinding node-reader-binding \ --clusterrole=node-reader \ --user=jane
Common Mistake
Candidates mix up Role vs ClusterRole and RoleBinding vs ClusterRoleBinding, or they forget to specify the correct namespace in the --serviceaccount flag (it must be namespace:name format like dev:app-sa, not just app-sa).
💬 Comments
Explanation
NetworkPolicy is one of the most challenging topics on the CKA exam because it requires understanding both Kubernetes networking concepts and YAML policy structure. The best strategy is to always start with a default deny policy that blocks all ingress and/or egress traffic to pods in a namespace, then create additional policies that explicitly allow only the traffic you need. This defense-in-depth approach matches real-world security practices and is exactly what exam questions expect. Remember that NetworkPolicies are additive — if any policy allows traffic, it is permitted, and there is no way to explicitly deny traffic that another policy allows. The podSelector field determines which pods the policy applies to, while ingress.from and egress.to define the allowed sources and destinations using podSelector, namespaceSelector, or ipBlock. An empty podSelector ({}) selects all pods in the namespace. Practice writing these policies from memory, because you will not have time to look up every field during the exam.
Command / YAML
# Default deny all ingress traffic in the production namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress # Name describing the deny-all policy
namespace: production # Target namespace for this policy
spec:
podSelector: {} # Empty selector matches ALL pods in the namespace
policyTypes:
- Ingress # This policy governs incoming traffic
---
# Allow traffic from frontend pods to backend pods on port 8080
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend # Descriptive policy name
namespace: production # Same namespace as the deny policy
spec:
podSelector: # Select the pods this policy applies to
matchLabels:
app: backend # Policy targets pods with label app=backend
policyTypes:
- Ingress # Governs incoming traffic to backend pods
ingress:
- from:
- podSelector: # Allow traffic from pods matching this selector
matchLabels:
app: frontend # Only frontend pods can reach backend
ports:
- protocol: TCP # Restrict to TCP protocol
port: 8080 # Only allow traffic on port 8080Common Mistake
Candidates place podSelector and namespaceSelector as separate list items under 'from', which creates an OR condition allowing traffic from any pod OR any namespace. To require both conditions (AND logic), they must be in the same list item.
💬 Comments
Explanation
On Kubernetes certification exams, time is your biggest constraint. Writing YAML from scratch is too slow. The fastest method is to use imperative `kubectl` commands with `--dry-run=client -o yaml` to generate a valid manifest. Redirect this output to a file, make the necessary edits with `vi`, and then apply it. Memorize the key generator flags for `kubectl create deployment` (`--image`, `--replicas`), `kubectl create service` (`--port`, `--target-port`, `--type`), and `kubectl create configmap/secret` (`--from-literal`, `--from-file`). For quick modifications, `kubectl set image` and `kubectl scale` are faster than editing the file again. **Exam Trap**: Always use `--dry-run=client`. The `--dry-run=server` flag still communicates with the API server and can fail on RBAC checks or other validations, wasting time. Also, be aware that `kubectl run` is now primarily for creating temporary debugging pods; use `kubectl create deployment` for creating deployments. A useful shortcut is to set `alias k=kubectl` at the start of your exam.
Command / YAML
# Generate a deployment YAML without creating it (fastest exam pattern) kubectl create deployment web --image=nginx:1.25 --replicas=3 --dry-run=client -o yaml > web-deploy.yaml # Expose a deployment as a service and generate its YAML kubectl expose deployment web --port=80 --target-port=8080 --name=web-svc --type=NodePort --dry-run=client -o yaml > web-svc.yaml # Create a ConfigMap and a Secret from literals kubectl create configmap app-cfg --from-literal=ENV=prod --from-literal=LOG_LEVEL=info --dry-run=client -o yaml kubectl create secret generic db-pass --from-literal=password=S3cr3tPa$$w0rd --dry-run=client -o yaml # Perform quick updates without editing YAML files kubectl set image deployment/web nginx=nginx:1.26 kubectl scale deployment web --replicas=5
Common Mistake
Writing YAML from scratch, which is too slow. Another common mistake is using `--dry-run=server` instead of `--dry-run=client`, which can fail unexpectedly and waste valuable time.
💬 Comments
Explanation
Etcd backup is a critical, high-value CKA task. First, SSH to the control plane node. Before running any `etcdctl` commands, you must `export ETCDCTL_API=3`. The required TLS certificate paths are not secret; find them by inspecting the etcd static pod manifest at `/etc/kubernetes/manifests/etcd.yaml`. Copy the values for `--cacert`, `--cert`, `--key`, and `--endpoints` directly from the manifest's command arguments. For backup, use `etcdctl snapshot save`. For restore, the process is more involved: first, stop the kube-apiserver to prevent it from interfering. Then, run `etcdctl snapshot restore` to a *new* data directory. Finally, edit the `etcd.yaml` manifest to update the `hostPath` volume to point to your new restored data directory. The kubelet will detect the change and restart the etcd pod. **Exam Trap**: Forgetting to stop the API server before restore, or restoring over the live data directory instead of a new one.
Command / YAML
# 1. Set API version export ETCDCTL_API=3 # 2. Backup (get paths from /etc/kubernetes/manifests/etcd.yaml) etcdctl snapshot save /opt/snapshot.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 # 3. Verify the backup etcdctl snapshot status /opt/snapshot.db --write-out=table # 4. Restore (example steps) # systemctl stop kubelet (Or move etcd.yaml out of manifests dir) etcdctl snapshot restore /opt/snapshot.db --data-dir=/var/lib/etcd-restored # chown -R etcd:etcd /var/lib/etcd-restored # Edit /etc/kubernetes/manifests/etcd.yaml: change spec.volumes.hostPath.path to /var/lib/etcd-restored # systemctl start kubelet (Or move etcd.yaml back)
Common Mistake
Forgetting ETCDCTL_API=3, using wrong certificate paths, or restoring over the live data directory without updating the static pod manifest volume hostPath.
💬 Comments
Explanation
A systematic approach is key for troubleshooting tasks. Follow this order: 1. **`kubectl describe pod <name>`**: This is your most important command. The `Events` section at the bottom will tell you the root cause of most issues like `ImagePullBackOff`, `CrashLoopBackOff`, failed volume mounts, or failed probes. 2. **`kubectl logs <pod>`**: If the pod is running but misbehaving, check its logs. For a pod in a crash loop, use `kubectl logs <pod> --previous` to see the logs from the last failed container instance. 3. **`kubectl get events`**: If the issue is not obvious from the pod description (e.g., a pod is stuck in `Pending`), check cluster-wide events with `kubectl get events --sort-by='.lastTimestamp'`. This can reveal node resource pressure or scheduling failures. 4. **`kubectl exec`**: If the pod is running but has network issues, `exec` into it to run `curl`, `wget`, or `ping` to test connectivity to other services. **Exam Trap**: Ignoring `Init:Error` status. If an init container fails, the main containers will never start. Check their logs specifically with `kubectl logs <pod> -c <init-container-name>`.
Command / YAML
# 1. Check pod status and events kubectl describe pod failing-pod # 2. Check logs (especially for CrashLoopBackOff) kubectl logs failing-pod kubectl logs failing-pod --previous # 3. Check logs of a specific container (init or sidecar) kubectl logs failing-pod -c my-init-container # 4. Check cluster-wide events for scheduling issues kubectl get events --sort-by='.lastTimestamp' -A # 5. Exec into a running pod to test network connectivity kubectl exec -it running-pod -- curl -s other-service:8080/health # 6. Use kubectl debug for deeper inspection (on recent k8s versions) kubectl debug pod/failing-pod -it --image=busybox --share-processes --copy-to=debug-pod
Common Mistake
Jumping straight to YAML edits or cluster-wide changes without reading pod Events in kubectl describe, which usually states the root cause in plain language.
💬 Comments
Explanation
Many exam tasks begin with `Use the clusterX context...`. Failing to switch context is the easiest way to get zero points for a perfectly solved problem. Before starting any task, read the context-switching command provided and execute it. Then, set the namespace for that context so you don't have to type `-n <namespace>` on every command. Always verify your current context and namespace before applying any resources. **Exam Trap**: The question will provide the exact command like `kubectl config use-context cluster-2`. Copy and paste it. Do not guess or assume. A common mistake is solving the entire problem in the `default` namespace when the question specified a different one. Get in the habit of running `kubectl config set-context --current --namespace=<ns>` immediately after switching clusters.
Command / YAML
# 1. List all available contexts kubectl config get-contexts # 2. Switch to the correct cluster context (copy-paste from the exam question) kubectl config use-context cluster-2 # 3. Set the default namespace for the current context kubectl config set-context --current --namespace=team-a # 4. Verify your current settings before proceeding kubectl config view --minify | grep -E 'cluster:|namespace:'
Common Mistake
Applying resources to the default namespace or wrong cluster because the candidate never switched context or set namespace before running commands.
💬 Comments