Kubernetes Under the Hood: How It Actually Works When You Deploy
"A battle-tested, zero-fluff engineering guide on Kubernetes internals control plane API state machines, etcd Raft consensus, kubelet CRI/gRPC calls, and Linux cgroups, namespaces & CNI/eBPF networking."
If you ask most developers what Kubernetes is, theyβll tell you itβs a tool that runs containers across a cluster using kubectl apply -f deployment.yaml.
Thatβs fine for high-level usage. But as a Senior DevOps / Infrastructure Engineer, when a production cluster experiences subtle IPVS connection drops, etcd disk commit stalls during high churn, or Pods getting stuck in ContainerCreating state, abstract definitions fall apart.
In this deep dive, weβre skipping generic marketing summaries. We will dissect the Kubernetes architecture layer by layer, tracing exact Linux primitives, gRPC calls, control loops, and kernel networking hooks under the hood.
1. High-Level Cluster Architecture
A Kubernetes cluster is fundamentally a distributed state machine designed to continuously reconcile observed cluster state with declared desired state.
+-----------------------------------------------------------------------------------+
| CONTROL PLANE (MASTER NODE) |
| |
| +--------------------+ +--------------------+ +-------------------+ |
| | kube-apiserver | <---> | etcd | <---> | kube-scheduler | |
| +--------------------+ +--------------------+ +-------------------+ |
| ^ | |
| | v |
| +-------------------------------------------+-----------------------+ |
| | kube-controller-manager| |
| +-----------------------+ |
+-----------------------------------------------------------------------------------+
|
TLS HTTP/2 (Protobuf / JSON Watch Streams)
|
v
+-----------------------------------------------------------------------------------+
| WORKER NODE |
| |
| +-----------------------+ +------------------------+ +----------------+ |
| | kubelet | | kube-proxy | | containerd | |
| | (CRI / gRPC Listener) | | (iptables/IPVS/eBPF) | | (runc / OCI) | |
| +-----------------------+ +------------------------+ +----------------+ |
| | | |
| +------------------------> Pod Sandbox <-------------------+ |
+-----------------------------------------------------------------------------------+
The system is strictly divided into two zones:
- Control Plane: Maintains global cluster state, enforces security, and executes scheduling and controller loops.
- Worker Nodes: Hosts daemons (
kubelet,kube-proxy, CNI/CRI runtimes) that isolate and manage container processes.
2. Control Plane Internals: The Engine Room
A. kube-apiserver β The Guarded Gateway
The API Server is the only component allowed to talk directly to etcd. No other component reads from or writes to the database directly.
When kubectl sends a request to kube-apiserver, it passes through a deterministic pipeline:
Request ---> [Authentication] ---> [Authorization (RBAC)] ---> [Mutating Webhooks] ---> [Object Validation] ---> [Validating Webhooks] ---> [etcd Persistence]
- Authentication (AuthN): Extracts client identity using TLS X.509 client certs, Bearer tokens, or OIDC identity tokens.
- Authorization (AuthZ): Evaluates RBAC rules (
ClusterRole,RoleBinding) to answer: Does user X have permission to perform verbcreateon resourcedeploymentsin namespaceprod? - Mutating Admission Controllers: Intercepts and modifies payloads (e.g., injecting sidecar containers or applying default storage classes).
- Schema Validation: Verifies structural adherence to OpenAPI definitions.
- Validating Admission Controllers: Performs final policy checks (e.g., block root user containers).
- ETCD Persistence: Serializes the object into Protobuf/JSON format and commits it to
etcd.
B. etcd β Distributed State & Concurrency Control
etcd is a strongly consistent, distributed key-value store using the Raft consensus protocol.
Key operational mechanics you must know:
- Optimistic Concurrency Control (MVCC):
etcdattaches a strictly increasingresourceVersionto every record. If two controllers update the same object concurrently, the transaction with the staleresourceVersionfails with HTTP409 Conflict. The failed client must re-read the object and re-apply its patch. - Watch Streams: Instead of controllers polling the API server every few seconds, clients maintain persistent HTTP/2 gRPC
watchstreams. Whenetcdmodifies a key prefix,kube-apiserverstreamsADDED,MODIFIED, orDELETEDevents instantly to listeners.
C. kube-scheduler β The Placement Engine
The schedulerβs sole job is to take Pods that have spec.nodeName == "" and assign them to a suitable node. It operates in two phases:
- Filtering Phase (Predicates): Filters out nodes incapable of hosting the Pod.
PodFitsResources: Checks if node CPU/memory capacity can satisfy request limits.NodePorts: Verifies host ports arenβt already bound.NodeSelectors/TaintsAndTolerations: Checks label matches and taints.
- Scoring Phase (Priorities): Ranks the surviving nodes from 0 to 100.
ImageLocality: Gives higher scores to nodes that already have the container image pulled locally.NodeResourcesBalancedAllocation: Scores nodes higher if placing the Pod leaves a balanced ratio of CPU to memory usage.
Once a winner node is selected, kube-scheduler sends a Binding object back to kube-apiserver to populate pod.spec.nodeName.
D. kube-controller-manager β The Reconciliation Engine
kube-controller-manager runs dozens of decoupled control loops inside a single binary.
Each controller executes an asynchronous Reconciliation Loop:
+---------------------------------------+
| |
v |
[Get Desired State] [Observe Actual State]
(from kube-apiserver) (from cluster events)
| |
+-------------------+-------------------+
|
v
[Diff Desired vs Actual]
|
+-----------+-----------+
| |
(States Match) (States Differ)
| |
v v
[Do Nothing] [Execute Repair Action]
(Create/Delete Pods, etc)
For example:
- DeploymentController: Watches
Deployments. When a Deployment update occurs, it creates a newReplicaSet. - ReplicaSetController: Watches
ReplicaSetsandPods. If target replica count is3but only2Pods exist, it submits a request tokube-apiserverto spawn1new Pod.
3. Worker Node Mechanics: From API Object to Running Process
WORKER NODE
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β kubelet ββ(gRPC over UDS)ββ> containerd ββ(OCI CLI)ββ> containerd-shim β
β β β
β v β
β runc β
β β β
β v β
β [Container Process] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
A. kubelet β The Node Supervisor
kubelet runs natively on the node OS (outside containers). It subscribes to kube-apiserver for PodSpecs assigned to its specific node name.
When a new Pod is scheduled to its node:
kubeletparses thePodSpec.- It executes CRI (Container Runtime Interface) gRPC calls to the local runtime socket (e.g.,
/run/containerd/containerd.sock). - It executes CNI (Container Network Interface) calls to set up network namespaces and IP routing.
- It periodically runs Liveness, Readiness, and Startup probes.
B. CRI, containerd, containerd-shim, and runc
Under the hood, kubelet does not manage low-level container namespaces or cgroups directly. It delegates to container runtimes using OCI standards:
kubelet->containerd(CRI Call):kubeletsendsRunPodSandboxover gRPC to set up shared Pod namespaces (Network, IPC, UTS).containerd->containerd-shim:containerdcreates a lightweight daemon calledcontainerd-shimfor each container. This process keeps standard file descriptors (stdout/stderr) open even ifcontainerdrestarts.containerd-shim->runc:containerd-shimexecutesrunc, the OCI reference implementation.- Kernel Namespace & Cgroup Creation:
runcconfigures Linux namespaces (pid,net,mnt,ipc,uts,user) for isolation.runcsets cgroups (cpu.max,memory.max) in/sys/fs/cgroup/to enforce resource quotas.
runclaunches the container main process and exits.containerd-shimremains to monitor the running container process.
4. Cluster Networking: CNI & kube-proxy
A. The Kubernetes Network Model
Kubernetes mandates three core networking invariants:
- Every Pod gets its own unique IP address.
- Pods on any node can communicate with Pods on all other nodes without NAT.
- Agents on a node (like
kubelet) can communicate with all Pods on that node.
B. CNI (Container Network Interface) in Action
When kubelet creates a Pod sandbox, it invokes the configured CNI plugin (e.g., Calico, Flannel, Cilium):
- veth pair creation: CNI creates a virtual Ethernet pair (
veth0inside the Pod namespace andvethXXXXin the host root namespace). - Bridge / Route Attachment: CNI connects
vethXXXXto a host bridge (cni0) or installs host routing table entries. - IP Allocation (IPAM): Assigns a free IP address from the nodeβs allocated subnet (e.g.,
10.244.1.0/24).
C. kube-proxy & Service Traffic Routing
Services provide stable VIPs (Virtual IPs) for pods that frequently die and get recreated. kube-proxy implements Service VIP routing using one of three mechanisms:
1. iptables Mode (Legacy Standard)
kube-proxy installs netfilter rules into Linux iptables.
When traffic hits a Service VIP:
PREROUTINGrules intercept the packet.statistic --mode randomrandomly picks one of the healthy backend Pod IPs.- DNAT (Destination Network Address Translation) rewrites the destination IP from Service VIP to target Pod IP.
Drawback: Scalability issues. iptables rules are evaluated sequentially ($O(N)$ lookup complexity). A cluster with 20,000 services generates hundreds of thousands of rules, causing CPU spikes during updates.
2. IPVS Mode (High Scale)
kube-proxy uses Linux IPVS (IP Virtual Server) kernel module. IPVS uses hash tables ($O(1)$ lookup complexity), maintaining high performance even with 100,000+ services.
3. eBPF Mode (Modern / Cilium)
Modern networking plugins bypass iptables and kube-proxy entirely using eBPF (Extended Berkeley Packet Filter). Custom eBPF programs attached to Linux socket filters directly route packets at the kernel network interface level, eliminating netfilter stack overhead.
5. End-to-End Walkthrough: What Happens During kubectl apply -f deployment.yaml
Letβs trace the complete life-cycle step-by-step:
[User] ββ(1. kubectl apply)ββ> [kube-apiserver] ββ(2. Save State)ββ> [etcd]
β
ββ(3. Watch Event)ββ> [DeploymentController]
β β (Creates ReplicaSet)
β v
β<ββββββββββββββββββββββββββ
β
ββ(4. Watch Event)ββ> [ReplicaSetController]
β β (Creates Pods: nodeName="")
β v
β<ββββββββββββββββββββββββββ
β
ββ(5. Watch Event)ββ> [kube-scheduler]
β β (Filters & Scores Nodes)
β v
β<ββ(6. Bind to Node-A)βββββ
β
ββ(7. Watch Event)ββ> [kubelet (Node-A)]
β
ββ(8. CNI)ββ> Set up veth & IP
ββ(9. CRI)ββ> containerd -> runc
β
v
[Container Running]
kubectlparses your YAML, converts it to JSON, and sends an HTTP POST request tokube-apiserver.kube-apiserverauthenticates, checks RBAC permissions, runs admission webhooks, validates schema, and writes the Deployment object intoetcd.DeploymentControllerreceives anADDEDevent via its watch stream, generates aReplicaSetspec, and POSTs it back tokube-apiserver.ReplicaSetControllerreceives theReplicaSetevent, sees that0/3pods exist, and POSTs3unassignedPoddefinitions (spec.nodeName == "") tokube-apiserver.kube-schedulerpicks up the pending Pods from its watch stream, filters and scores all cluster nodes, selectsNode-A, and submits aBindingobject updatingpod.spec.nodeName = "Node-A".kubeleton Node-A receives theMODIFIEDPod event matching its node name.kubeletinvokes CNI to set up networking (eth0, IPAM allocation).kubeletsendsRunPodSandboxandCreateContainergRPC requests tocontainerd.containerdspawnscontainerd-shim, which invokesruncto create Linux namespaces, set cgroups limits, and start the container process.kubeletreports status back tokube-apiserver, marking the Pod asRunning.
6. Summary Reference Architecture
| Component | Layer / Scope | Main Subsystem / Primitives | Key Communication Protocol |
|---|---|---|---|
kube-apiserver | Control Plane | AuthN, AuthZ, Admission Control, Schema Validation | HTTPS REST / Protobuf / HTTP/2 |
etcd | Control Plane | Raft Consensus, MVCC, Watch API | gRPC over TLS |
kube-scheduler | Control Plane | Predicates (Filtering) & Priorities (Scoring) | HTTP/2 Watch Stream |
kube-controller-manager | Control Plane | Reconciliation Loops (Deployment, RS, Node) | HTTP/2 Watch Stream |
kubelet | Worker Node | Pod Lifecycle Manager, Health Checker | gRPC (CRI) / Netlink (CNI) |
containerd / runc | Worker Node | OCI Runtime, Linux namespaces, cgroups | Unix Domain Sockets / System Calls |
kube-proxy | Worker Node | Service VIP load balancer | Linux iptables / IPVS / eBPF |
Conclusion
Kubernetes is not magicβitβs a masterclass in distributed systems engineering. By combining declarative state management, watch-based event loops, modular runtime interfaces (CRI/CNI), and core Linux kernel isolation primitives (namespaces/cgroups), it builds a resilient engine capable of running global cloud infrastructure seamlessly.