Kubernetes Hands-on Exercises — Manage the Restaurant
Time to stop reading and start doing. These exercises require a Kubernetes cluster. The easiest way is minikube (local) or kind (Docker-based).
Install minikube first (minikube start), then type the commands one by one and read the output.
Exercise 0 · Setup — Connect to the Restaurant
minikube start
kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:8443
kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 30s v1.28.x
minikube gives you a single-node cluster locally. It's perfect for learning and exercises.
Exercise 1 · First Deployment — Hire Your First Chef
cat > deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: campus-library
spec:
replicas: 2
selector:
matchLabels:
app: campus-library
template:
metadata:
labels:
app: campus-library
spec:
containers:
- name: web
image: nginx:alpine
ports:
- containerPort: 80
EOF
kubectl apply -f deployment.yaml
deployment.apps/campus-library created
kubectl get pods
NAME READY STATUS RESTARTS AGE
campus-library-7d4b8c9f-x2k4m 1/1 Running 0 10s
campus-library-7d4b8c9f-a9n3p 1/1 Running 0 10s
kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
campus-library 2/2 2 2 30s
You created 2 Pods with one command. If one dies, the Deployment replaces it automatically.
Exercise 2 · Service — Open the Order Window
cat > service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
name: campus-library-svc
spec:
selector:
app: campus-library
ports:
- port: 80
targetPort: 80
type: NodePort
EOF
kubectl apply -f service.yaml
kubectl get svc campus-library-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
campus-library-svc NodePort 10.96.123.45 <none> 80:31234/TCP 5s
curl $(minikube service campus-library-svc --url)
<!DOCTYPE html>
<html>
<head><title>Welcome to nginx!</title>...
The Service gives a stable address. Even if Pods are replaced, the Service IP and DNS name stay the same.
Exercise 3 · Scaling — Hire More Chefs
kubectl scale deployment campus-library --replicas=5
kubectl get pods -w
NAME READY STATUS AGE
campus-library-7d4b8c9f-x2k4m 1/1 Running 5m
campus-library-7d4b8c9f-a9n3p 1/1 Running 5m
campus-library-7d4b8c9f-q8w2r 0/1 ContainerCreating 0s
campus-library-7d4b8c9f-m3j5n 0/1 ContainerCreating 0s
campus-library-7d4b8c9f-k8p2w 0/1 ContainerCreating 0s
After a few seconds, all 5 should be Running.
kubectl scale deployment campus-library --replicas=2
Scaling is instant. Kubernetes creates or removes Pods based on the replica count you specify.
Exercise 4 · Update and Rollback — Change the Menu
kubectl set image deployment/campus-library web=nginx:1.25-alpine
kubectl rollout status deployment/campus-library
deployment "campus-library" successfully rolled out
kubectl rollout history deployment/campus-library
REVISION CHANGE-CAUSE
1 <none>
2 <none>
kubectl rollout undo deployment/campus-library
deployment.apps/campus-library rolled back
rollout undo is instant. Old ReplicaSets are kept for exactly this purpose.
Exercise 5 · Debugging — Inspect the Kitchen
kubectl describe pod $(kubectl get pods -l app=campus-library -o jsonpath='{.items[0].metadata.name}')
Look for the Events section at the bottom — this tells you what Kubernetes did with the Pod.
kubectl logs $(kubectl get pods -l app=campus-library -o jsonpath='{.items[0].metadata.name}')
127.0.0.1 - - [10/Oct/2024:12:00:00 +0000] "GET / HTTP/1.1" 200 615 "-"
kubectl exec -it $(kubectl get pods -l app=campus-library -o jsonpath='{.items[0].metadata.name}') -- sh
/ # exit
When something goes wrong: kubectl get pods → kubectl describe pod <name> → kubectl logs <name>. This is the debugging trifecta.
Exercise 6 · Cleanup — Close the Restaurant
kubectl delete -f service.yaml
kubectl delete -f deployment.yaml
kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m
Deleting the Deployment removes all its Pods. Deleting the Service removes the stable address. Always clean up after exercises.