Kubernetes
Run many containers across many machines by describing the state you want and letting the system chase it.
Fast answer: Kubernetes (K8s) runs and manages containerized applications across many machines. Docker packages your application into a portable container; Kubernetes manages fleets of those containers: deciding where they run, restarting them when they fail, scaling them up and down, and keeping them reachable. You describe the state you want; Kubernetes works continuously to make reality match.
Why Kubernetes exists
Imagine you run an online store. At the start life is simple:
1 server · 1 application · 100 users
Then the business grows: millions of users, multiple servers, several services, deployments every week. Questions start arriving faster than you can answer them by hand:
- Which server should run this container?
- What happens when a server dies at 3am?
- How do we update without downtime?
- How do we add instances during a traffic spike and remove them after?
Kubernetes is the system that answers these automatically. Keep the scale of that origin story in mind; it returns in Lesson 6 as the reason most projects should not start here.
The building blocks, smallest first
Container. Exactly the unit from Lesson 1: your Python app plus its runtime and dependencies, packaged to run anywhere.
Pod. The smallest thing Kubernetes deploys. A pod wraps one or more containers; usually one:
Pod ┌──────────────────┐ │ API container │ └──────────────────┘
Occasionally a pod carries a helper container alongside the main one (a log shipper, for instance), which is why the wrapper exists at all.
Node. A machine: physical server, VM, or cloud instance. Pods run on nodes.
Cluster. The collection of nodes that Kubernetes manages as one pool.
Cluster ├── Node 1 ── Pod Pod Pod ├── Node 2 ── Pod Pod └── Node 3 ── Pod Pod Pod Pod
Two parts run the show: the control plane (the brain: an API server, a scheduler deciding where pods go, and a database called etcd holding the cluster's state) and the worker nodes, which actually run your pods.
The central idea: desired state
This is the mental shift that makes everything else click. With Docker you issue commands: run this container. With Kubernetes you declare an outcome:
"I want 3 instances of my API running."
Desired: 3 Reality: 3 ✓ nothing to do
...a pod crashes...
Desired: 3 Reality: 2 ✗ start one
Desired: 3 Reality: 3 ✓
Kubernetes controllers compare desired state with observed state, continuously, and act to close any gap. That loop is called reconciliation, and it is the single most important idea in Kubernetes. Self-healing is not a feature bolted on top; it is what the loop does all day.
Deployments: how you ask for pods
You almost never create pods directly. You create a Deployment that describes what you want, and Kubernetes maintains it:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: api
image: myorg/myapp:1.4
kubectl apply -f deployment.yaml
Read the YAML as a sentence: keep three replicas of the container built from myorg/myapp:1.4 running, labelled app: web. Notice the image reference: the nodes pull that exact image from the registry you met in Lesson 3. The whole release pipeline plugs in here.
Scaling is a change of one number, by hand or automatically:
kubectl scale deployment web --replicas=30
Updates are the reconciliation loop again: change the image to :1.5 and Kubernetes performs a rolling update, replacing pods a few at a time so users see little or no downtime:
v1 v1 v1 → v2 v1 v1 → v2 v2 v1 → v2 v2 v2 kubectl rollout undo # and back again if it goes wrong
Services: a stable address for unstable pods
Pods are temporary. When one dies and is replaced, the replacement has a different IP. Anything pointed at the old IP is now broken. A Service gives a changing set of pods one stable name and load-balances across them:
Users
│
▼
API Service stable name: api
┌──────┼──────┐
▼ ▼ ▼
Pod Pod Pod (IPs come and go underneath)
The Service finds its pods by their labels (app: web in the YAML above), not by their addresses. If that principle sounds familiar, it should: it is the find-each-other-by-name rule from Lesson 2, operating at cluster scale.
The remaining Kubernetes vocabulary
The remaining nouns you will meet all map onto ideas this course has already covered:
| Kubernetes term | What it is | You already know it as |
|---|---|---|
| ConfigMap | Configuration delivered to pods at runtime | Environment variables, Lesson 1 |
| Secret | Sensitive values delivered at runtime, access-controlled | Secrets never in images, Lesson 4 |
| Volume / PersistentVolume | Storage that outlives pods | Docker volumes, Lesson 1 |
| Ingress | Routes outside traffic to Services, terminates HTTPS | The public listener in front of an internal port |
| Namespace | Walls between environments in one cluster | dev / staging / production separation |
And the day-to-day commands are few:
kubectl get pods
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl exec -it <pod-name> -- bash
One request, top to bottom
A user opens https://shop.com:
User → Ingress → Service → Pod → Container → your Python code
If a pod fails, reconciliation replaces it. If traffic grows, replicas increase. If you ship version 2, the rolling update swaps pods gradually. Every mechanism in this lesson is visible in that one request path.
A mental model to keep
| Real world | Kubernetes |
|---|---|
| City | Cluster |
| Building | Node |
| Apartment | Pod |
| Resident | Container |
| Building manager | Scheduler |
| Reception desk | Service |
| Street address | Ingress |
| Building blueprint | Deployment |
If you want to feel the reconciliation loop rather than read about it, install a local cluster (Minikube or Kind), deploy the YAML above, then kubectl delete pod one of your pods and watch Kubernetes calmly replace it. That single moment teaches more than any diagram.
Try it: predict the controller
A Deployment says replicas: 3. Write down what you expect after each event: one pod crashes; you manually delete another pod; you change the image tag; traffic doubles but no autoscaler exists.
Model: Kubernetes replaces each missing pod because observed state fell below three. Changing the image starts a rolling replacement. Traffic alone changes nothing unless you configured an autoscaler; the system only chases desired state you actually declared.
If the Kubernetes nouns still feel like a pile
Keep one sentence: a Deployment asks a cluster to keep some pods running, and a Service gives those changing pods a stable address. Nodes are merely the machines underneath. Most of the remaining vocabulary adds configuration, storage, or outside traffic to that sentence.
Check your understanding
Answer before opening each explanation.
Put container, pod, node, and cluster in order and give each a job.
Hint: Start with the running application and work outward.
Answer: A container runs the packaged application. A pod wraps one or more closely related containers. A node is a machine that runs pods. A cluster is the pool of nodes Kubernetes manages.
A pod crashes but the API remains available. Which loop did the work?
Hint: Desired versus observed.
Answer: The reconciliation loop noticed that observed replicas had fallen below the Deployment's desired count and created a replacement. Other healthy replicas continued receiving traffic through the Service.
Why do applications use a Service instead of a pod IP?
Hint: Pods are disposable.
Answer: Replacement pods receive new IPs. A Service keeps one stable name and routes to the currently matching pods. It is the same "find services by name, not changing IP" principle introduced with Docker networking in Lesson 2.
What makes kubectl rollout undo safer than rebuilding latest?
Hint: A rollback needs an identifiable previous artifact.
Answer: The rollout history refers to versioned images that already exist. Undo can restore a known prior revision; rebuilding a movable latest tag creates new bytes and does not guarantee the previous release.