Kubernetes practice
Explore the cluster, simulate Pod recovery, and try the kubectl exercise. The browser simulations need no setup; the command-line exercise requires a disposable local cluster.
Review Kubernetes foundationsInside a Kubernetes cluster
Select a component to inspect its role, or follow a request through the cluster.
Outer frame = Pod; inner block = container. Connections describe control communication, not application traffic. Pod placement is illustrative.
Teaching model: real controllers operate asynchronously through the API. This is not a live cluster. Cloud integration is optional; networking implementations vary. The diagram omits CNI, DNS, storage and control-plane replicas to keep the core roles readable.
Keep the promise of three replicas
Predict first, then step through. Set replicas to 4 and worker slots to 2. Why do two Pods stay Pending?
No Pod objects
The Deployment requests three replicas. No Pod objects exist yet. Take the next step to let the ReplicaSet controller act.
Browser simulation, not a live cluster. One slot represents an entire Pod request. Real scheduling considers CPU, memory, constraints and policies. Steps run concurrently in real clusters; readiness, image failures, retries and termination delays are omitted.
Observe reconciliation in a real cluster
Optional on your first read. You need kubectl, a disposable local cluster (kind or minikube), permission to create a namespace and workloads, and internet access from the cluster to pull the image. Cluster installation is covered in Your first cluster. The browser labs above work without any installation.
Use only your own disposable local cluster. Confirm the context before creating anything. If academy-foundations already exists, stop and choose an unused lab namespace, replacing it in every command and in the manifest.
kubectl config current-context
kubectl get nodes
kubectl create namespace academy-foundationskind-kind
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane ... v1.x.y
namespace/academy-foundations createdRead the contract before applying it
Save this as foundations-web.yaml. apiVersion and kind choose the resource type; metadata names it. spec.replicas requests three copies. The selector matches the template labels, which let the ReplicaSet identify its Pods. template describes each Pod. The HTTP readiness probe tests whether nginx can answer; containerPort alone does not expose a Service or publish a host port.
apiVersion: apps/v1
kind: Deployment
metadata:
name: foundations-web
namespace: academy-foundations
spec:
replicas: 3
selector:
matchLabels:
app: foundations-web
template:
metadata:
labels:
app: foundations-web
spec:
containers:
- name: web
image: nginx:stable-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
memory: 128Mi
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 2
periodSeconds: 3The stable-alpine tag is convenient for this disposable lab but can change. Production releases should use a reviewed version or immutable digest. CPU and memory requests are scheduling inputs; these small example values are not production sizing guidance.
kubectl apply -f foundations-web.yaml
kubectl -n academy-foundations rollout status deployment/foundations-web --timeout=120s
kubectl -n academy-foundations get deployment,replicaset,podsdeployment.apps/foundations-web created
...
deployment "foundations-web" successfully rolled out
...
NAME READY UP-TO-DATE AVAILABLE
deployment.apps/foundations-web 3/3 3 3# Terminal 2
kubectl -n academy-foundations get pods -l app=foundations-web -w
# Terminal 1
kubectl -n academy-foundations get pods -l app=foundations-web -o custom-columns=NAME:.metadata.name,UID:.metadata.uid
LAB_POD=$(kubectl -n academy-foundations get pods -l app=foundations-web -o jsonpath='{.items[0].metadata.name}')
kubectl -n academy-foundations delete pod "$LAB_POD"
kubectl -n academy-foundations rollout status deployment/foundations-web --timeout=120s
kubectl -n academy-foundations get pods -l app=foundations-web -o custom-columns=NAME:.metadata.name,UID:.metadata.uidA deleted Pod disappears.
A new Pod progresses from Pending toward Running.
After recovery, three Pods exist again.
The replacement UID differs from the deleted Pod's UID.
Exact names, event order and timings vary.kubectl apply -f foundations-web.yaml
kubectl -n academy-foundations rollout status deployment/foundations-web --timeout=120s
kubectl -n academy-foundations get deployment foundations-webdeployment.apps/foundations-web configured
...
NAME READY UP-TO-DATE AVAILABLE
foundations-web 2/2 2 2If the expected state never arrives
kubectl -n academy-foundations describe deployment foundations-web
kubectl -n academy-foundations describe pods -l app=foundations-web
kubectl -n academy-foundations get events --sort-by=.metadata.creationTimestamp- Pending + FailedScheduling: inspect requests, node capacity and placement constraints.
- ImagePullBackOff: inspect the image name, registry access and network. Extra replicas do not fix a bad image.
- Running but 0/1 Ready: inspect the readiness probe and application. A running process may still be unable to serve requests.
kubectl delete namespace academy-foundationsnamespace "academy-foundations" deletedExercise: explain the result before reading the answer
Deleting a managed Pod changes observed state, so the ReplicaSet creates a replacement. Editing replicas changes desired state, so the ReplicaSet keeps the new count.