Chapter 1
From Containers to Kubernetes — Why Orchestration Exists
Before you read, guessWhy does manual container management fail to support reliable, scalable services?
Take ten seconds and guess — even a wrong guess makes the answer stick. Tap to see where the chapter lands, or just read on.
Running containers by hand breaks down fast: crashed hosts don't self-heal, scaling is manual, zero-downtime deploys are error-prone, and services can't reliably find each other.
Imagine an airport with one runway and one person on the tarmac, waving flags to guide a single plane in and out. That works fine for a tiny airstrip. Now picture Heathrow: hundreds of planes, dozens of gates, constant delays and reroutes. You can't run that with one person and two flags. You need a control tower watching everything at once, all the time, and adjusting as things change. That's the exact same leap we're making in this post — from running one container by hand to running a whole fleet of them with Kubernetes.
Quick recap: what even is a container?
You've used Docker before, so this is a refresher, not a first introduction. A container is not a tiny virtual machine. It doesn't boot its own kernel (the core part of an operating system that talks to the hardware) and it doesn't emulate hardware. A container is just a normal process running directly on your Linux host — the same kind of process as anything else on the machine — except it's fenced in by two Linux kernel features. Namespaces give it its own private view of the filesystem, network, and process list, so it can't see anything outside its box. Cgroups (control groups) cap how much CPU and memory it's allowed to grab. Docker's image format then bundles that process together with every library and file it needs, so it runs the same way on your laptop, your coworker's laptop, and a server in a data center.
So a container is really two ideas stacked together. Isolation: this process can't see or touch anything outside its box. Packaging: everything it needs travels with it, in one image. No magic, no hidden operating system — just a regular process, fenced in and shipped with its dependencies.
Running containers by hand works... until it doesn't
With one app on one server, docker run is all you need. The trouble starts the moment things get messy, which happens almost immediately at any real company. Say the server running your container crashes at 3am. Nothing brings it back on its own. You're the one whose pager goes off, SSHing in half asleep to restart it by hand.
Or traffic spikes and one container can't keep up anymore. You need five more copies, spread across several machines so you're not betting everything on one box. By hand, that means picking servers, copying the image to each one, starting each container, and wiring up a load balancer yourself — then doing the whole thing again the next time traffic shifts.
Then there's deployment. Shipping a new version without downtime means: start the new containers, wait until each one is healthy, only then send traffic to them, and only then kill the old ones — with a rollback plan ready in case the new version is broken. Skip a step by hand and you get an outage and an angry Slack channel.
And there's service discovery: how does one part of your app find another? Say your checkout service needs to reach your inventory service, but inventory runs on three different hosts, on ports that change every time it restarts. Hardcoded IP addresses go stale within hours, and nobody keeps a spreadsheet of them accurate for long.
None of this is exotic. It's just what happens the moment you have more than a handful of containers and more than one server. The root cause is always the same: humans are slow and make mistakes, while servers fail and traffic shifts at machine speed.
Enter Kubernetes: a system that never stops watching
Kubernetes' answer to all of this comes down to one idea. Slow down for this one, because literally every other post in this series builds on it.
Desired state is simply this: what you WANT to be true. "I want 5 copies of this container running." That's it — that's a desired state. You write it down and hand it to Kubernetes, not as a set of steps, but as a target.
Actual state is what IS true right now, this second, for real. Maybe only 3 copies are actually running, because a server crashed and took 2 of them down with it.
Kubernetes' entire job, all day, every single day, is comparing these two things — desired state vs. actual state — and the moment they don't match, doing something about it until they do match again. Concretely: you said 5, only 3 are running, so Kubernetes notices the gap and starts 2 more, automatically, on whatever servers have room. Now actual state is 5. Gap closed. This is called the reconciliation loop: look at what's actually running, compare it to what you asked for, act to close any gap, then check again. That loop never stops. It runs constantly, in the background, forever, whether you're watching or not.
That one idea — watch what's actually happening, compare it to what you asked for, fix the gap — explains almost everything Kubernetes does automatically. A server dies and takes 2 of your 5 containers with it? The loop sees "3 running" against a desired "5" and starts 2 more elsewhere. You change the desired image version? The loop sees the mismatch and gradually swaps old containers for new ones. You never hand Kubernetes a script of steps — you just change what you want, and the loop keeps chasing that target until reality matches it. You'll see this exact same loop again and again throughout this series, just pointed at different things: Pods, Deployments, and almost everything else Kubernetes manages.
Wasn't there competition?
Kubernetes wasn't the only orchestrator (a system that automatically manages where and how containers run) built to solve this problem. Docker Swarm offered a simpler, Docker-native approach, and HashiCorp Nomad a lighter, general-purpose scheduler. Both still exist, but the industry has overwhelmingly standardized on Kubernetes: it's what most companies run, what job postings ask for, and what the CKA exam tests. So that's our focus for the rest of this series.
Let's get hands-on: your own local cluster
Reading about orchestration only gets you so far — you need a cluster (a group of machines working together as one Kubernetes system) to poke at. The easiest way to get one on your own laptop is minikube, a tool that spins up a small, real Kubernetes cluster inside a VM or container on your machine, purely for learning and testing.
Install minikube and kubectl (the command-line tool you use to talk to any Kubernetes cluster, pronounced "kube-control" or "kube-cuttle") through your OS's package manager — for example brew install minikube kubectl on macOS. Then start your first cluster with one command:
$ minikube start
minikube v1.33.0 on Darwin
Using the docker driver
Starting control plane node minikube in cluster minikube
Pulling base image ...
Done! kubectl is now configured to use "minikube" cluster
That command downloads a small VM or container image, boots a single-node Kubernetes cluster inside it, and points kubectl at it automatically. Give it a minute or two the first time — it's pulling images.
Now let's confirm everything's talking correctly.
$ kubectl version --client
Client Version: v1.30.0
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
That just proves kubectl itself is installed and working. Next, check that it can actually reach your new cluster:
$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:XXXXX
CoreDNS is running at https://127.0.0.1:XXXXX/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
And finally, ask the cluster what machines (called nodes in Kubernetes) it has to work with:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 2m v1.30.0
That single line is your entire cluster right now: one node, acting as control plane, reporting itself Ready. It's small, but it's a real, working Kubernetes cluster, running the same core software as clusters with thousands of nodes at large companies. Everything in this series, you can practice right here.
minikube start, then run the three kubectl commands above. If kubectl get nodes shows Ready, you're set up for the rest of this series. If something fails, run minikube status first.Key Takeaways
- A container is an isolated, packaged process, not a lightweight VM. It uses namespaces (private view of filesystem/network) and cgroups (CPU/memory limits), not its own kernel.
- Running containers by hand breaks down fast: crashed hosts don't self-heal, scaling is manual, zero-downtime deploys are error-prone, and services can't reliably find each other.
- Desired state = what you want to be true. Actual state = what's really true right now. The reconciliation loop constantly compares the two and closes any gap — that loop is the core of everything Kubernetes does.
- Think of Kubernetes as an airport control tower: the flight plan is desired state, the radar is actual state, and the tower's nonstop comparing-and-correcting is the reconciliation loop.
- Docker Swarm and Nomad exist, but Kubernetes is the industry standard — and the focus of this series and the CKA exam.
- minikube gives you a real local cluster in minutes: install it, run
minikube start, and confirm withkubectl get nodes.