Kubernetes and What It Actually Replaces
If you're running a few containers on one server, Docker Compose handles it fine. You define your services in a YAML file, run docker compose up, and everything starts. For a side project or small product, this is the right tool.
Things get harder once you need more than one server. You have to decide which containers go where, set up health checks, and figure out how to push updates without dropping traffic. Most teams write scripts for this: a deploy script, a recovery script, a cron job to check if things are still running. By the time you're running 40 or 50 containers, maintaining those scripts starts to feel like its own full-time job.
There are good options short of Kubernetes. Heroku, Render, and Railway handle infrastructure for you: push code and it runs. The downside is cost at scale and limited configurability once you're past a dozen services. Cloud-specific container services like ECS or Cloud Run are a middle ground: they handle scheduling and scaling, but your configs and tooling only work on that one provider.
Kubernetes does something different. You write a manifest describing what you want running, and it continuously works to make reality match that description. "Run three copies of this container, each with 512MB of memory, reachable at this internal address." Kubernetes picks the machines, starts the containers, and monitors them. If one dies because its host ran out of memory, it finds a healthy machine and starts a replacement without any human involvement.
It does this through a reconciliation loop. A controller process constantly compares what you declared (three replicas) to what exists (two, because one crashed), and takes action to close the gap. The same loop handles scaling: change the manifest to five replicas and the controller creates two more.
The system is organized around a few abstractions. A Pod is the smallest unit you deploy, usually one container. A Deployment manages a set of identical pods and rolls out new versions by replacing them one at a time so traffic keeps flowing. A Service gives pods a stable network address, which matters because pods get a new IP every time they restart.
What makes Kubernetes hard to replace is the ecosystem built on top of it. Helm for package management, Argo CD for GitOps, Prometheus for monitoring, Istio for service mesh. If you adopt Kubernetes, all of these are available. If you use ECS or Cloud Run, you either find provider-specific equivalents or build something yourself.
Kubernetes is overkill for a lot of projects. If you're running five containers on one cloud provider, ECS or a managed platform will serve you better. It starts to make sense when the cost of running the platform is lower than the cost of handling all the failure modes, deploys, and scaling events by hand.