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
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.
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.