Why Kubernetes
Why Kubernetes
TL;DR
- Docker solves packaging (“works on my machine”); Kubernetes solves cluster orchestration across dozens of machines
- Raw containers lack scheduling logic, self-healing on node failure, rolling updates, and cross-node service discovery
- Declarative model defines desired state (3 replicas, 256MB RAM); Kubernetes reconciles reality to match
- Control loop reads desired state from etcd, observes actual state, identifies drift, and acts to reconcile
- Node controller detects kubelet heartbeat loss and reschedules pods to healthy nodes
- Kubernetes NOT needed for simple apps, strict microsecond latency, or tiny teams without DevOps expertise
Core Concepts
The Raw Docker Problem
Raw Docker/Compose on multiple servers creates operational chaos:
- Scheduling: Which server has CPU/memory capacity for a new container?
- Self-healing: When Server 2 crashes, who detects failure and reschedules 50 containers to Server 1?
- Service discovery: Container IPs change on restart; how do other containers find them?
- Rolling updates: How to deploy new code without downtime?
- Secrets & config: How to distribute API keys and TLS certs across hundreds of machines securely?
Kubernetes as Cluster OS
Kubernetes is an open-source orchestration engine (Google’s Borg inspired). It acts as a distributed operating system automating deployment, scaling, and management across a cluster.
Declarative vs. Imperative
- Imperative (Docker): “Run this container, map port 8080, limit to 256MB RAM.” (Tell system HOW.)
- Declarative (Kubernetes): “I want 3 frontend replicas with 256MB RAM on port 80.” (Define DESIRED STATE; K8s achieves it.)
Control Loop (Reconciliation)
Kubernetes controllers continuously run:
- Read desired state from etcd
- Observe actual cluster state (pods, nodes, IPs)
- Analyze differences (desired vs. actual)
- If mismatch exists → reconcile (take action); else → do nothing
- Loop continuously
Comparison Table
| Capability | Raw Docker/Compose | Kubernetes |
|---|---|---|
| Cluster awareness | Single-host or Swarm (limited) | Control plane manages 1000s of machines |
| Self-healing | Restart on local host only | Reschedule pods to healthy nodes on failure |
| Scaling | Manual (docker compose up --scale) |
Automatic HPA based on CPU/RAM/custom metrics |
| Rolling updates | Requires scripting/external proxies | Native zero-downtime rolling upgrades |
| Storage | Local directories or manual plugins | Auto-mount EBS, NFS, Ceph, etc. |
| Service discovery | Manual IP lists or external DNS | Built-in CoreDNS with stable Services |
Core Concepts Dive
Scheduling Problem
Kubernetes scheduler places pods on nodes with sufficient CPU, memory, and matching tolerations/affinities. Raw Docker requires manual selection or simple bin-packing scripts.
Self-Healing Pipeline
When node loses power:
- kubelet stops sending heartbeats → API Server loses contact
- node-controller detects missing heartbeat
- After grace period (default 5 min), node-controller marks pods
Terminating - Scheduler places replacement pods on healthy nodes
- Result: Application stays running despite hardware failure
Declarative Reconciliation
Controllers read desired state (Deployment manifest: “3 nginx replicas”), query reality (“1 running, 1 pending, 1 failed”), compute delta, and act. This continuous loop means temporary outages self-correct without manual intervention.
Interview Questions
Q — Walk through what happens when a node loses power. How does Kubernetes know to reschedule?
kubelet on the failed node stops sending periodic heartbeats to the API Server. The node-controller inside the Controller Manager detects missing heartbeats. After a grace period (default 5 minutes, configurable via node-monitor-grace-period), the node-controller marks all pods on that node as Terminating. The scheduler then places replacement pods on the remaining healthy nodes. Network traffic reroutes through updated Service endpoints.
Q — Explain the declarative model and how it differs from Docker’s imperative approach. Declarative: Author writes a manifest defining desired state (“3 replicas, 256MB RAM, port 80”) and Kubernetes continuously ensures reality matches. Imperative: Author issues direct commands (“run container, expose port”) and Kubernetes takes a one-time action. Declarative enables GitOps, auditing, and self-healing; imperative is faster for one-off operations but not production-grade.
Q — When is Kubernetes NOT the right architectural choice? Overkill for simple, low-scale applications—a single VM with systemd or a PaaS (AWS App Runner, Cloud Run) is simpler. Unsuitable for strict microsecond-latency requirements because CNI and overlay networks (VXLAN) add a few milliseconds. Risky for small teams without dedicated DevOps engineers; Kubernetes complexity requires specialized knowledge and operational burden.
Common Pitfalls
Pitfall: Hardcoding Pod IP Addresses Directly using pod IPs for inter-service communication (“http://10.244.1.5:8080”) in code or configs.
- Why: Pods are ephemeral and recreate frequently, changing IPs; hardcoded IPs become stale immediately.
- Fix: Use Kubernetes Services with stable DNS names (e.g., “http://backend-service:8080”). CoreDNS resolves service names to current pod IPs automatically.
Pitfall: Expecting High Availability Without Controllers Deploying bare Pod resources and expecting self-healing on node failure.
- Why: Bare pods are not managed by Deployments or StatefulSets; if node crashes, pod is gone forever.
- Fix: Always wrap pods in a controller (Deployment, StatefulSet, DaemonSet) for automatic rescheduling and self-healing.