✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Worker Node Architecture

Kubernetes Worker Node Architecture explains the structure and components of nodes that run containerized applications in a Kubernetes cluster.

Kubernetes Worker Node Architecture is the internal layering of components and interfaces present on every worker machine, tracing how a scheduling decision made by the control plane ultimately becomes a running, networked, storage-attached container process on that specific machine. Where cluster architecture as a whole describes how the control plane and nodes relate, worker node architecture zooms into a single node and examines the stack of software running on it, from the kubelet at the top down through the container runtime, the operating system's isolation primitives, and the pluggable interfaces connecting it to networking and storage.


The Node's Internal Stack

Layered Responsibility

A worker node's software stack is formally layered: the kubelet sits at the top, translating API-level Pod specifications into concrete actions; below it, the container runtime interface (CRI) mediates to an actual container runtime; below that, the runtime relies on OS-level primitives, namespaces, cgroups, to isolate and constrain processes; alongside this vertical stack, CNI and CSI plugins provide networking and storage as horizontal services the kubelet invokes at the appropriate lifecycle moments.

node_stack:
  - kubelet                # top: API-driven reconciliation
  - CRI (container runtime) # containerd / CRI-O
  - CNI plugin              # pod networking
  - CSI plugin               # volume attachment
  - kube-proxy                # service routing rules
  - OS kernel primitives        # namespaces, cgroups, filesystem
node = kubelet CRI kernel

kubelet as the Node's Reconciliation Engine

Watching Only Its Own Pods

The kubelet formally watches the API server for Pods whose spec.nodeName matches its own node's identity, ignoring every other Pod in the cluster; this narrow scope is what allows kubelets across thousands of nodes to operate independently without coordinating with one another.

PLEG and Status Reporting

Internally, the kubelet runs a Pod Lifecycle Event Generator (PLEG) that periodically inspects the container runtime's actual state and compares it against the Pods it is responsible for, generating the status updates it then writes back to the API server, forming the node's half of the overall reconciliation loop.

kubectl get pod codartium-app-abc123 -o jsonpath='{.status.containerStatuses}'
journalctl -u kubelet -f

The CRI Boundary

Runtime Interchangeability

The Container Runtime Interface formally decouples the kubelet from any specific runtime implementation; the kubelet issues CRI gRPC calls, create Pod sandbox, pull image, start container, and any CRI-compliant runtime, containerd, CRI-O, satisfies those calls identically from the kubelet's perspective.

crictl ps
crictl images
crictl inspect <container-id>

Pod Sandbox as a Runtime Concept

Beneath the Pod abstraction the API exposes, the runtime formally maintains a "Pod sandbox," the shared network namespace and supporting infrastructure that all of a Pod's containers join, created once per Pod and reused across container restarts within it.


Kernel-Level Isolation

Namespaces

Linux namespaces formally provide the isolation boundary between a container and the rest of the node: PID namespaces isolate process trees, mount namespaces isolate filesystem views, and, at the Pod level, network and IPC namespaces are shared across a Pod's containers rather than isolated individually.

Control Groups (cgroups)

Control groups formally enforce the resource limits declared in a Pod's resources.limits, capping CPU and memory usage for each container's process tree at the kernel level, independent of and beneath the scheduling and admission decisions made earlier in a Pod's lifecycle.

cgroup limit = container resources.limits

Networking Layer on the Node

CNI Invocation Points

The kubelet formally invokes the configured CNI plugin at two points in a Pod's lifecycle: once to set up networking when the Pod sandbox is created, and once to tear it down when the Pod is removed, with the plugin responsible for IP allocation and attaching the sandbox to the cluster's broader network fabric.

kube-proxy's Local Rule Programming

kube-proxy runs on every node independently, watching Service and EndpointSlice objects and translating them into local packet-forwarding rules, meaning Service routing is, architecturally, a per-node responsibility rather than a centralized one, even though its configuration is driven by cluster-wide objects.

iptables -t nat -L KUBE-SERVICES -n
ip route show

Storage Layer on the Node

CSI Volume Lifecycle

For Pods referencing persistent storage, the kubelet formally coordinates with a node-local CSI driver component to stage, mount, and, on Pod termination, unmount and unstage the corresponding volume, a multi-step handshake distinct from and layered on top of the underlying PersistentVolume/PersistentVolumeClaim binding already resolved by the control plane.

kubectl get volumeattachments
mount | grep kubelet

Why the Node Is Architected in Layers

Structuring the node's internals as a stack of narrowly scoped, independently replaceable layers, kubelet, CRI, CNI, CSI, kernel primitives, mirrors the same separation-of-concerns principle applied to the cluster as a whole: any layer, a specific container runtime, a specific CNI implementation, a specific CSI driver, can be substituted without requiring changes to the layers above or below it, so long as each continues to satisfy the interface the layers around it depend on.