TinyPDF.in / Playgrounds
Deploy a sample web app, watch its pods come up, run a rolling update, break it on purpose, and try kubectl-style commands.
Work through the stages in order. Each one builds on the last, and the stage goal says what you should understand by the end.
Goal: see a Deployment create pods, serve traffic, update, and recover.
image: hello-web:1.0 to hello-web:2.0, apply, and watch the rolling update keep pods serving.hello-web:broken and apply. The rollout stalls, and only the old pods serve traffic.Goal: see what a pod without a controller does, and how it differs from a Deployment.
kubectl delete pod NAME. Nothing brings it back, because it has no controller.kubectl run debug --image=hello-web:1.0, then kubectl get pods.kubectl expose deployment hello-web --port=8080 --name=web, then request web a few times.Goal: find out where each event comes from, using the Logs, Events and Control plane panels.
Goal: pass settings into pods with ConfigMaps and Secrets, and see what happens when a dependency is missing.
kubectl create configmap app-config --from-literal=MESSAGE=changed: running pods keep the old value until they restart.kubectl get secret db -o yaml. The value is base64, which is encoding, not encryption. describe pod hides it.CreateContainerConfigError until you create it.kubectl exec config-pod -- ls /etc/config and cat /etc/config/MESSAGE. Change the ConfigMap's MESSAGE, apply, and the file updates in about 10 seconds. The env var would not change until a restart. Writing to the file fails: config volumes are read-only.cat /etc/secret/PASSWORD shows the value. The Secret is stored encoded, but this is still a plain file for anything in the pod.configMapKeyRef, secretKeyRef or envFrom can't start until the object exists. Without it, the pod shows CreateContainerConfigError and retries each tick, so applying them first avoids the wait.persistentvolumeclaim "NAME" not found. Apply the claim first, or in the same file above the pod.--- and apply them together in the order above. Re-applying an unchanged object prints unchanged.A real cluster has the same dependencies, but its controllers keep retrying, so the order matters less. The playground shows each wait so you can see the cause.
Goal: tell a pod that isn't ready (removed from the Service) apart from one that is stuck (restarted).
hello-web:stuck and add a livenessProbe). Readiness removes the pod from the Service first, then liveness restarts it, and RESTARTS goes up.Goal: see which data survives a pod restart and which doesn't, and how claims are shared.
kubectl exec writer -- write /data/notes.txt hello, delete the pod, and apply again. The file is still there. Then write under /scratch (an emptyDir) and see it vanish with the pod.ReadWriteMany, and both run.kubectl get pv shows Bound. Delete the claim, and with the Retain policy the volume becomes Released and won't bind to a new claim until you clean it up.kubectl get pv shows one called pvc-data, made by the standard class. Its Delete policy means deleting the claim deletes the volume and its data.Goal: reach pods by name, control who can reach them, and route HTTP through an Ingress.
kubectl exec client -- wget http://hello-web and nslookup hello-web work. Then try request node-1:30080: the policy blocks it too, because outside traffic has no role=client label. Delete the policy with kubectl delete netpol only-client and it works.role=client. Run kubectl run other --image=busybox:1.36 and try to wget from it: it times out.request web: the Service sends to 9090 but the app listens on 8080, so the request is refused. Fix targetPort to 8080, apply, and it works. kubectl get endpoints web shows the IP and port the Service sends to.request ingress web-ingress / --host=hello.local, and try a different --host to see the 404. kubectl get ingress shows the host and address.YAML for a Deployment and a Service. Edit it, then apply it. Supported: Deployment, Service.
Green: ready. Amber: starting or not ready. Red: readiness failing. Dashed: pending, not scheduled yet. Click a pod to delete it.
Each box is a part of Kubernetes doing work in this model. The count is how many events it caused. Recent actions are listed under it.
Tab completes commands, names and flags. Up and Down recall earlier commands. Try kubectl get pods -o wide, kubectl get pods -l app=hello-web -o name or clear. Ctrl+L also clears.
Each example gives the command, what it does, and the output the playground prints for it. Try them in order from the top.
kubectl get pods
Lists the pods. READY shows whether the container is ready. STATUS is the pod phase. RESTARTS counts container restarts.
NAME READY STATUS RESTARTS AGE NODE hello-web-1w4zot-kvzp9 1/1 Running 0 13s node-2 hello-web-1w4zot-qrfnj 1/1 Running 0 12s node-3 hello-web-1w4zot-vbs99 1/1 Running 0 14s node-1
kubectl get pods -o wide
Adds the pod IP to the table.
NAME READY STATUS RESTARTS AGE NODE IP hello-web-1w4zot-kvzp9 1/1 Running 0 13s node-2 10.244.2.3 hello-web-1w4zot-qrfnj 1/1 Running 0 12s node-3 10.244.3.4 hello-web-1w4zot-vbs99 1/1 Running 0 14s node-1 10.244.1.2
kubectl get pods -o name
Prints one name per line, in the form pod/NAME. Useful in scripts.
pod/hello-web-1w4zot-kvzp9 pod/hello-web-1w4zot-qrfnj pod/hello-web-1w4zot-vbs99
kubectl get pods -l app=hello-web
Shows only pods whose labels match. Use --selector=KEY=VALUE for the same thing.
NAME READY STATUS RESTARTS AGE NODE hello-web-1w4zot-kvzp9 1/1 Running 0 13s node-2 hello-web-1w4zot-qrfnj 1/1 Running 0 12s node-3 hello-web-1w4zot-vbs99 1/1 Running 0 14s node-1
kubectl get svc -o yaml
Shows a Service as a manifest, so you can see its selector, port and targetPort.
apiVersion: v1
kind: Service
metadata:
name: hello-web
spec:
type: ClusterIP
clusterIP: 10.96.0.10
selector:
app: hello-web
ports:
- port: 8080
targetPort: 8080
kubectl describe pod hello-web-1w4zot-vbs99
Shows the node, IP, status and recent events for one pod. Replace NAME with a name from kubectl get pods.
Name: hello-web-1w4zot-vbs99 Node: node-1 IP: 10.244.1.2 Status: Running Ready: true Restart Count: 0 Image: hello-web:1.0 Owner: ReplicaSet/hello-web-1w4zot Labels: app=hello-web
kubectl scale deployment hello-web --replicas=5
Changes the replica count. Press Play, or type wait 10, to see the new pods start.
deployment.apps/hello-web scaled
kubectl set image deployment/hello-web web=hello-web:2.0
Starts a rolling update to the new image. Check progress with the next command.
deployment.apps/hello-web image updated
kubectl rollout status deployment/hello-web
Waits until the rollout is complete. In this command the playground prints the final status.
deployment "hello-web" successfully rolled out
kubectl create configmap app-config --from-literal=MESSAGE=hi
Creates a ConfigMap from a literal value. Pods that read it need it to exist before they start.
configmap/app-config created
kubectl run debug --image=hello-web:1.0
Starts a single pod with no controller. Delete it and nothing brings it back.
Error from server (AlreadyExists): pods "debug" already exists
kubectl logs --tail=3 debug
Shows the last three log lines for the pod. Each line has the simulated second it was written.
[16s] scheduled to node-1 (ip 10.244.1.5) [16s] container "debug" started (image hello-web:1.0) [16s] listening on :8080
kubectl expose deployment hello-web --port=8080 --name=web
Creates a Service called web for the deployment. Then request web sends a request through it.
service/web exposed hello from hello-web-1w4zot-kvzp9 (version 1.0)
kubectl exec writer -- ls /data
Runs a command inside the pod. exec only works on paths that are mounted volumes (here /data), not on the root filesystem.
notes.txt
request ingress web-ingress / --host=hello.local
Sends a request through an Ingress. A host or path with no matching rule gets a 404.
hello from hello-web-pod (version 1.0) 404 Not Found (no ingress rule matches this host and path)
kubectl get endpoints hello-web
Lists the IP and targetPort each Service sends to. An empty list means no ready pods match its selector.
NAME ENDPOINTS hello-web 10.244.2.3:8080,10.244.3.4:8080,10.244.1.2:8080
kubectl get pods -n kube-system
Only the default namespace exists in the playground. Other namespaces report that nothing is there.
No resources found in kube-system namespace.
Goal: see how requests reserve room on a node, and how limits stop a container.
kubectl describe pod resources-pod to see the requests and limits. Then kubectl describe node node-1 shows how much of the node's CPU and memory the requests reserve.Insufficient cpu: each node has 2 CPUs, and the request is 3.cpu: "1" per pod and 4 replicas. Two pods fit on each node, and the rest wait until there is room.describe pod shows Last State: Terminated (OOMKilled).Modelled: Deployments and ReplicaSets, pod scheduling with per-node pod count and CPU and memory requests, readiness and liveness probes, memory limits (OOMKilled), Services with round-robin endpoints and targetPort, ConfigMaps and Secrets as env vars and files, PersistentVolumes with binding, StorageClasses and reclaim policies, DNS, NetworkPolicy, Ingress, rolling updates with maxSurge and maxUnavailable, self-healing, node failure and eviction, and basic kubectl output.
Not modelled: real containers and images, CPU limits and throttling, named ports, cloud load balancers, RBAC, and the exact wording and timing of real Kubernetes.