Kubernetes: Orchestrating Containers at Scale
If you’ve already read about Docker, you know how to package an application into a container. Kubernetes answers the next question: what happens when you have hundreds of containers, across dozens of machines, and one of those machines just died at 3 AM?
What Kubernetes Actually Is
Kubernetes (often shortened to “K8s” — 8 letters between the K and the s) is an open-source container orchestration platform, originally built by Google and now maintained by the Cloud Native Computing Foundation. It takes a set of machines (called a cluster) and treats them as one pool of compute, on which it schedules, runs, heals, and scales your containers automatically.
Docker answers “how do I package and run one container?” Kubernetes answers “how do I run thousands of containers reliably, across many machines, without babysitting them?”
Why Not Just Use Plain Docker?
Docker alone is great for a single host. But production systems need things Docker by itself doesn’t provide:
- Self-healing — if a container crashes or a node dies, something needs to notice and restart work elsewhere.
- Scaling — traffic spikes; you need more replicas of a service, automatically.
- Service discovery & load balancing — containers come and go with new IPs each time; something needs to route traffic to whichever ones are currently alive.
- Rolling updates & rollbacks — deploying a new version without downtime, and reverting cleanly if it breaks.
- Declarative infrastructure — you describe the desired state (“I want 3 replicas of this app”), and the system continuously works to match reality to that description.
Kubernetes provides all of this as a platform, so teams stop hand-rolling scripts around docker run and start describing what they want instead.
Core Concepts
Pods
The smallest deployable unit in Kubernetes is a Pod, not a container. A Pod wraps one or more tightly-coupled containers that share networking and storage. Most of the time, a Pod holds exactly one container — think of it as “a container, plus the Kubernetes metadata around it.”
Deployments
You rarely create Pods directly. Instead, you create a Deployment, which describes:
- which container image to run
- how many replicas (identical Pods) you want
- how updates should be rolled out
The Deployment controller constantly compares what’s running against what you asked for, and reconciles the difference — if a Pod dies, it creates a new one; if you scale from 3 to 10 replicas, it creates 7 more.
Services
Pods are disposable and get new IP addresses whenever they’re recreated. A Service gives a stable name and IP/DNS entry that load-balances traffic across whichever Pods currently match a label selector — so the rest of your system never has to track individual Pod IPs.
Namespaces, ConfigMaps, and Secrets
Beyond the core three, Kubernetes gives you Namespaces (logical isolation within a cluster), ConfigMaps (externalized configuration), and Secrets (sensitive values like API keys) — all so your container image itself stays generic and environment-agnostic.
A Simple Example Manifest
Here’s a minimal Deployment and Service for an nginx web app — the kind of thing you’d apply with kubectl apply -f app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "250m"
memory: "256Mi"
---
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
type: LoadBalancer
selector:
app: web-app
ports:
- port: 80
targetPort: 80
Apply it, and Kubernetes will:
- Schedule 3 Pods running
nginx:1.25across available nodes. - Keep exactly 3 healthy replicas running at all times — restarting or rescheduling any that fail.
- Expose them behind a single stable Service endpoint that load-balances requests across the live Pods.
Change replicas: 3 to replicas: 10 and re-apply, and Kubernetes scales out for you — no new scripts, no manual load balancer reconfiguration.
Where It Fits in a Real Stack
In practice, the flow looks like this: you build an image with Docker (or buildah/podman), push it to a registry, and hand the image reference to a Kubernetes Deployment manifest. From there, Kubernetes handles placement, scaling, health checks, rolling updates, and networking. Logs and metrics from these Pods typically flow into an observability stack — which is exactly what the ELK Stack or Graylog posts in this series cover. And increasingly, Kubernetes is also the substrate for AI/ML infrastructure, scheduling GPU-backed training and inference workloads the same way it schedules ordinary web apps.
Kubernetes has a learning curve, and it’s overkill for a single hobby app on one server. But once you’re running more than a handful of services that need to stay up, scale, and deploy safely, it earns its complexity fast — which is why it’s the de facto standard for running containers in production today.