CKAD — Pod Design Hands-On Lab & Practice
Lab 1: Label Management
Practice adding, viewing, and selecting Pods by labels.
# Create 3 Pods with different labels
kubectl run app1 --image=nginx --labels="app=web,env=prod"
kubectl run app2 --image=nginx --labels="app=web,env=staging"
kubectl run app3 --image=nginx --labels="app=api,env=prod"
# Find all Pods in prod environment
kubectl get pods -l env=prod
# Expected: app1 and app3
# Find all web Pods
kubectl get pods -l app=web
# Expected: app1 and app2
# Find web Pods in prod
kubectl get pods -l app=web,env=prod
# Expected: app1 only
# Add a version label to all web Pods
kubectl label pods -l app=web version=v1
# Verify
kubectl get pods -l app=web --show-labels
# Expected: app1 and app2 both show version=v1
Verify Your Work
# Count Pods matching each selector
kubectl get pods -l env=prod --no-headers | wc -l
# Expected: 2
kubectl get pods -l app=web,env=prod --no-headers | wc -l
# Expected: 1
kubectl get pods -l 'env in (prod,staging)' --no-headers | wc -l
# Expected: 3
Lab 2: Annotations
Practice adding and managing annotations.
# Add annotations to a Pod
kubectl annotate pod app1 build="ci-build-123" team="platform"
# Verify annotations
kubectl describe pod app1 | grep -A 5 Annotations
# Update an annotation
kubectl annotate pod app1 build="ci-build-456" --overwrite
# Remove an annotation
kubectl annotate pod app1 team-
# Verify removal
kubectl get pod app1 -o jsonpath='{.metadata.annotations}' | python3 -m json.tool
Lab 3: Pod Lifecycle Debugging
Practice debugging Pods in different states.
# Create a Pod that will crash
kubectl run crasher --image=busybox:1.36 -- /bin/sh -c "exit 1"
# Check the status — it will show CrashLoopBackOff
kubectl get pod crasher -w
# Press Ctrl+C after seeing CrashLoopBackOff, then check events
kubectl describe pod crasher | tail -20
# Check the exit code
kubectl get pod crasher -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'
# Expected: 1
# Check restart count
kubectl get pod crasher -o jsonpath='{.status.containerStatuses[0].restartCount}'
# Expected: a number > 0
# Clean up
kubectl delete pod crasher
Create a Succeeding Pod
# Create a Pod that exits successfully
kubectl run success --image=busybox:1.36 --restart=Never -- /bin/sh -c "echo done"
# Check status
kubectl get pod success
# Expected: STATUS = Completed
# Check logs
kubectl logs success
# Expected: done
# Clean up
kubectl delete pod success
Lab 4: Ephemeral Volumes
Practice sharing data between containers using emptyDir.
# Create the Pod spec
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: vol-lab
spec:
containers:
- name: writer
image: busybox:1.36
command: ["/bin/sh", "-c"]
args:
- |
for i in 1 2 3 4 5; do
echo "Message \$i at \$(date)" >> /shared/messages.txt
sleep 2
done
sleep 3600
volumeMounts:
- name: shared
mountPath: /shared
- name: reader
image: busybox:1.36
command: ["/bin/sh", "-c", "sleep 15 && cat /shared/messages.txt && sleep 3600"]
volumeMounts:
- name: shared
mountPath: /shared
volumes:
- name: shared
emptyDir: {}
EOF
# Wait for the Pod to be ready
kubectl wait --for=condition=Ready pod/vol-lab --timeout=30s
# Read the shared messages
kubectl exec vol-lab -c reader -- cat /shared/messages.txt
# Expected: 5 messages with timestamps
# Clean up
kubectl delete pod vol-lab
Lab 5: Node Selection
Practice scheduling Pods on specific nodes (requires a multi-node cluster).
# List your nodes
kubectl get nodes
# Label a node
kubectl label node <node-name> disktype=ssd
# Create a Pod that requires the label
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: ssd-pod
spec:
nodeSelector:
disktype: ssd
containers:
- name: app
image: nginx:1.27
EOF
# Verify the Pod is on the labeled node
kubectl get pod ssd-pod -o wide
# Expected: NODE column shows the labeled node
# Clean up
kubectl delete pod ssd-pod
kubectl label node <node-name> disktype-
Practice Questions
Q1: How do you select all Pods that have the label env=prod but NOT app=cache?
Show Answer
```bash kubectl get pods -l 'env=prod,app!=cache' ``` Or using set-based syntax: ```bash kubectl get pods -l 'env=prod,app notin (cache)' ```Q2: What is the difference between labels and annotations?
Show Answer
**Labels** are used to identify and select objects. Kubernetes uses them for grouping, filtering, and service discovery. They have strict character limits (63 chars, alphanumeric + `-_.`). **Annotations** store non-identifying metadata. They are used by tools, humans, and controllers for additional information (build details, monitoring configuration, etc.). They can contain larger, unstructured data.Q3: A Pod is stuck in Pending state. List 3 possible reasons and how to debug each.