What are the core components running on a worker node?
Quick Answer
Each worker node runs a **kubelet** (the agent that talks to the API server, ensures the containers described in its assigned Pods are actually running, and reports node/pod status back), a **container runtime** (like containerd or CRI-O, which actually pulls images and runs containers, via the Container Runtime Interface), and **kube-proxy** (which maintains the networking rules that let traffic reach the right Pod for each Service).
Detailed Answer
The three node-level components
Worker Node
┌──────────────────────────────────────────┐
│ kubelet ───────▶ Container Runtime │
│ ▲ (containerd / CRI-O) │
│ │ → actually runs Pods │
│ │ (talks to API server) │
│ kube-proxy │
│ → maintains network rules for Services │
└──────────────────────────────────────────┘
kubelet
The primary agent on every node — it watches the API server for Pods assigned to its node, and ensures the containers described in each Pod's spec are actually running and healthy (starting them via the container runtime, restarting them if they crash, running liveness/readiness probes). It also reports the node's and its pods' status back to the API server, which is how kubectl get pods and kubectl get nodes show current state. The kubelet does not manage containers that weren't created through Kubernetes — it only manages what's described in the Pod specs assigned to it.
Container runtime
The software that actually pulls container images and runs containers — containerd and CRI-O are the two most common choices today. The kubelet talks to the runtime through a standard interface called the Container Runtime Interface (CRI), rather than being hardcoded to any one runtime (see that question for why Docker specifically was deprecated as a direct Kubernetes runtime, even though containers built with Docker still run fine).
kube-proxy
Maintains the network rules on each node that implement the Service abstraction (see the networking topic) — traditionally via iptables rules, though modern configurations increasingly use IPVS or eBPF-based approaches (like Cilium) for better performance at scale. When a Service is created or its backing Pods change, kube-proxy updates the node's networking rules so traffic sent to the Service's virtual IP gets routed to one of the actual healthy backing Pods.
Why nodes need all three, and the control plane doesn't run them
The control plane decides what should happen (desired state, scheduling decisions); worker nodes are where things actually run. The kubelet and container runtime are what turn a scheduling decision into an actual running container; kube-proxy is what turns a Service definition into actual working network routing on that node. Every node needs all three because every node needs to both run containers and participate correctly in cluster networking — the control plane components, by contrast, don't run application workloads at all (in most production setups) and so don't need them.
What happens if a node's kubelet stops reporting
The control plane's node controller notices the node has stopped sending heartbeats within a configured threshold, marks the node as NotReady, and — after a further grace period — Pods that were running on it are considered for rescheduling onto healthy nodes (assuming they're managed by a controller like a Deployment that maintains a desired replica count; a bare unmanaged Pod would simply be lost).