CKAD Exam Tips and kubectl Speed Tricks¶
Exam Environment Setup¶
First Thing: Set Up Your Shell¶
Run these commands at the very start of your exam:
# Essential aliases
alias k=kubectl
alias kn='kubectl config set-context --current --namespace'
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kgd='kubectl get deployments'
# Shorthand for dry-run YAML generation
export do="--dry-run=client -o yaml"
export now="--force --grace-period=0"
# Verify
k version --client
Configure vim for YAML editing¶
cat >> ~/.vimrc << 'EOF'
set expandtab
set tabstop=2
set shiftwidth=2
set autoindent
set number
EOF
Enable kubectl autocompletion (usually already enabled)¶
source <(kubectl completion bash)
complete -o default -F __start_kubectl k
Imperative Command Reference¶
Pods¶
# Create a Pod
k run nginx --image=nginx:1.25
k run nginx --image=nginx:1.25 --port=80
k run nginx --image=nginx:1.25 --labels="app=web,tier=frontend"
k run nginx --image=nginx:1.25 --env="DB_HOST=db" --env="DB_PORT=5432"
k run nginx --image=nginx:1.25 --requests="cpu=100m,memory=64Mi" --limits="cpu=200m,memory=128Mi"
# Generate YAML
k run nginx --image=nginx:1.25 $do > pod.yaml
# Run a temporary Pod for testing
k run test --image=busybox:1.36 --rm -it -- /bin/sh
k run test --image=busybox:1.36 --rm -it -- wget -qO- http://my-svc:80
k run test --image=busybox:1.36 --rm -it -- nslookup my-svc
# Delete a Pod quickly
k delete pod nginx $now
Deployments¶
# Create
k create deploy nginx --image=nginx:1.25 --replicas=3
k create deploy nginx --image=nginx:1.25 --port=80
# Generate YAML
k create deploy nginx --image=nginx:1.25 --replicas=3 $do > deploy.yaml
# Scale
k scale deploy nginx --replicas=5
# Update image
k set image deploy/nginx nginx=nginx:1.26
# Rollout management
k rollout status deploy/nginx
k rollout history deploy/nginx
k rollout undo deploy/nginx
k rollout undo deploy/nginx --to-revision=2
k rollout restart deploy/nginx
Services¶
# Expose a Deployment
k expose deploy nginx --port=80 --target-port=8080 --type=ClusterIP
k expose deploy nginx --port=80 --target-port=8080 --type=NodePort
k expose deploy nginx --port=80 --target-port=8080 --type=NodePort --name=nginx-svc
# Expose a Pod
k expose pod nginx --port=80 --target-port=80 --name=nginx-svc
# Generate YAML
k expose deploy nginx --port=80 --target-port=8080 $do > svc.yaml
ConfigMaps¶
# From literals
k create cm my-config --from-literal=key1=value1 --from-literal=key2=value2
# From file
k create cm my-config --from-file=config.txt
k create cm my-config --from-file=mykey=config.txt # Custom key name
# From env file
k create cm my-config --from-env-file=config.env
# Generate YAML
k create cm my-config --from-literal=key=value $do > cm.yaml
Secrets¶
# Generic
k create secret generic my-secret --from-literal=user=admin --from-literal=pass=secret
# Docker registry
k create secret docker-registry my-reg --docker-server=reg.io --docker-username=user --docker-password=pass
# TLS
k create secret tls my-tls --cert=cert.pem --key=key.pem
# Generate YAML
k create secret generic my-secret --from-literal=key=value $do > secret.yaml
Jobs and CronJobs¶
# Job
k create job my-job --image=busybox:1.36 -- echo "Hello"
k create job my-job --image=busybox:1.36 $do > job.yaml -- echo "Hello"
# CronJob
k create cj my-cron --image=busybox:1.36 --schedule="*/5 * * * *" -- echo "Hello"
k create cj my-cron --image=busybox:1.36 --schedule="*/5 * * * *" $do > cron.yaml -- echo "Hello"
Ingress¶
# Create Ingress
k create ingress myingress --class=nginx --rule="host.com/path*=svc:80"
# Multiple rules
k create ingress myingress --class=nginx \
--rule="host.com/api*=api-svc:8080" \
--rule="host.com/*=web-svc:80"
# Generate YAML
k create ingress myingress --class=nginx --rule="host.com/*=svc:80" $do > ingress.yaml
Other Resources¶
# Namespace
k create ns my-namespace
# ServiceAccount
k create sa my-sa -n my-namespace
# Role
k create role pod-reader --verb=get,list,watch --resource=pods -n my-namespace
# RoleBinding
k create rolebinding pod-reader-binding --role=pod-reader --serviceaccount=my-namespace:my-sa -n my-namespace
# ResourceQuota
k create quota my-quota --hard=pods=10,requests.cpu=4,requests.memory=8Gi -n my-namespace
YAML Generation and Editing Tricks¶
Generate, Edit, Apply Workflow¶
This is the fastest approach for creating resources that need customization:
# 1. Generate the base YAML
k run myapp --image=nginx:1.25 $do > myapp.yaml
# 2. Edit to add what you need (probes, volumes, etc.)
vim myapp.yaml
# 3. Apply
k apply -f myapp.yaml
# 4. Verify
k get pod myapp
k describe pod myapp
Quick YAML Snippets to Memorize¶
Resource requests and limits:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
Liveness probe (HTTP):
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
Readiness probe (TCP):
readinessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 5
periodSeconds: 10
Volume mount (emptyDir):
# In containers:
volumeMounts:
- name: data
mountPath: /data
# In spec:
volumes:
- name: data
emptyDir: {}
ConfigMap as env:
envFrom:
- configMapRef:
name: my-config
Secret as env:
envFrom:
- secretRef:
name: my-secret
SecurityContext (container):
securityContext:
runAsUser: 1000
runAsNonRoot: true
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
vim Tips for the Exam¶
Essential vim Commands¶
i Enter insert mode
Esc Exit insert mode
:w Save
:q Quit
:wq Save and quit
:q! Quit without saving
dd Delete current line
5dd Delete 5 lines
yy Copy current line
5yy Copy 5 lines
p Paste below
P Paste above
gg Go to top of file
G Go to bottom of file
:10 Go to line 10
/pattern Search forward
?pattern Search backward
n Next match
N Previous match
u Undo
Ctrl+r Redo
v Visual mode (select text)
V Visual line mode
d Delete selection (in visual mode)
y Copy selection (in visual mode)
>> Indent line
<< Unindent line
5>> Indent 5 lines
:%s/old/new/g Replace all occurrences in file
YAML-Specific vim Tricks¶
# Select and indent a block
V (visual line mode)
j/k (select lines)
> (indent) or < (unindent)
# Duplicate a section
V (visual line mode)
j/k (select the block)
y (yank/copy)
p (paste below cursor)
Time Management¶
Strategy¶
- Read the task completely before starting (30 seconds)
- Check context and namespace - run the provided context command
- Start with imperative commands - fastest approach
- Use
$doto generate YAML when you need to add custom fields - Verify your work -
kubectl get,kubectl describe - Move on if a task takes more than 8 minutes
Task Priority¶
- Do first: Tasks you know well (quick wins, bank points)
- Do second: Tasks that need some YAML editing but are straightforward
- Do last: Complex tasks or topics you are less confident in
- Always attempt: Even partial solutions may earn points
Time Allocation (2 hours, ~15-20 tasks)¶
- First 80 minutes: Work through all tasks in order, skip hard ones
- Next 30 minutes: Return to skipped tasks
- Final 10 minutes: Verify completed work, attempt remaining tasks
Common Gotchas¶
Context and Namespace¶
- Every task may use a different cluster context - always run the provided
kubectl config use-contextcommand - Always check the namespace - use
-n <namespace>or set it withkn <namespace> - Forgetting the namespace is the most common mistake on the exam
YAML Issues¶
- Indentation matters - use 2 spaces, never tabs
- Labels must match -
spec.selector.matchLabelsmust matchspec.template.metadata.labelsin Deployments - Name conflicts - check if a resource with the same name already exists:
k get <resource> <name> -n <namespace>
Resource-Specific Gotchas¶
- Jobs:
restartPolicymust beNeverorOnFailure, notAlways - CronJobs: The
concurrencyPolicygoes inspec, not inspec.jobTemplate.spec - NetworkPolicies: Once any policy selects a Pod, all unmatched traffic is denied
- Secrets:
kubectl create secrethandles base64 encoding for you; in YAML manifests,datamust be base64-encoded (usestringDatafor plain text) - Probes: Without a
startupProbe, thelivenessProbecan kill slow-starting containers - Services:
targetPortis the container port,portis the Service port - do not confuse them - Ingress: Requires an Ingress controller - the Ingress resource alone does nothing
Exam Environment Gotchas¶
- Copy-paste may work differently in the PSI browser (right-click menu)
- The terminal may have limited screen real estate - use short aliases
- File paths in tasks are usually absolute - pay attention to where files should be created
- Some clusters may have different configurations - do not assume anything carries over between tasks