18 — Exam Tips & Strategy
← 17-troubleshooting-networking.md | → 19-practice-exercises.md
Overview
This file covers Module 6 — Exam Strategy & Practice, topics 1–5:
Time Management
Exam Structure
| Detail |
Info |
| Duration |
2 hours (120 minutes) |
| Questions |
~15–20 tasks |
| Passing |
66% |
| Average time per task |
~6–8 minutes |
| Environment |
Remote browser-based terminal (PSI) |
The Two-Pass Strategy
| Pass 1 (first 80 minutes):
├─ Read every question, note its weight (%)
├─ Solve all tasks you can do in < 5 minutes FIRST
├─ Flag anything that needs doc lookup or feels complex
└─ Target: 70–80% of questions done
Pass 2 (remaining 40 minutes):
├─ Return to flagged questions, hardest first by weight
├─ Use documentation for YAML you don't remember
└─ Partial credit exists — always attempt something
|
Time Allocation by Weight
| Domain |
Weight |
Approx. Time Budget |
| Cluster Architecture, Installation & Configuration |
25% |
~30 min |
| Workloads & Scheduling |
15% |
~18 min |
| Services & Networking |
20% |
~24 min |
| Storage |
10% |
~12 min |
| Troubleshooting |
30% |
~36 min |
Time-Saving Rules
| Rule |
Why |
| Use imperative commands first |
10x faster than writing YAML |
--dry-run=client -o yaml > file.yaml |
Generate base YAML, then edit |
| Don't memorize full specs |
Know where to find them in docs |
| Switch context immediately |
Every question may use a different cluster |
| Read the WHOLE question first |
Avoid redoing work because you missed a detail |
| If stuck > 3 minutes, flag and move on |
Come back in Pass 2 |
Imperative Commands Cheat Sheet
Pod & Workload Creation
| # Pod
kubectl run nginx --image=nginx
kubectl run nginx --image=nginx --port=80 --labels="app=web,tier=frontend"
kubectl run nginx --image=nginx --command -- sleep 3600
kubectl run nginx --image=nginx --env="DB=mysql" --env="PORT=3306"
# Pod with resource requests/limits
kubectl run nginx --image=nginx --requests="cpu=100m,memory=128Mi" --limits="cpu=200m,memory=256Mi"
# Generate YAML without creating
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml
# Deployment
kubectl create deployment nginx --image=nginx --replicas=3
kubectl create deployment nginx --image=nginx --port=80 --dry-run=client -o yaml > deploy.yaml
# Job
kubectl create job my-job --image=busybox -- echo "done"
# CronJob
kubectl create cronjob my-cron --image=busybox --schedule="*/5 * * * *" -- echo "tick"
|
Services
| # Expose a pod (ClusterIP)
kubectl expose pod nginx --port=80 --target-port=80 --name=nginx-svc
# Expose a deployment (NodePort)
kubectl expose deployment nginx --port=80 --type=NodePort
# Expose with specific node port
kubectl create service nodeport nginx --tcp=80:80 --node-port=30080
# ClusterIP service
kubectl create service clusterip my-svc --tcp=80:8080
|
ConfigMaps & Secrets
| # ConfigMap from literals
kubectl create configmap my-cm --from-literal=key1=val1 --from-literal=key2=val2
# ConfigMap from file
kubectl create configmap my-cm --from-file=config.txt
# Secret (generic)
kubectl create secret generic my-secret --from-literal=user=admin --from-literal=pass=s3cret
# TLS Secret
kubectl create secret tls my-tls --cert=tls.crt --key=tls.key
# Docker registry secret
kubectl create secret docker-registry my-reg --docker-server=reg.io --docker-username=user --docker-password=pass
|
RBAC
| # Role
kubectl create role pod-reader --verb=get,list,watch --resource=pods -n dev
# ClusterRole
kubectl create clusterrole node-reader --verb=get,list --resource=nodes
# RoleBinding
kubectl create rolebinding read-pods --role=pod-reader --user=jane -n dev
# ClusterRoleBinding
kubectl create clusterrolebinding read-nodes --clusterrole=node-reader --user=jane
# ServiceAccount
kubectl create serviceaccount my-sa -n dev
# Bind role to ServiceAccount
kubectl create rolebinding sa-binding --role=pod-reader --serviceaccount=dev:my-sa -n dev
|
Namespace & Context
| # Namespace
kubectl create namespace dev
# Switch context (CRITICAL — do this first on every question)
kubectl config use-context <context-name>
# Set default namespace for current context
kubectl config set-context --current --namespace=dev
|
Other Essential Commands
| # Scale
kubectl scale deployment nginx --replicas=5
# Set image (rolling update)
kubectl set image deployment/nginx nginx=nginx:1.25
# Rollback
kubectl rollout undo deployment/nginx
kubectl rollout history deployment/nginx
# Taint a node
kubectl taint nodes node1 key=value:NoSchedule
# Remove taint (trailing minus)
kubectl taint nodes node1 key=value:NoSchedule-
# Label
kubectl label node node1 disk=ssd
kubectl label pod nginx env=prod
# Annotate
kubectl annotate pod nginx description="my pod"
# Drain / Uncordon
kubectl drain node1 --ignore-daemonsets --delete-emptydir-data
kubectl uncordon node1
# Check permissions
kubectl auth can-i create pods --as=jane -n dev
kubectl auth can-i '*' '*' --as=system:serviceaccount:dev:my-sa
# Get YAML of existing resource
kubectl get pod nginx -o yaml > existing.yaml
# Explain a field (built-in docs)
kubectl explain pod.spec.containers.livenessProbe
kubectl explain pod.spec --recursive | grep -i toleration
|
The --dry-run Pattern (Most Important Exam Technique)
| # 1. Generate base YAML
kubectl run nginx --image=nginx --port=80 --dry-run=client -o yaml > pod.yaml
# 2. Edit to add what imperative can't do (volumes, probes, affinity, etc.)
vi pod.yaml
# 3. Apply
kubectl apply -f pod.yaml
# This is faster than writing YAML from scratch or copying from docs
|
Documentation Bookmarks
You can access https://kubernetes.io/docs/ during the exam. Bookmark these pages:
Must-Have Bookmarks
| Topic |
URL Path |
| kubectl Cheat Sheet |
/docs/reference/kubectl/cheatsheet/ |
| Pod spec |
/docs/reference/kubernetes-api/workload-resources/pod-v1/ |
| Persistent Volumes |
/docs/concepts/storage/persistent-volumes/ |
| Network Policies |
/docs/concepts/services-networking/network-policies/ |
| RBAC |
/docs/reference/access-authn-authz/rbac/ |
| Scheduling (affinity) |
/docs/concepts/scheduling-eviction/assign-pod-node/ |
| Taints & Tolerations |
/docs/concepts/scheduling-eviction/taint-and-toleration/ |
| kubeadm upgrade |
/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/ |
| etcd backup |
/docs/tasks/administer-cluster/configure-upgrade-etcd/ |
| Ingress |
/docs/concepts/services-networking/ingress/ |
| Probes |
/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ |
| Resource Quotas |
/docs/concepts/policy/resource-quotas/ |
| JSONPath |
/docs/reference/kubectl/jsonpath/ |
Search Tips
| # Use the docs search bar — faster than navigating
# Search for exact resource kind: "NetworkPolicy"
# Search for task: "etcd backup"
# Copy YAML examples directly from docs, then modify
|
CKA Tip: The docs search is fast. Type the resource name and you'll find a copyable YAML example within seconds. Don't waste time memorizing complex specs.
Shell Productivity
First Thing: .bashrc Setup
Run this at the very start of the exam (takes 30 seconds, saves minutes):
| # Aliases
alias k=kubectl
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kgn='kubectl get nodes'
alias kd='kubectl describe'
alias kaf='kubectl apply -f'
alias kdel='kubectl delete --force --grace-period=0'
# Auto-completion (may already be enabled)
source <(kubectl completion bash)
complete -o default -F __start_kubectl k
# Default editor (vi is default, change if you prefer nano)
export KUBE_EDITOR=vi
# Quick dry-run alias
alias kdr='kubectl --dry-run=client -o yaml'
# Apply immediately
source ~/.bashrc
|
vi Essentials for the Exam
| # Navigation
gg → go to top
G → go to bottom
/<pattern> → search forward
n / N → next / previous match
:set number → show line numbers
# Editing
i → insert mode
o → new line below, insert mode
dd → delete line
yy → copy line
p → paste below
u → undo
Ctrl+r → redo
# YAML-critical
:set paste → paste without auto-indent mangling
:set nopaste → back to normal
:set tabstop=2 shiftwidth=2 expandtab → proper YAML indentation
# Save and quit
:wq → save and quit
:q! → quit without saving
|
Productivity Shortcuts
| # Quick context switch (copy from question, paste)
k config use-context <name>
# Fast resource generation
k run tmp --image=nginx --dry-run=client -o yaml > q7.yaml
# Name files by question number for easy tracking
# q1.yaml, q2.yaml, etc.
# Quick delete (no waiting for graceful shutdown)
k delete pod nginx --force --grace-period=0
# Watch resources
k get pods -w
# Get all resources in a namespace
k get all -n <ns>
# Quick JSON path extraction
k get pod nginx -o jsonpath='{.status.podIP}'
k get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'
|
Common Pitfalls
Context Switching (The #1 Exam Killer)
| EVERY question may use a different cluster/context.
If you forget to switch → you modify the WRONG cluster → lose points.
ALWAYS run this first:
kubectl config use-context <context-from-question>
Make it muscle memory.
|
YAML Indentation Errors
| # WRONG — args under containers instead of under the container
spec:
containers:
- name: app
image: nginx
args: ["--flag"] # ← WRONG: this is a sibling of the container
# RIGHT
spec:
containers:
- name: app
image: nginx
args: ["--flag"] # ← RIGHT: indented under the container
|
| # Validate before applying
kubectl apply -f file.yaml --dry-run=server
# Catches schema errors that --dry-run=client misses
|
Namespace Mistakes
| # Forgetting -n <namespace> operates on "default"
kubectl get pods # ← default namespace only
kubectl get pods -n kube-system # ← what you probably meant
# Set namespace for current context to avoid repeating -n
kubectl config set-context --current --namespace=<ns>
|
Common Spec Mistakes
| Mistake |
Symptom |
Fix |
targetPort wrong |
Service has endpoints but no response |
Match container's listening port |
selector mismatch |
Endpoints empty |
Labels must match exactly |
Missing command vs args |
Container runs wrong entrypoint |
command overrides ENTRYPOINT, args overrides CMD |
volumeMounts.mountPath typo |
App can't find config |
Double-check path |
secretKeyRef vs configMapKeyRef |
CreateContainerConfigError |
Use correct ref type |
Forgot --- separator |
Multi-resource YAML fails |
Separate resources with --- |
etcd Restore Pitfalls
| # Pitfall 1: Using certs during restore (not needed)
etcdctl snapshot restore snap.db --data-dir=/var/lib/etcd-new
# No --cert, --key, --cacert needed for restore
# Pitfall 2: Forgetting to update etcd manifest after restore
# Must edit /etc/kubernetes/manifests/etcd.yaml:
# --data-dir=/var/lib/etcd-new
# AND update the hostPath volume to match
# Pitfall 3: Not waiting for etcd to restart
# Static pod restarts automatically — wait ~30 seconds
|
Drain Pitfalls
| # Fails if DaemonSet pods exist (they always do)
kubectl drain node1
# Error: cannot delete DaemonSet-managed Pods
# Fix: always use --ignore-daemonsets
kubectl drain node1 --ignore-daemonsets
# Fails if pods use emptyDir
kubectl drain node1 --ignore-daemonsets
# Error: cannot delete Pods with local storage
# Fix: add --delete-emptydir-data
kubectl drain node1 --ignore-daemonsets --delete-emptydir-data
|
RBAC Pitfalls
| # Pitfall: RoleBinding in wrong namespace
# The RoleBinding must be in the SAME namespace as the Role
# and the namespace where you want the permissions to apply
# Pitfall: Using Role when you need ClusterRole
# Nodes, PVs, namespaces are cluster-scoped → need ClusterRole + ClusterRoleBinding
# Quick verify
kubectl auth can-i list pods --as=jane -n dev
|
Exam Environment Gotchas
| Gotcha |
Mitigation |
| Copy-paste may not work as expected |
Practice with the PSI browser; use right-click paste |
| Multiple terminals not available |
Use & for background, or tmux if available |
| Slow docs loading |
Bookmark specific pages, don't browse |
| Cluster may be slow |
Be patient after kubectl apply; use -w to watch |
| Question wording is precise |
Read twice — "all namespaces" vs "namespace X" matters |
| Partial credit |
Always attempt — a half-correct answer > blank |
Exam Day Checklist
| Before the exam:
□ Government ID ready
□ Clean desk, no second monitors
□ Stable internet connection
□ Webcam and microphone working
□ PSI Secure Browser installed and tested
First 2 minutes of exam:
□ Set up aliases and bash completion
□ Verify kubectl works: kubectl get nodes
□ Note which cluster/context each question uses
During the exam:
□ Switch context FIRST on every question
□ Use imperative commands → dry-run → edit → apply
□ Flag hard questions, come back in Pass 2
□ Name files by question number (q1.yaml, q2.yaml)
□ Validate: kubectl get / describe after every apply
|
CKA Tips
- 30 seconds of setup saves 10+ minutes — always configure aliases and completion first
--dry-run=client -o yaml is the single most important exam technique
- Context switching is the #1 cause of lost points — make it automatic
- Don't write YAML from scratch — generate with imperative, copy from docs, or get from existing resources
kubectl explain is faster than searching docs for field names
- Partial credit exists — always attempt every question, even if incomplete
--force --grace-period=0 on deletes saves waiting time during the exam
Practice Exercises
Exercise 1 — Speed Drill: Imperative Commands
| # Time yourself — complete all in under 5 minutes:
# 1. Create namespace "exam"
# 2. Create deployment "web" with nginx:1.25, 3 replicas, in namespace exam
# 3. Expose it as NodePort service on port 80
# 4. Create a ConfigMap "app-config" with key "env=production"
# 5. Create a Secret "db-creds" with user=admin and password=secret123
# 6. Create a ServiceAccount "app-sa" in namespace exam
# 7. Create a Role "pod-manager" allowing get,list,create,delete on pods
# 8. Bind the role to the ServiceAccount
# 9. Verify: kubectl auth can-i list pods --as=system:serviceaccount:exam:app-sa -n exam
# 10. Scale the deployment to 5 replicas
|
Exercise 2 — dry-run YAML Generation
| # Generate YAML for each, then add the specified modification:
# 1. Pod with nginx + a liveness probe (httpGet on port 80, path /)
kubectl run probe-pod --image=nginx --port=80 --dry-run=client -o yaml > probe.yaml
# Edit: add livenessProbe
# 2. Deployment with a toleration for key=special:NoSchedule
kubectl create deployment tolerant --image=nginx --dry-run=client -o yaml > tolerant.yaml
# Edit: add toleration
# 3. Pod with a PVC volume mount
kubectl run pvc-pod --image=nginx --dry-run=client -o yaml > pvc-pod.yaml
# Edit: add volume and volumeMount for an existing PVC
|
Exercise 3 — Context Switching Drill
| # If using kind or kubeadm with multiple clusters:
# 1. List all contexts
kubectl config get-contexts
# 2. Switch to each context and run kubectl get nodes
# 3. Set default namespace to "kube-system" for one context
# 4. Switch back and verify namespace is still "default" in the other
# Practice until context switching is automatic
|
Exercise 4 — Documentation Speed Run
| # Time yourself finding and copying YAML from kubernetes.io/docs:
# 1. Find a NetworkPolicy that allows ingress from a specific namespace (< 60s)
# 2. Find a PersistentVolumeClaim with ReadWriteOnce and 1Gi (< 45s)
# 3. Find an Ingress with TLS termination (< 60s)
# 4. Find a Pod with node affinity (< 60s)
# 5. Find the etcdctl snapshot save command with all cert flags (< 45s)
|
Key Takeaways
| Concept |
Key Point |
| Two-pass strategy |
Easy questions first, flag hard ones for Pass 2 |
| Imperative first |
kubectl run/create/expose before writing YAML |
--dry-run=client -o yaml |
Generate → edit → apply (fastest workflow) |
| Context switch |
First command on EVERY question — non-negotiable |
| Aliases |
alias k=kubectl + completion = significant time savings |
| vi basics |
:set paste, dd, yy, p, /<search> — know these cold |
| Bookmarks |
Cheat sheet, NetworkPolicy, PV, RBAC, etcd, kubeadm upgrade |
| Partial credit |
Always attempt — something > nothing |
| File naming |
q1.yaml, q2.yaml — track your work |
| Validate |
kubectl get/describe after every apply |
← 17-troubleshooting-networking.md | → 19-practice-exercises.md