A minimalistic guide to learning Kubernetes. Follow these steps sequentially to move from zero to cluster operator.
Running a cluster requires docker, kubectl, and kind. Use the local setup script to audit your machine.
# Run the local setup script
chmod +x ./setup_k8s.sh
./setup_k8s.sh
Once finished, verify your installation with: kind version and kubectl version --client.
Kubernetes is a reconciliation loop. You declare what you want (Desired State), and Kubernetes works to make it happen (Actual State).
These are the building blocks you will use 90% of the time.
| Resource | Purpose |
|---|---|
Pod | The smallest unit; one or more containers. |
Deployment | Manages Pods (scaling, rolling updates). |
Service | A stable IP/DNS name to reach your Pods. |
Namespace | A logical boundary to isolate projects. |
ConfigMap | Injects configuration into your app. |
Work through these drills on your local machine to build muscle memory.
Create a cluster and run your first application.
kind create cluster --name lab
kubectl create deployment web --image=nginx:alpine
kubectl expose deployment web --port=80 --type=ClusterIP
kubectl port-forward svc/web 8080:80
Result: Visit localhost:8080 in your browser to see Nginx.
Watch Kubernetes maintain your desired state.
kubectl scale deployment web --replicas=3
kubectl get pods
# Kill a pod and watch it restart:
kubectl delete pod [pod-name]
kubectl get pods -w
Update your application version safely.
kubectl set image deployment web nginx=nginx:1.27
kubectl rollout status deployment web
# Undo a mistake:
kubectl rollout undo deployment web
When things break, follow the standard flow: Get → Describe → Logs → Exec.
App starts then fails. Check kubectl logs [pod] for app-level errors or probe failures.
Incorrect tag or private registry auth issue. Run kubectl describe pod to see pull events.
No resources available or taints/selectors mismatch. Check describe pod events for scheduling errors.
Container exceeded its memory limit. Review resources.limits vs actual app usage.
Verify label selectors: kubectl get endpoints should list Pod IPs. No endpoints = no traffic.
Debug from inside: kubectl exec -it [pod] -- nslookup my-service. Checks CoreDNS health.
404: Path/Host mismatch. 503: Backend Service or Pods are unhealthy. Check Ingress controller logs.
No matching StorageClass or provisioner is down. Run kubectl describe pvc [name].
Volume is already used by another node (RWO) or path doesn't exist. Check node logs / events.
Node is out of disk or memory. K8s will evict low-priority Pods. kubectl get nodes shows status.
ServiceAccount lacks permissions. Debug with kubectl auth can-i [verb] [resource].
Pods stuck in Terminating. Force delete with --grace-period=0 --force (use with caution).
Missing resource requests or Metrics Server not installed. Run kubectl get hpa to see status.
Namespace limits hit. New Pods will be denied by the API. Check kubectl get quota.
| Command | Impact | What it does |
|---|---|---|
kind create cluster |
Local | Creates a local cluster. |
kubectl get pods |
Control | Lists all pods in the current namespace. |
kubectl get nodes |
Control | Shows cluster health and node status. |
kubectl describe pod [name] |
Control | Deep dive into pod events and status. |
kubectl logs [name] |
Data | Streams container logs. |
kubectl exec -it [name] -- sh |
Data | Opens a shell inside a container. |
kubectl apply -f [file.yaml] |
Control | Apply a configuration file. |
kubectl delete -f [file.yaml] |
Control | Remove resources defined in a file. |