LFCE 137 🐧 Kubernetes — Nodes and Control Plane
A Kubernetes cluster is a set of machines divided into two roles. The control plane makes global decisions about the cluster—scheduling Pods, detecting node failures, responding to events—and stores the desired state. The worker nodes run the application workloads. Every cluster needs at least one worker node to run Pods, and the control plane manages both the nodes and the Pods on them . In production, the control plane usually runs across multiple computers for fault tolerance, and the cluster usually runs multiple worker nodes for capacity and availability .
This chapter covers the components on each side of that division: the five control plane components and their individual responsibilities, the three components that run on every worker node, and the commands that verify each component is healthy. It also covers the scheduling boundary—what the control plane decides and what the node executes—and the failure modes that occur when one side is unhealthy.
Key point: The control plane does not run application containers. It runs the components that decide where containers should run. The worker nodes run the containers. A Pod is always tied to the node where it was scheduled, and remains there until termination or deletion .
Why the division exists
The global decision problem. Scheduling a Pod requires knowledge of every node’s available resources, the Pod’s requirements, and the cluster’s constraints. A single node cannot make that decision correctly because it does not see the other nodes. The control plane’s scheduler sees the entire cluster and assigns each Pod to a node that satisfies its requirements .
The execution problem. Once a Pod is assigned to a node, the node must start the containers, monitor their health, and report status back to the control plane. The control plane does not reach into the node to start processes; it sends the Pod specification to the node’s kubelet, and the kubelet carries out the instructions .
The failure isolation problem. If a worker node fails, the control plane notices and reschedules the Pods onto other available nodes . If a control plane component fails, the worker nodes continue running their existing Pods, but new scheduling decisions cannot be made until the control plane recovers. The two sides have different failure modes and different recovery paths.
a. The control plane components
The control plane components make global decisions about the cluster and detect and respond to cluster events. They can run on any machine in the cluster, but setup scripts typically start them on dedicated machines that do not run user containers .
The kube-apiserver is the front end of the control plane. It exposes the Kubernetes HTTP API, and every interaction with the cluster—kubectl, the scheduler, the controller manager, the kubelets—goes through it. It is designed to scale horizontally by deploying more instances and balancing traffic between them .
The etcd is a consistent and highly available key-value store used as the backing store for all cluster data. If the cluster uses etcd as its backing store, a backup plan for the data is mandatory .
The kube-scheduler watches for newly created Pods with no assigned node and selects a node for them to run on. The scheduling decision considers individual and collective resource requirements, hardware and software constraints, affinity and anti-affinity specifications, data locality, inter-workload interference, and deadlines .
The kube-controller-manager runs the controller processes. Logically each controller is a separate process, but they are compiled into a single binary and run in a single process to reduce complexity. Examples include the Node controller (notices when nodes go down), the Job controller (creates Pods for one-off tasks), the EndpointSlice controller (links Services to Pods), and the ServiceAccount controller (creates default ServiceAccounts for new namespaces) .
The cloud-controller-manager embeds cloud-specific control logic and links the cluster to the cloud provider’s API. It runs only the controllers that are specific to the cloud provider. A self-hosted cluster or a learning environment does not have one .
b. The node components
Node components run on every worker node, maintaining the running Pods and providing the Kubernetes runtime environment .
The kubelet is the primary node agent. It ensures that Pods and their containers are running. It receives Pod specifications from the API server and manages the containers on the machine .
The kube-proxy is optional. It maintains network rules on nodes to implement Services. Some network plugins provide their own third-party implementation of proxying, and when that kind of plugin is used, the node does not need to run kube-proxy .
The container runtime is the software responsible for running containers. It pulls the container image from a registry, unpacks the container, and runs the application .
Complete Example Session
# ============================================
# PART 1: LIST THE NODES
# ============================================
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# master Ready control-plane 10d v1.34.0
# worker-1 Ready <none> 10d v1.34.0
# worker-2 Ready <none> 10d v1.34.0
# ============================================
# PART 2: CHECK CONTROL PLANE HEALTH
# ============================================
kubectl get componentstatuses
# NAME STATUS MESSAGE ERROR
# scheduler Healthy ok
# controller-manager Healthy ok
# etcd-0 Healthy ok
# ============================================
# PART 3: CHECK CONTROL PLANE PODS
# ============================================
kubectl get pods -n kube-system
# kube-apiserver-master 1/1 Running
# kube-controller-manager-master 1/1 Running
# kube-scheduler-master 1/1 Running
# etcd-master 1/1 Running
# coredns-... 1/1 Running
# kube-proxy-... 1/1 Running
# ============================================
# PART 4: CHECK THE API SERVER
# ============================================
kubectl cluster-info
# Kubernetes control plane is running at https://10.0.0.1:6443
# ============================================
# PART 5: CHECK THE SCHEDULER
# ============================================
kubectl get pods -n kube-system -l component=kube-scheduler
# kube-scheduler-master 1/1 Running
# ============================================
# PART 6: CHECK THE CONTROLLER MANAGER
# ============================================
kubectl get pods -n kube-system -l component=kube-controller-manager
# kube-controller-manager-master 1/1 Running
# ============================================
# PART 7: CHECK ETCD
# ============================================
kubectl get pods -n kube-system -l component=etcd
# etcd-master 1/1 Running
# ============================================
# PART 8: CHECK THE KUBELET ON A NODE
# ============================================
# On the node itself:
systemctl status kubelet
# Active: active (running)
# ============================================
# PART 9: CHECK KUBE-PROXY
# ============================================
kubectl get pods -n kube-system -l k8s-app=kube-proxy
# kube-proxy-xxxxx 1/1 Running
# ============================================
# PART 10: CHECK THE CONTAINER RUNTIME
# ============================================
# On the node itself:
crictl info | grep -i runtimeType
# "runtimeType": "containerd"
The ten parts covered node listing, component statuses, control plane Pods, the API server, the scheduler, the controller manager, etcd, the kubelet, kube-proxy, and the container runtime.
Quick Reference
Control plane components
| Component | Responsibility |
|---|---|
kube-apiserver | Exposes the Kubernetes API, front end |
etcd | Backing store for all cluster data |
kube-scheduler | Assigns Pods to nodes |
kube-controller-manager | Runs controller loops |
cloud-controller-manager | Cloud provider integration (optional) |
Node components
| Component | Responsibility | Optional |
|---|---|---|
kubelet | Ensures Pods and containers run | No |
kube-proxy | Network rules for Services | Yes (with some CNIs) |
| Container runtime | Runs containers | No |
Verification commands
| Command | Checks |
|---|---|
kubectl get nodes | Node status |
kubectl get componentstatuses | Control plane health |
kubectl get pods -n kube-system | Control plane Pods |
kubectl cluster-info | API server endpoint |
systemctl status kubelet | Kubelet on a node |
crictl info | Container runtime on a node |
Best Practices
✅ Do This:
# Back up etcd regularly
etcdctl snapshot save backup.db # ✅
# Run the control plane on dedicated machines
# Do not schedule user workloads there # ✅
# Check componentstatuses after cluster changes
kubectl get componentstatuses # ✅
# Verify the kubelet on each node after maintenance
systemctl status kubelet # ✅
❌ Don’t Do This:
# Assume the control plane is healthy because nodes are Ready
# Check componentstatuses separately # ❌
# Run user workloads on control plane nodes
# Without taints and tolerations, they compete for resources # ❌
# Skip etcd backups
# Losing etcd loses the cluster state # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Pods stay Pending | No worker nodes or insufficient resources | Check kubectl get nodes and resource requests |
kubectl commands fail | API server down | Check kubectl cluster-info and API server Pod |
| Node shows NotReady | Kubelet or container runtime down | Check systemctl status kubelet and crictl info |
| Service name does not resolve | CoreDNS not running | Check kube-system for CoreDNS Pods |
| Scheduling stops | Scheduler down | Check kube-scheduler Pod and componentstatuses |
Real-World Examples
1. List nodes
kubectl get nodes
2. Check control plane health
kubectl get componentstatuses
3. Check control plane Pods
kubectl get pods -n kube-system
4. Check API server
kubectl cluster-info
5. Check scheduler
kubectl get pods -n kube-system -l component=kube-scheduler
6. Check controller manager
kubectl get pods -n kube-system -l component=kube-controller-manager
7. Check etcd
kubectl get pods -n kube-system -l component=etcd
8. Check kubelet
systemctl status kubelet
9. Check kube-proxy
kubectl get pods -n kube-system -l k8s-app=kube-proxy
10. Check container runtime
crictl info
Visual
The cluster architecture
┌─────────────────────────────────────────────────────────────┐
│ CONTROL PLANE │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ kube- │ │ etcd │ │ kube- │ │
│ │ apiserver │ │ │ │ scheduler │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ kube-controller-manager │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ WORKER NODE 1 WORKER NODE 2 │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ kubelet │ │ kubelet │ │
│ │ kube-proxy │ │ kube-proxy │ │
│ │ runtime │ │ runtime │ │
│ │ ┌──────────┐ │ │ ┌──────────┐ │ │
│ │ │ Pod │ │ │ │ Pod │ │ │
│ │ └──────────┘ │ │ └──────────┘ │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
The scheduling boundary
┌─────────────────────────────────────────────────────────────┐
│ CONTROL PLANE DECIDES NODE EXECUTES │
│ │
│ Scheduler selects a node Kubelet receives the Pod │
│ for a new Pod specification │
│ │ │ │
│ ▼ ▼ │
│ Node is assigned Kubelet starts the containers│
│ │ │
│ ▼ │
│ Container runtime pulls image│
│ and runs the container │
└─────────────────────────────────────────────────────────────┘
Pod scheduling and failure
┌─────────────────────────────────────────────────────────────┐
│ POD LIFECYCLE │
│ │
│ Pod created ──► Scheduler assigns node │
│ │ │
│ ▼ │
│ Pod runs on that node │
│ │ │
│ ├── Node fails ──► Control plane reschedules │
│ │ identical Pod on another node │
│ │ │
│ └── Pod terminated ──► according to restart policy │
└─────────────────────────────────────────────────────────────┘
Verification flow
┌─────────────────────────────────────────────────────────────┐
│ HEALTH CHECK │
│ │
│ kubectl get nodes │
│ └── Are worker nodes Ready? │
│ │
│ kubectl get componentstatuses │
│ └── Is the control plane healthy? │
│ │
│ kubectl get pods -n kube-system │
│ └── Are the control plane Pods running? │
│ │
│ systemctl status kubelet (on each node) │
│ └── Is the node agent running? │
└─────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Control plane | Makes global decisions |
| Worker nodes | Run application Pods |
| API server | Front end, exposes the Kubernetes API |
| etcd | Backing store for all cluster data |
| Scheduler | Assigns Pods to nodes |
| Controller manager | Runs reconciliation loops |
| Kubelet | Node agent, ensures Pods run |
| kube-proxy | Network rules for Services (optional with some CNIs) |
| Container runtime | Runs containers |
| Pod placement | Tied to the scheduled node until termination |
Key takeaways:
- The control plane decides, and the worker nodes execute. The scheduler selects a node for each Pod, and the kubelet on that node ensures the containers are running. The control plane does not run application containers .
- The
kube-apiserveris the front door. Every interaction with the cluster goes through it. It is stateless and can be scaled horizontally for high availability . etcdis the source of truth. Every object in the cluster is stored there. A backup plan is mandatory, because losingetcdmeans losing the cluster’s state .- The
kubeletis the node agent. It receives Pod specifications from the API server and ensures the containers are running. The container runtime does the actual running . kube-proxyis optional with some CNI plugins. It maintains the network rules for Services, but a plugin that provides its own proxying can replace it .- A Pod is tied to its node. It remains on the node where it was scheduled until termination or deletion. If the node fails, the control plane schedules an identical Pod on another available node .
Remember: The Kubernetes cluster is a separation of concerns. The control plane makes the global decisions—scheduling, reconciliation, API access—and the worker nodes execute the local work—running containers, reporting status, routing traffic. The kube-apiserver is the interface, etcd is the memory, the scheduler is the placement decision, and the controller manager is the reconciliation loop. The kubelet on each node is the agent that carries out the instructions. When a Pod stays Pending, the scheduler cannot find a node that satisfies its requirements. When a node goes NotReady, the kubelet or the container runtime has failed. When kubectl stops responding, the API server is down. Knowing which component is responsible for which decision is what makes cluster debugging tractable.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!