Run a Kubernetes deployment and break its service
Task
Deploy an application to a local Kubernetes cluster, confirm the control loop replaces a killed pod, and reproduce the commonest Service failure -- a selector that matches no pods -- then diagnose it the way you would in production.
Steps
- Apply a Deployment named
webwith three replicas of a simple web image, its pods labelledapp: web-- the names the Verify uses -- and confirmkubectl get podsshows three running. - Delete one pod with
kubectl delete pod <name>and watch the control loop start a replacement within seconds. State why a bare Pod would not have come back. - Add a Service named
webselecting the deployment's pods by label, and confirmkubectl get endpointslists three endpoints. Reach the app through it. - Break it: change the Service's selector to a label no pod has. Confirm the Service object still looks healthy in
kubectl get service web, that connections to it now fail -- refused at once under kube-proxy's default iptables mode, which rejects traffic to a Service with no endpoints -- and thatkubectl get endpointsnow shows<none>. - Diagnose from the symptom:
kubectl describe serviceandkubectl get endpointstogether point at the label mismatch. Fix the selector and confirm endpoints return. - Add a ConfigMap for non-secret settings and a Secret named
webholding a keypassword(kubectl create secret generic web --from-literal=password=lab-only), mount both, and confirm the Secret is only base64-encoded -- decode it withkubectl get secret ... -o jsonpathandbase64 -d. - Roll out an image change and use
kubectl rollout statusandkubectl rollout undoto advance and revert it.
Verify
kubectl get deploy web -o jsonpath='{.status.readyReplicas}' # 3
kubectl delete "$(kubectl get pod -l app=web -o name | head -1)" # one pod, as in step 2
kubectl wait --for=condition=Ready pod -l app=web --timeout=60s >/dev/null
kubectl get pods -l app=web --no-headers | grep -c Running # back to 3
kubectl get endpoints web -o jsonpath='{.subsets}' ; echo # <none> when broken
kubectl get secret web -o jsonpath='{.data.password}' | base64 -d; echo # plaintext
The endpoints going to <none> when the selector is wrong is the diagnosis to carry: a Service with no matching pods looks healthy and refuses every connection, and kubectl get endpoints is the one command that says why. (Deleting with -l app=web would take all three pods at once, not the one step 2 describes; kubectl wait replaces a fixed sleep that could count a replacement still starting.) The base64 decode proves a Secret is encoding, not encryption.
Notes
A bare Pod that dies stays dead; a Deployment maintains the replica count. That is the single most useful fact about Pods, and step 2 is where it becomes concrete -- the killed pod is replaced because the control loop is comparing desired state to actual and closing the gap.
This is an independent study companion for CompTIA Linux+ and is not produced by or endorsed by CompTIA.