Module 0.2: Developer Workflow
Complexity:
[QUICK]- Essential kubectl patternsTime to Complete: 25-30 minutes
Prerequisites: Module 0.1 (CKAD Overview), CKA Module 0.2 (Shell Mastery)
Learning Outcomes
Section titled “Learning Outcomes”After completing this module, you will be able to:
- Configure kubectl aliases, shell completions, and CKAD-specific shortcuts for maximum speed
- Create Kubernetes resources imperatively using
kubectl run,kubectl create, andkubectl expose - Debug resource issues rapidly using
kubectl describe,kubectl logs, andkubectl exec - Explain the developer-centric kubectl workflow that distinguishes CKAD from CKA tasks
Why This Module Matters
Section titled “Why This Module Matters”CKAD is about speed AND correctness. You have 2 hours for ~15-20 tasks. Every second counts. The difference between a passing and failing score is often not knowledge—it’s execution speed.
This module focuses on the developer-specific kubectl patterns you’ll use repeatedly. If you completed the CKA curriculum, you already have aliases and completions set up. Here we add CKAD-specific optimizations.
The Carpenter’s Toolbelt Analogy
A master carpenter doesn’t rummage through a toolbox for each nail. Their most-used tools hang at their waist, positioned for instant access. Similarly, your most-used kubectl patterns should be at your fingertips—aliased, memorized, and practiced until they’re muscle memory.
Essential Aliases for CKAD
Section titled “Essential Aliases for CKAD”If you completed the CKA curriculum, you already have these. If not, add them now:
# Add to ~/.bashrc or ~/.zshrc
# Basic alias (MUST have)alias k='kubectl'
# Common actionsalias kaf='kubectl apply -f'alias kdel='kubectl delete'alias kd='kubectl describe'alias kg='kubectl get'alias kl='kubectl logs'alias kx='kubectl exec -it'
# Output formatsalias kgy='kubectl get -o yaml'alias kgw='kubectl get -o wide'
# Dry-run pattern (CKAD essential)alias kdr='kubectl --dry-run=client -o yaml'
# Quick runalias kr='kubectl run'
# Watchalias kgpw='kubectl get pods -w'CKAD-Specific Additions
Section titled “CKAD-Specific Additions”# Jobs and CronJobs (CKAD heavy)alias kcj='kubectl create job'alias kccj='kubectl create cronjob'
# Quick debug podalias kdebug='kubectl run debug --image=busybox --rm -it --restart=Never --'
# Logs with container selectionalias klc='kubectl logs -c'
# Fast context switchalias kctx='kubectl config use-context'alias kns='kubectl config set-context --current --namespace'The Dry-Run Pattern: Your Best Friend
Section titled “The Dry-Run Pattern: Your Best Friend”The --dry-run=client -o yaml pattern generates YAML without creating resources. This is essential for CKAD:
# Generate pod YAMLk run nginx --image=nginx $kdr > pod.yaml
# Generate deployment YAMLk create deploy web --image=nginx --replicas=3 $kdr > deploy.yaml
# Generate job YAMLk create job backup --image=busybox -- echo done $kdr > job.yaml
# Generate service YAMLk expose deploy web --port=80 $kdr > svc.yamlThe $kdr Variable
Section titled “The $kdr Variable”Set this for even faster YAML generation:
export kdr='--dry-run=client -o yaml'
# Now use it anywherek run nginx --image=nginx $kdr > pod.yamlk create deploy web --image=nginx $kdr > deploy.yamlPause and predict: What happens if you run a test pod using
k run test --image=busybox -- wget ...without including the--restart=Neverflag? What happens to the Pod’s lifecycle after thewgetcommand completes successfully? Think about it before reading on.
Multi-Container Pod YAML Generation
Section titled “Multi-Container Pod YAML Generation”This is a CKAD signature skill. You can’t create multi-container pods imperatively—you need YAML. Here’s the fastest approach:
Step 1: Generate Base YAML
Section titled “Step 1: Generate Base YAML”k run multi --image=nginx $kdr > multi-pod.yamlStep 2: Add Second Container
Section titled “Step 2: Add Second Container”Edit the file and duplicate the container section:
apiVersion: v1kind: Podmetadata: name: multispec: containers: - name: nginx image: nginx - name: sidecar # Add this image: busybox # Add this command: ["sleep", "3600"] # Add thisPractice Until Automatic
Section titled “Practice Until Automatic”This pattern appears in ~20% of CKAD questions. You should be able to:
- Generate base YAML
- Add a sidecar container
- Apply and verify
All in under 2 minutes.
Quick Testing Patterns
Section titled “Quick Testing Patterns”CKAD often asks you to verify your work. These patterns help:
Test Pod-to-Service Connectivity
Section titled “Test Pod-to-Service Connectivity”# One-liner test podk run test --image=busybox --rm -it --restart=Never -- wget -qO- http://service-name
# DNS resolution testk run test --image=busybox --rm -it --restart=Never -- nslookup service-name
# Test with curlk run test --image=curlimages/curl --rm -it --restart=Never -- curl http://service-nameCheck Pod Logs Quickly
Section titled “Check Pod Logs Quickly”# Last 10 linesk logs pod-name --tail=10
# Follow logsk logs pod-name -f
# Specific container in multi-container podk logs pod-name -c container-name
# Previous container (if restarted)k logs pod-name --previousDebug Inside a Container
Section titled “Debug Inside a Container”# Interactive shellk exec -it pod-name -- sh
# Specific containerk exec -it pod-name -c container-name -- sh
# Run a single commandk exec pod-name -- cat /etc/config/app.confStop and think: You need to verify that a Service called
backendis reachable from within the cluster. What one-liner kubectl command would you use to test this without leaving any resources behind?
JSON Path for Quick Data Extraction
Section titled “JSON Path for Quick Data Extraction”Some CKAD questions ask for specific values. JSONPath helps:
# Get pod IPk get pod nginx -o jsonpath='{.status.podIP}'
# Get all pod IPsk get pods -o jsonpath='{.items[*].status.podIP}'
# Get container imagek get pod nginx -o jsonpath='{.spec.containers[0].image}'
# Get node where pod runsk get pod nginx -o jsonpath='{.spec.nodeName}'Common JSONPath Patterns for CKAD
Section titled “Common JSONPath Patterns for CKAD”# All container names in a podk get pod multi -o jsonpath='{.spec.containers[*].name}'
# All service cluster IPsk get svc -o jsonpath='{.items[*].spec.clusterIP}'
# ConfigMap datak get cm myconfig -o jsonpath='{.data.key}'
# Secret data (base64 encoded)k get secret mysecret -o jsonpath='{.data.password}' | base64 -dNamespace Management
Section titled “Namespace Management”CKAD questions often specify namespaces. Be fast:
# Create namespacek create ns dev
# Set default namespace for sessionk config set-context --current --namespace=dev
# Run command in specific namespacek get pods -n prod
# All namespacesk get pods -AStop and think: What would happen if you forget to switch namespaces between two consecutive exam tasks? If the first task uses the
devnamespace and the second usesprod, what goes wrong, and how long might it take you to realize the mistake?
Pro Tip: Check Namespace First
Section titled “Pro Tip: Check Namespace First”Many exam questions fail because candidates work in the wrong namespace. Always verify:
# Check current namespacek config view --minify | grep namespace
# Or set it explicitly in each commandk get pods -n specified-namespaceVim Speed for YAML Editing
Section titled “Vim Speed for YAML Editing”You’ll edit YAML constantly. These Vim settings help:
" Add to ~/.vimrcset tabstop=2set shiftwidth=2set expandtabset autoindentEssential Vim Commands for YAML
Section titled “Essential Vim Commands for YAML”" Copy a lineyy
" Paste belowp
" Delete a linedd
" Indent a block (visual mode)>>
" Unindent a block<<
" Search for text/searchterm
" Jump to line 50:50
" Save and quit:wqCopying YAML Blocks
Section titled “Copying YAML Blocks”When adding a sidecar container, you’ll copy an existing container spec:
1. Position cursor on the line with "- name:"2. V (visual line mode)3. Move down to select all container lines4. y (yank/copy)5. Move to where you want the new container6. p (paste)7. Edit the pasted blockDid You Know?
Section titled “Did You Know?”- The
--restart=Neverflag sets the pod’srestartPolicytoNever. This is crucial for test pods that run a single command and exit, preventing Kubernetes from continuously restarting the container after it finishes. - The
--rmflag deletes the pod after it exits, which is perfect for one-off tests and keeps your environment clean. - You can combine
-itand--rmfor ephemeral debug sessions. The pod runs interactively and disappears entirely when you exit the shell. - JSONPath in kubectl uses the exact same syntax as the Kubernetes API. Practicing it helps with both the exam and real-world automation scripts.
Common Mistakes
Section titled “Common Mistakes”| Mistake | Why It Hurts | Solution |
|---|---|---|
Forgetting --restart=Never on test pods | Pod enters CrashLoopBackOff as it restarts continuously after exiting | Make it part of your one-off test pattern |
| Wrong namespace | Resources are created in default or previous namespace | Always check/set namespace first |
| Editing YAML with wrong indent | Invalid YAML, cryptic errors | Use :set paste in Vim before pasting |
Not using --dry-run | Slower YAML creation | Make $kdr variable second nature |
| Searching docs too much | Time wasted | Memorize common specs |
-
Your team lead asks you to quickly generate the YAML for a new batch Job without actually running it in the cluster. You need to hand off the YAML file for code review. What’s the fastest approach?
Answer
Use `kubectl create job myjob --image=busybox -- echo done --dry-run=client -o yaml > job.yaml`. The `--dry-run=client` flag generates valid YAML without contacting the API server, and `-o yaml` outputs it in YAML format. This is the standard generate-then-edit workflow for CKAD because you generate a skeleton imperatively, then customize the YAML as needed. This practice saves significant time compared to writing YAML completely from scratch. -
After deploying a new Service called
api-gateway, you need to verify it’s reachable from inside the cluster — but you don’t want to leave any debug resources behind. How do you test this cleanly?Answer
Run `kubectl run test --image=busybox --rm -it --restart=Never -- wget -qO- http://api-gateway`. The `--rm` flag automatically deletes the pod when it exits, and `-it` gives you interactive output. The `--restart=Never` flag is critical because it ensures the Pod does not continuously restart itself after the `wget` command finishes successfully. This one-liner is essential for CKAD, as you will use it repeatedly to verify Services, DNS resolution, and connectivity without polluting the cluster. -
A CKAD exam task says: “Write the image used by the first container in pod
web-appto the file/opt/answer.txt.” You need to extract just the image string, not the full pod spec. How do you do this efficiently?Answer
Use `kubectl get pod web-app -o jsonpath='{.spec.containers[0].image}' > /opt/answer.txt`. JSONPath allows you to drill directly into the pod spec and extract exactly the field you need without any extra text. The `{.spec.containers[0].image}` path navigates exactly to the first container's image field. This approach is much faster than running a `describe` followed by manual copying, and it is far less error-prone than attempting to `grep` on YAML output. -
You just completed a task in the
paymentsnamespace and moved to the next task, which requires working ininventory. You create a Deployment, butkubectl get podsshows nothing. What likely went wrong, and what’s the fastest fix?Answer
You are likely still operating in the `payments` namespace, meaning your Deployment was created there instead of in `inventory`. The fastest fix is to switch contexts immediately using `kubectl config set-context --current --namespace=inventory`, then verify with `kubectl get pods`. To prevent this frustrating issue, you must always check or explicitly set your namespace at the start of every single exam task. Many candidates lose points purely to namespace placement errors.
Hands-On Exercise
Section titled “Hands-On Exercise”Task: Practice the CKAD developer workflow patterns.
Part 1: Dry-Run Mastery (Target: 3 minutes)
# Generate these YAML files using --dry-run# 1. Pod named 'web' with nginx image# 2. Deployment named 'api' with httpd image, 2 replicas# 3. Job named 'backup' that echoes "complete"# 4. CronJob named 'hourly' running every hourPart 2: Multi-Container Creation (Target: 4 minutes)
# Create a pod with two containers:# - main: nginx# - sidecar: busybox running "sleep 3600"Part 3: Quick Testing (Target: 2 minutes)
# Test connectivity to a service# Verify pod logs work# Execute a command in a containerSuccess Criteria:
- All YAML files generated correctly
- Multi-container pod running with both containers Ready
- Test commands execute successfully
Practice Drills
Section titled “Practice Drills”Drill 1: Alias Verification (Target: 1 minute)
Section titled “Drill 1: Alias Verification (Target: 1 minute)”Verify your aliases work:
# These should all workk get podskgy pod nginx # Get YAML of a podkdr # Should echo "--dry-run=client -o yaml"Drill 2: YAML Generation Speed (Target: 5 minutes)
Section titled “Drill 2: YAML Generation Speed (Target: 5 minutes)”Generate YAML for each resource type without looking at notes:
# Podk run nginx --image=nginx $kdr > /tmp/pod.yaml
# Deploymentk create deploy web --image=nginx $kdr > /tmp/deploy.yaml
# Servicek create svc clusterip mysvc --tcp=80:80 $kdr > /tmp/svc.yaml
# Jobk create job backup --image=busybox -- echo done $kdr > /tmp/job.yaml
# CronJobk create cronjob hourly --image=busybox --schedule="0 * * * *" -- date $kdr > /tmp/cronjob.yaml
# ConfigMapk create cm myconfig --from-literal=key=value $kdr > /tmp/cm.yaml
# Secretk create secret generic mysecret --from-literal=password=secret $kdr > /tmp/secret.yamlDrill 3: Multi-Container Speed (Target: 3 minutes)
Section titled “Drill 3: Multi-Container Speed (Target: 3 minutes)”Create a multi-container pod from scratch:
# Generate basek run multi --image=nginx $kdr > /tmp/multi.yaml
# Edit to add sidecar (use vim)vim /tmp/multi.yaml
# Applyk apply -f /tmp/multi.yaml
# Verify both containers runningk get pod multi -o jsonpath='{.spec.containers[*].name}'# Expected: nginx sidecar
# Cleanupk delete pod multiDrill 4: JSONPath Extraction (Target: 3 minutes)
Section titled “Drill 4: JSONPath Extraction (Target: 3 minutes)”# Create a test pod firstk run nginx --image=nginx
# Wait for runningk wait --for=condition=Ready pod/nginx
# Extract these values using JSONPath:# 1. Pod IPk get pod nginx -o jsonpath='{.status.podIP}'
# 2. Container imagek get pod nginx -o jsonpath='{.spec.containers[0].image}'
# 3. Node namek get pod nginx -o jsonpath='{.spec.nodeName}'
# 4. Pod phase (Running/Pending/etc)k get pod nginx -o jsonpath='{.status.phase}'
# Cleanupk delete pod nginxDrill 5: Namespace Workflow (Target: 2 minutes)
Section titled “Drill 5: Namespace Workflow (Target: 2 minutes)”# Create a namespacek create ns ckad-test
# Set as defaultk config set-context --current --namespace=ckad-test
# Verifyk config view --minify | grep namespace
# Create a pod (should go to ckad-test)k run nginx --image=nginx
# Verify pod is in ckad-testk get pods # Should show nginxk get pods -n default # Should NOT show nginx
# Reset namespacek config set-context --current --namespace=default
# Cleanupk delete ns ckad-testDrill 6: Complete Developer Workflow (Target: 8 minutes)
Section titled “Drill 6: Complete Developer Workflow (Target: 8 minutes)”Simulate a CKAD task end-to-end:
Scenario: Create a web application with a sidecar that logs access.
# 1. Create namespacek create ns web-app
# 2. Set namespacek config set-context --current --namespace=web-app
# 3. Generate multi-container pod YAMLk run webapp --image=nginx $kdr > /tmp/webapp.yaml
# 4. Edit to add sidecar (logs container)# Add this container:# - name: logger# image: busybox# command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]# volumeMounts:# - name: logs# mountPath: /var/log/nginx
# 5. Applyk apply -f /tmp/webapp.yaml
# 6. Verify both containers runningk get pod webapp -o widek describe pod webapp | grep -A5 Containers
# 7. Test connectivityk expose pod webapp --port=80k run test --image=busybox --rm -it --restart=Never -- wget -qO- http://webapp
# 8. Cleanupk config set-context --current --namespace=defaultk delete ns web-appNext Module
Section titled “Next Module”Module 1.1: Container Images - Build, tag, and push container images for CKAD.