The problem Docker Compose doesn't solve
Docker Compose is excellent for running a multi-container app on a single machine. But what happens when that one machine's CPU hits 100%? Or when you need to run 10 replicas of your API across 5 servers? Or when a container crashes at 3am and needs to be automatically restarted on a healthy node? Compose has no answer. Kubernetes does.
Kubernetes (K8s) is a container orchestrator: it schedules containers across a cluster of machines, self-heals crashed pods, rolls out updates without downtime, and scales workloads up or down based on CPU/memory demand. Every major cloud provider (AWS EKS, GCP GKE, Azure AKS) offers managed K8s — it's the industry standard for running containerised production workloads at scale.
🎯 Practice Questions
Show Answer
docker compose up -d --no-deps app causes a brief window where the old container is stopped before the new one is ready — at 10× traffic, this is noticeable.The K8s building blocks
Everything in Kubernetes is declared in YAML manifests. The three objects you'll use constantly: Pod — the smallest deployable unit, wraps one or more containers; Deployment — manages a set of identical Pods, handles rolling updates and rollbacks; Service — gives Pods a stable DNS name and IP so other services can reach them even as Pods are replaced.
You almost never create a bare Pod. You create a Deployment (which creates a ReplicaSet, which creates Pods). Then you expose it via a Service.
🎯 Practice Questions
Show Answer
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-api
spec:
replicas: 2
selector:
matchLabels:
app: flask-api
template:
metadata:
labels:
app: flask-api
spec:
containers:
- name: flask
image: your-ecr-url/flask-app:latest
ports:
- containerPort: 5000
resources:
requests: { cpu: "100m", memory: "64Mi" }
limits: { cpu: "200m", memory: "128Mi" }kubectl apply and kubectl create? Which should you use in a CI/CD pipeline and why?kubectl rollout undo deployment/capstone-api after a bad deploy. What does K8s actually do under the hood — which object does it modify?Configuration management in K8s
ConfigMaps store non-sensitive configuration: environment variables, config files, feature flags. Secrets store sensitive data: passwords, API keys, TLS certificates — stored base64-encoded in etcd (and encrypted at rest if the cluster is configured correctly). Both are injected into Pods as environment variables or mounted as files.
Important caveat: base64 is not encryption. Kubernetes Secrets require proper RBAC + encryption at rest + external secret management (AWS Secrets Manager via External Secrets Operator) for production. For learning purposes, Secrets + RBAC is the standard starting point.
kubectl create secret imperatively.🎯 Practice Questions
my-db-password in base64 using the terminal. Then decode it back. Explain why this demonstrates that Kubernetes Secrets are NOT encrypted by default.Show Answer
$ echo -n "my-db-password" | base64
bXktZGItcGFzc3dvcmQ=
$ echo "bXktZGItcGFzc3dvcmQ=" | base64 -d
my-db-passwordThis shows that base64 is reversible encoding, not encryption. Anyone with access to the Secret object in etcd (or via
kubectl get secret -o yaml) can decode the value in one command. Encryption at rest + strict RBAC on the secrets resource is required for production.envFrom: secretRef and env: valueFrom: secretKeyRef? When would you use each?Your K8s toolbelt
kubectl is the CLI for all Kubernetes interactions — the equivalent of docker but for clusters. You'll use a core set of commands for 90% of day-to-day work: get, describe, logs, exec, apply, delete, scale, rollout. The rest you look up when needed.
kubectl describe pod X shows Events — which is where 90% of "why is my pod not starting" answers live.-l app=name — much better than picking one pod by name.🎯 Practice Questions
CrashLoopBackOff. List the exact kubectl commands you'd run (in order) to diagnose why it's crashing.Show Answer
kubectl get pods — confirm status and how many restarts2.
kubectl describe pod <pod-name> — check Events section for OOMKilled, image pull errors, liveness probe failures3.
kubectl logs <pod-name> — see the last stdout/stderr before crash4.
kubectl logs <pod-name> --previous — logs from the previous (crashed) container instance5. If you can't tell from logs:
kubectl exec -it <pod-name> -- sh to inspect the container environment (may not work if it's crashing too fast)kubectl get pods -o wide show that kubectl get pods doesn't? Give a real debugging scenario where the extra columns matter.kubectl port-forward to access the Prometheus metrics endpoint of your capstone app running inside minikube. Write the exact command and explain the port numbers.Local cluster options
minikube is the most popular tool for running a single-node K8s cluster locally — it starts a VM (or Docker container) with a full K8s control plane. kind (Kubernetes in Docker) runs K8s nodes as Docker containers — faster startup, great for CI testing, supports multi-node clusters on one machine. Both give you a real kubectl experience without any cloud cost.
minikube image load or kind load docker-image to avoid needing ECR for local testing.minikube addons enable ingress adds NGINX Ingress; metrics-server enables HPA — real cluster features locally.🎯 Practice Questions
metrics-server addon in minikube (minikube addons enable metrics-server). Then run kubectl top pods. What does this output show and how is it related to the HPA (Horizontal Pod Autoscaler)?imagePullPolicy: Never in your Deployment YAML when testing locally with minikube vs. using the default policy? When does this matter?Project overview
Take the Docker Compose stack from your capstone project and re-deploy it to a local minikube cluster using Kubernetes manifests. This is the same mental shift that happens in industry when teams move from Compose-based dev to a production K8s cluster — the containers don't change, the orchestration layer does.
capstone namespace — keeps your work separate from kube-system and easy to delete cleanly.📋 Project Deliverables
- A
k8s/directory in your capstone repo containing: namespace.yaml, configmap.yaml, api-deployment.yaml (2 replicas, resource limits), api-service.yaml (NodePort for minikube access) - Screenshot of
kubectl get all -n capstonewith all Pods in Running state - Demonstrate a rolling update: change the image tag, run
kubectl rollout status, and show the app still responding during the rollout (usecurlin a loop) - Demonstrate a rollback:
kubectl rollout undoand confirm the previous version is serving traffic - Update your capstone README with a "Kubernetes deployment" section documenting the commands to spin up the K8s stack from scratch
🎯 Practice Questions
Show Answer
postgres-0, postgres-1 instead of random hashes — so the app can connect to a known hostname. (2) Ordered startup/shutdown — pod-0 starts before pod-1 (important for primary/replica replication). (3) Stable persistent storage — each pod gets its own PersistentVolumeClaim that survives pod rescheduling. A Deployment would give a new random PVC on every reschedule, losing all data.curl http://$(minikube ip):<nodePort>/health in a loop while triggering a rolling update. Observe whether any requests fail. What would you add to your Deployment to prevent failures during rollout?