Kubernetes (K8s) is an open-source platform designed to automate the deployment, scaling, and management of containerized applications. Originally developed by Google based on its internal Borg system, K8s has become the de facto standard for production-grade container orchestration in modern cloud-native environments.
At its core, Kubernetes doesn't invent new technologies—it orchestrates existing Linux primitives: namespaces for isolation, cgroups for resource control, and root filesystems (rootfs) for image packaging. These are the same mechanisms Docker uses under the hood, but K8s elevates them into a coordinated, declarative system.
Containers: Beyond Docker Commands
Running a container via docker run nginx may seem simple, but behind the scenes, Docker invokes Linux system calls like clone() with namespace flags (CLONE_NEWNET, CLONE_NEWPID, etc.) to isolate process views, network interfaces, and filesystem mounts. The container isn’t a virtual machine—it’s a process with restricted visibility.
Container images bundle application binaries, libraries, and configuration into a read-only layer (rootfs), which is mounted at runtime. Crucially, all containers on a host share the same kernel—no hypervisor is involved. This makes containers lightweight and fast, but also means they rely entirely on the host OS for core functionality.
While containers solve the "it works on my machine" problem, running one container isn’t enough for production. What happens when it crashes? How do you scale it across nodes? How do you update it without downtime? These are orchestration problems.
Orchestration: Coordinating Distributed Components
Modern applications are never single-process systems. A web service typically requires a frontend (Nginx), a cache (Redis), a database (PostgreSQL), and background workers—all neeeding to be deployed, monitored, scaled, and recovered together.
Before Kubernetes, teams relied on custom scripts, configuration management tools (Ansible, Chef), or legacy PaaS platforms. These solutions were brittle: scaling meant manual intervention, health checks were rudimentary, and recovery was reactive.
Kubernetes introduces a shift: from imperative scripting to declarative configuration. Instead of writing "run this script to start 3 Nginx instances," you declare: "I want 3 replicas of this container, always running." The system then works to make reality match that intent.
The Pod: Kubernetes’ Atomic Unit
Kubernetes’ smallest deployable unit is the Pod. A Pod is not a container—it’s a group of one or more containers that share:
A network namespace (shared IP and ports) A storage volume (shared filesystem) Life cycle (all containers start and stop together)
Each Pod includes a special pause (or infra) container. This container holds the network and IPC namespaces. Other containers in the Pod join this namespace using setns() system calls, effectively sharing the same network stack and hostname.
Why not just run multiple containers in one process? Because containers are designed to be single-responsibility units. The Pod pattern allows tightly coupled components—like a web server and its log shipper—to be managed as one logical entity, while preserving container isolation and reusability.
Declarative Control: Deployments and the Reconciliation Loop
Kubernetes doesn’t just manage containers—it manages intent. A Deployment object declares the desired state:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
This YAML doesn’t tell Kubernetes how to deploy—it says what to achieve: "Ensure three instances of nginx:1.25 are running."
The kube-controller-manager continuously monitors the actual state of the cluster (via kubelet heartbeats, API server data, and metrics) and compares it to the desired state. If a Pod crashes, the controller spawns a new one. If you scale from 3 to 5 replicas, it creates two more. This is the reconciliation loop—the heart of Kubernetes automation.
Controllers are modular and composable. There are controllers for:
ReplicaSets (ensuring Pod count) DaemonSets (one Pod per node) StatefulSets (stateful applications with stable identities) HorizontalPodAutoscalers (scale based on CPU/memory)
Each observes its own set of resources and acts independent, forming a distributed control plane.
Services and the Network Abstraction
Pods are ephemeral. They get created, destroyed, and rescheduled. Their IPs change. So how do other services find them?
Kubernetes introduces the Service object, which provides a stable network endpoint. A Service selects Pods using labels and exposes them via a virtual IP and DNS name. Traffic is load-balanced across matching Pods using iptables or IPVS rules managed by kube-proxy.
Example:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
This Service makes all nginx Pods accessible at nginx-service.default.svc.cluster.local:80, regardless of where they run.
State and Storage: Beyond Stateless Apps
Not all applications are stateless. Databases, message queues, and caches need persistent storage. Kubernetes handles this via Volume and PersistentVolume objects, which abstract storage from the underlying infrastructure (local disk, NFS, cloud volumes).
For stateful applications with ordered deployment and stable identities (like etcd or Kafka), StatefulSet ensures:
Persistent storage tied to each Pod Ordered creation and termination Stable network identifiers (e.g., web-0, web-1)
The Architecture: Control Plane and Nodes
Kubernetes clusters consist of:
Control Plane: Components that make global decisions (scheduler, controller manager, API server, etcd) Nodes: Worker machines running Pods via kubelet and container runtime (containerd, CRI-O)
The API server is the single source of truth. All components communicate through it. etcd stores cluster state as key-value pairs. The scheduler assigns Pods to nodes based on resource availability and constraints. kubelet ensures the local state matches the desired state declared in the API.
There are no "master" or "slave" nodes in modern K8s—only control plane and worker nodes, with high availability achieved by running multiple control plane instances.
Why Kubernetes Wins
Kubernetes doesn’t replace Docker—it replaces the glue code. It removes the need for custom scripts, manual scaling, and brittle health checks. By abstracting infrastructure into declarative resources (Pods, Deployments, Services, ConfigMaps, Secrets), it enables:
Consistent deployment across environments Self-healing through automatic restarts Scalability via policy-driven replication Rollouts and rollbacks without downtime Resource efficiency through co-location and scheduling
It turns infrastructure management from a task into a declarative contract—written in YAML, enforced by code, and resilient by design.