KCNA Hands-on Lab Exercises¶
These labs reinforce KCNA concepts through practical exercises. While KCNA is a multiple-choice exam, hands-on experience helps solidify understanding.
Prerequisites¶
- Access to a Kubernetes cluster (minikube, kind, or cloud)
- kubectl installed and configured
- Basic terminal/command line knowledge
Lab 1: Kubernetes Architecture Exploration¶
Objective: Understand Kubernetes cluster components
Tasks¶
- Explore control plane components:
# List all pods in kube-system namespace
kubectl get pods -n kube-system
# Describe the API server pod
kubectl describe pod -n kube-system -l component=kube-apiserver
# Check etcd pod
kubectl describe pod -n kube-system -l component=etcd
- Examine node components:
# List all nodes
kubectl get nodes -o wide
# Describe a node to see kubelet info
kubectl describe node <node-name>
# Check node conditions
kubectl get nodes -o jsonpath='{.items[*].status.conditions}'
- Verify cluster health:
Expected Outcome
You should see: - Control plane pods: kube-apiserver, etcd, kube-controller-manager, kube-scheduler - Node components: kubelet, kube-proxy - Cluster is healthy with all components runningLab 2: Pod Lifecycle and Management¶
Objective: Understand pod creation, states, and lifecycle
Tasks¶
- Create a simple pod:
# Create pod imperatively
kubectl run nginx-pod --image=nginx:latest
# Verify pod is running
kubectl get pod nginx-pod -w
- Create pod from YAML:
# Save as simple-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
labels:
app: demo
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
- name: sidecar
image: busybox
command: ['sh', '-c', 'while true; do echo "sidecar running"; sleep 10; done']
kubectl apply -f simple-pod.yaml
kubectl get pod multi-container-pod
kubectl logs multi-container-pod -c sidecar
- Explore pod states:
# Create a pod that will fail
kubectl run failing-pod --image=nonexistent:image
# Watch the pod status
kubectl get pod failing-pod -w
# Check events
kubectl describe pod failing-pod
- Cleanup:
Expected Outcome
- Pods transition through Pending → ContainerCreating → Running - Failed pods show ImagePullBackOff or ErrImagePull - Multi-container pods run all containers in same podLab 3: Deployments and ReplicaSets¶
Objective: Understand deployment strategies and scaling
Tasks¶
- Create a deployment:
kubectl create deployment web-app --image=nginx:1.19 --replicas=3
kubectl get deployment web-app
kubectl get replicaset
kubectl get pods -l app=web-app
- Scale the deployment:
# Scale up
kubectl scale deployment web-app --replicas=5
kubectl get pods -l app=web-app
# Scale down
kubectl scale deployment web-app --replicas=2
kubectl get pods -l app=web-app
- Update the deployment:
# Update image
kubectl set image deployment/web-app nginx=nginx:1.20
# Watch rollout
kubectl rollout status deployment/web-app
# Check rollout history
kubectl rollout history deployment/web-app
- Rollback:
# Rollback to previous version
kubectl rollout undo deployment/web-app
# Verify
kubectl describe deployment web-app | grep Image
- Cleanup:
Expected Outcome
- Deployment manages ReplicaSet which manages Pods - Scaling adjusts pod count - Rolling updates replace pods gradually - Rollback reverts to previous ReplicaSetLab 4: Services and Networking¶
Objective: Understand Kubernetes service types
Tasks¶
- Create deployment and ClusterIP service:
kubectl create deployment web --image=nginx --replicas=3
kubectl expose deployment web --port=80 --type=ClusterIP
kubectl get svc web
- Test ClusterIP service:
# Create a test pod
kubectl run test-pod --image=busybox --rm -it --restart=Never -- wget -qO- http://web
- Create NodePort service:
kubectl expose deployment web --port=80 --type=NodePort --name=web-nodeport
kubectl get svc web-nodeport
- Explore service endpoints:
- Cleanup:
Expected Outcome
- ClusterIP: Internal cluster access only - NodePort: External access via node IP + port - Services load balance across pod endpointsLab 5: ConfigMaps and Secrets¶
Objective: Understand configuration management
Tasks¶
- Create ConfigMap:
# From literal
kubectl create configmap app-config --from-literal=APP_ENV=production --from-literal=LOG_LEVEL=info
# View ConfigMap
kubectl get configmap app-config -o yaml
- Create Secret:
# Create secret
kubectl create secret generic db-secret --from-literal=DB_USER=admin --from-literal=DB_PASS=secretpassword
# View secret (base64 encoded)
kubectl get secret db-secret -o yaml
- Use in Pod:
# Save as config-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-demo
spec:
containers:
- name: app
image: busybox
command: ['sh', '-c', 'echo "Env: $APP_ENV, User: $DB_USER" && sleep 3600']
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-secret
key: DB_USER
- Cleanup:
Expected Outcome
- ConfigMaps store non-sensitive configuration - Secrets store sensitive data (base64 encoded) - Both can be injected as environment variables or volumesLab 6: Namespaces and Resource Quotas¶
Objective: Understand multi-tenancy basics
Tasks¶
- Create namespace:
- Deploy to namespace:
- Create ResourceQuota:
# Save as quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev-team
spec:
hard:
pods: "5"
requests.cpu: "2"
requests.memory: 2Gi
limits.cpu: "4"
limits.memory: 4Gi
- Test quota limits:
# Try to create more pods than allowed
kubectl create deployment test --image=nginx --replicas=10 -n dev-team
kubectl get pods -n dev-team
kubectl describe deployment test -n dev-team
- Cleanup: