What Is a Node (Worker Node) in Kubernetes?
The machine that actually runs your applications: what lives inside it, how it stays healthy, and how it fits into a Kubernetes cluster.
Imagine you tap a button in a food-delivery app. Behind that tap, a small program has to wake up, look up your order, and send back a reply within a fraction of a second. That program has to run on a real computer somewhere. Now imagine thousands of such programs, all needing computers at the same time, all being started, stopped, and moved around all day long. Someone has to decide which program goes on which computer. That someone is Kubernetes.
The computers that do the running are called nodes. If Kubernetes is the manager of a giant kitchen, a node is one cooking station with its own stove, its own fridge, and its own cook. In this guide you will learn what a node is, what lives inside it, how it talks to the rest of the system, how it stays healthy, and how large companies run thousands of them without losing sleep.
1What Is a Worker Node?
Before anything else, let us pin down exactly what a node is and what it is not.
The one-sentence answer
A node is a single machine, either a physical server or a virtual machine, that belongs to a Kubernetes cluster and does the real work of running your applications. Every time you deploy something on Kubernetes, that something ends up running on a node. A worker node is simply the everyday name for such a machine. People use the word “worker” to tell it apart from the machines that manage the cluster.
Let us define the words in that sentence. A cluster is a group of machines that are managed together so they behave like one big computer. A container is a lightly packaged box that holds one program plus everything the program needs, such as its libraries and settings. A pod is the smallest unit Kubernetes schedules. It wraps one or more containers that must live side by side and share the same network address and storage. A pod always lives on exactly one node. It can never be split across two.
Think of a large restaurant chain. The head office takes orders and decides which branch should cook which dish. Each branch is a node. Inside a branch there is a kitchen with stoves and fridges (the CPU, memory, and disk), and a shift supervisor who receives instructions from head office and makes sure the cooks follow them. Each dish being prepared is a pod. If a branch catches fire, head office simply sends the same orders to another branch.
Where do nodes come from?
A node can be almost any computer that runs a supported operating system, which is usually Linux. In the cloud, a node is normally a virtual machine, such as an Amazon EC2 instance in Amazon EKS, a Compute Engine VM in Google GKE, or a virtual machine in Azure AKS. In a company data center, a node might be a physical server in a rack. Hobbyists even build small clusters from Raspberry Pi boards. Kubernetes does not care about the brand of the hardware. It only cares that the machine has the right software installed and can reach the rest of the cluster over a network.
You will hear two meanings of “node”. One is the real machine. The other is the Node object, a small record stored inside Kubernetes that represents the machine. The record holds its name, address, labels, and health. Deleting the record does not destroy the machine, but Kubernetes will forget it exists.
Older documents call worker nodes “minions” and the management machines “masters”. Modern Kubernetes prefers “worker node” and “control plane node”. If you read an old tutorial, mentally translate the words.
2Control Plane vs Worker Node
A cluster has two kinds of machines with two very different jobs. Mixing them up is one of the most common sources of confusion.
The control plane is the brain of the cluster. It stores what you asked for, decides where things should run, and watches for anything that drifts from the plan. The worker nodes are the muscles. They follow instructions and run the actual containers. Your own application code normally runs only on worker nodes.
| Aspect | Control Plane | Worker Node |
|---|---|---|
| Main job | Decide, store, and coordinate | Run containers and report back |
| Key components | API server, etcd, scheduler, controller manager | kubelet, container runtime, kube-proxy |
| Runs your app? | Normally no, it is tainted to keep workloads away | Yes, this is where pods run |
| If one fails | Cluster cannot change, but running apps usually keep running | Pods on it stop, and replacements start elsewhere |
| Typical count | 1 for learning, 3 or 5 for production | From 1 to thousands |
The control plane has four main parts. The kube-apiserver is the front door; every request goes through it. etcd is the database that stores the desired state of the cluster. The kube-scheduler chooses a node for every new pod. The kube-controller-manager runs many small loops that keep reality matching the plan, for example noticing that a node has gone silent.
flowchart TB
Dev["Developer using kubectl"] --> API
Users["End users"] --> LB["Cloud Load Balancer"]
subgraph CP["Control Plane"]
API["kube-apiserver"]
ETCD[("etcd datastore")]
SCH["kube-scheduler"]
CTRL["kube-controller-manager"]
API --- ETCD
SCH --> API
CTRL --> API
end
subgraph W1["Worker Node 1"]
K1["kubelet"]
R1["Container runtime"]
X1["kube-proxy"]
POD1["Pods"]
K1 --> R1 --> POD1
end
subgraph W2["Worker Node 2"]
K2["kubelet"]
R2["Container runtime"]
X2["kube-proxy"]
POD2["Pods"]
K2 --> R2 --> POD2
end
K1 --> API
K2 --> API
LB --> X1
LB --> X2
Read the diagram from the top. A developer sends a request through kubectl, the command-line tool, to the API server. The API server saves it in etcd. The scheduler and controller manager watch the API server and react. Notice that the control plane never talks directly to your containers. Instead, the kubelet on each worker node reaches up to the API server, asks what it should be running, and does it. End-user traffic takes a separate path: it arrives at a cloud load balancer, which forwards it to the nodes, where kube-proxy steers it to the right pod.
In small learning clusters such as minikube or kind, one machine plays both roles. That is convenient for practice but it is not how production clusters are built.
3Inside a Node: The Core Components
A node is more than a computer. It is a computer plus a small team of software helpers that connect it to the cluster.
On top of its operating system, every worker node runs a handful of components. Each has one clear responsibility. Understanding who does what makes almost every Kubernetes problem easier to debug.
kubelet
The node’s shift supervisor. It takes pod instructions from the API server and makes sure they are carried out and kept healthy.
Container runtime
The software that pulls images and starts containers. Common choices are containerd and CRI-O.
kube-proxy
Programs rules in the operating system so traffic sent to a Service reaches one of the healthy pods behind it.
CNI plugin
Gives every pod its own network address and connects it to the wider cluster network. Examples are Calico, Cilium, and the AWS VPC CNI.
CSI node plugin
Attaches and mounts disks or network storage so pods can save data that survives restarts.
cAdvisor
A measuring tool built into the kubelet. It records how much CPU, memory, disk, and network each container is using.
flowchart LR
API["kube-apiserver (control plane)"]
subgraph NODE["Worker Node"]
KUBELET["kubelet"]
CADV["cAdvisor inside kubelet"]
CRI["Container runtime such as containerd"]
PROXY["kube-proxy"]
CNI["CNI plugin"]
CSI["CSI node plugin"]
KERNEL["Linux kernel rules: iptables or IPVS"]
subgraph PODS["Pods"]
PA["Pod A"]
PB["Pod B"]
end
KUBELET -->|"CRI calls"| CRI
CRI --> PODS
KUBELET -->|"asks for pod network"| CNI
KUBELET -->|"asks for volumes"| CSI
KUBELET --- CADV
PROXY -->|"programs traffic rules"| KERNEL
end
KUBELET |"watch and report"| API
PROXY -->|"watch Services"| API
Look at how the kubelet sits in the middle. It is the only component that constantly talks to the control plane about pods. When a pod arrives, the kubelet asks the container runtime to create it, asks the CNI plugin to wire up its network, and asks the CSI plugin to mount its storage. Meanwhile kube-proxy works separately: it watches Services in the API server and translates them into rules that the Linux kernel enforces. The kernel itself moves the packets, so kube-proxy is not sitting in the traffic path like a traditional proxy server would.
There is one more small helper worth knowing: the pause container. Whenever a pod starts, the runtime first creates a tiny, do-nothing container whose only job is to hold the pod’s network space open. The real containers then join that space and share it. This is why all containers in a pod can talk to each other over localhost.
Picture the pause container as the apartment’s front door and mailbox. The tenants (your containers) come and go, but the address stays the same as long as the apartment exists.
4The Kubelet in Depth
If you remember only one node component, make it the kubelet. It is the link between the cluster’s plan and the machine’s reality.
The kubelet is a background program that runs on every worker node. It does not run inside a container; it runs directly on the machine so that it keeps working even when containers misbehave. Its work can be described as a loop that repeats forever: look at what should be running, look at what is actually running, and fix any difference.
Register the node
When a machine joins, the kubelet introduces itself to the API server with a secure certificate and creates the Node record, including its CPU, memory, and address.
Watch for assigned pods
It keeps a live connection to the API server and notices every pod whose chosen node is this one.
Start and stop containers
It asks the container runtime to create containers, mounts volumes, and injects settings and secrets into them.
Check health
It runs small tests called probes against each container and restarts or isolates those that fail them.
Report status
It sends heartbeats and reports pod and node conditions back to the control plane.
Protect the node
When memory or disk runs low, it evicts less important pods so the machine itself does not fall over.
The three kinds of probes
A probe is a routine check, like a nurse asking “are you okay?” at regular intervals. A liveness probe asks whether the container is stuck; if the answer is no, the kubelet restarts it. A readiness probe asks whether the container is ready to receive traffic; if the answer is no, the pod is quietly removed from the list of destinations for its Service until it recovers. A startup probe gives slow-starting programs extra time before the other two begin. When a container keeps crashing, the kubelet waits longer between each restart, up to five minutes, which you will see as the status CrashLoopBackOff.
Static pods
Normally pods arrive from the API server. There is one exception: static pods. These are described by files placed in a special folder on the node itself, and the kubelet starts them without asking anyone. Tools such as kubeadm use this trick to launch control plane components, because at the moment a cluster is born there is no API server yet to give instructions.
The kubelet only manages containers that it created for pods. If someone starts a container by hand on a node, the kubelet does not know about it, does not count its resources, and will not clean it up.
Because the kubelet is so central, its own health matters. If it crashes or freezes, the node stops sending heartbeats, and the control plane will eventually declare the node lost even though the containers may still be running. The kubelet listens on port 10250, which is why securing that port is such an important task, as you will see later.
5The Container Runtime
The kubelet gives the orders. The container runtime is the hands that do the work.
A container runtime is software that downloads container images, unpacks them, and starts them as isolated processes on the machine. An image is the frozen, ready-to-run package of your program, similar to an installer file. The runtime pulls it from a registry, which is an online storage place for images such as Docker Hub or Amazon ECR.
How does a container stay separated from its neighbours on the same machine? The Linux kernel provides two tools. Namespaces give each container its own private view of the system, so it sees only its own processes and network. Cgroups (control groups) limit how much CPU and memory the container may use. Together they create the illusion of a small private computer without the cost of running a full extra operating system.
The kubelet is the shift supervisor who writes “prepare dish 42” on a ticket. The container runtime is the cook who reads the ticket, fetches the ingredients, and does the actual chopping. Namespaces are the walls of each cooking booth, and cgroups are the portion limits that stop one cook from grabbing all the flour.
The Container Runtime Interface
The kubelet does not know how any specific runtime works. Instead, both sides agree on a common language called the Container Runtime Interface, or CRI. Any runtime that speaks CRI can be plugged in. This is a good example of a clean design: because the contract is fixed, teams can swap the engine underneath without changing the rest of Kubernetes.
| Runtime | Who uses it | Notes |
|---|---|---|
| containerd | Most managed services, including EKS and GKE | General-purpose and widely adopted; it grew out of the original Docker project |
| CRI-O | Red Hat OpenShift and some others | Built specifically for Kubernetes and nothing else |
| Docker Engine | Older clusters | No longer supported directly since Kubernetes 1.24; it needs an extra adapter |
That last row causes a lot of worry, so let us clear it up. In version 1.24, Kubernetes removed a built-in bridge called dockershim that let the kubelet talk to Docker Engine. This did not break Docker-built images. Images follow an open standard called OCI, and containerd runs them happily. What changed is only which program on the node starts them.
Standard containers share the node’s kernel. For untrusted code, Kubernetes lets you pick a different runtime per pod through a feature called RuntimeClass. Sandboxed runtimes such as gVisor and Kata Containers add an extra wall around the pod, at the cost of some speed.
6kube-proxy and Node Networking
Pods are born and die constantly. Networking is what keeps the rest of the system able to find them.
Kubernetes follows a simple networking promise: every pod gets its own IP address, and any pod can reach any other pod without tricks such as address translation. Making that promise true is the job of the CNI plugin (Container Network Interface). When the kubelet creates a pod, the CNI plugin picks an address, creates a virtual network cable between the pod and the node, and adds the routes needed so other nodes know where to send packets. Different plugins do this differently. Calico uses routing rules, Cilium uses a modern kernel technology called eBPF, and the AWS VPC CNI hands pods real addresses from your private cloud network.
There is a problem, though. Pod addresses change every time a pod is replaced. If a website pod needs to call a database pod, it cannot memorize an address that may vanish in an hour. Kubernetes solves this with a Service: a stable name and virtual address that stands in front of a changing group of pods.
A Service is like a hotel’s front desk phone number. Guests (pods) change rooms all the time, but callers always dial the same number, and the desk connects them to whoever is currently available.
What kube-proxy actually does
The Service address is virtual: no machine owns it. kube-proxy makes it real. It watches the API server for Services and for the list of healthy pods behind each one. Then it writes rules into the node’s kernel that say: “any packet sent to this Service address should be redirected to one of these pod addresses.” Because every node has its own kube-proxy, every node can route Service traffic locally without asking anyone.
iptables
The long-time default. It writes a chain of rules and picks a pod at random. Simple and reliable, but very large clusters can make the rule list slow.
IPVS
Uses the kernel’s built-in load balancer. It handles thousands of Services better and offers choices such as round robin and least connections.
nftables
A newer rule system that is replacing iptables across Linux. Recent Kubernetes versions support it in kube-proxy.
No kube-proxy
Some CNI plugins, Cilium being the best known, can take over Service routing entirely and let you skip kube-proxy.
Services come in several flavours. A ClusterIP Service is reachable only from inside the cluster. A NodePort Service opens the same port number on every node so outside traffic can enter. A LoadBalancer Service asks the cloud provider to create a public load balancer in front of the nodes. Names such as “orders.shop.svc” are turned into Service addresses by CoreDNS, a DNS server that itself runs as pods on your nodes.
Because kube-proxy only writes rules and the kernel moves the packets, a crash of kube-proxy does not immediately break traffic. Existing rules keep working. New changes simply stop being applied until it returns.
7Node Resources: Capacity, Allocatable, and QoS
A node has a fixed amount of CPU, memory, and disk. Kubernetes must share them fairly without letting any one pod ruin the party.
Every node reports how much it owns. This total is its capacity. But not all of it is available to your pods, because the operating system and Kubernetes components need some for themselves. What is left after those reservations is called allocatable. The scheduler only ever plans against the allocatable number.
Picture an apartment building with 100 units of floor space. The lobby, the elevators, and the boiler room take 15. The other 85 can be rented to tenants. Capacity is 100. Allocatable is 85.
| Term | Meaning | Who sets it |
|---|---|---|
| Capacity | Total CPU, memory, disk, and pod slots on the machine | The hardware or VM size |
| System and kube reserved | Space kept for the operating system and Kubernetes agents | Node administrator |
| Eviction threshold | A safety margin; when free space drops below it the kubelet starts removing pods | Node administrator |
| Allocatable | What remains for pods | Calculated automatically |
| Request | The minimum a container asks for; the scheduler uses this to pick a node | Application team |
| Limit | The maximum a container may use | Application team |
Requests, limits, and what happens when they are crossed
A request is a promise the scheduler honours: “this pod needs at least this much.” A limit is a ceiling the node enforces. The two resources behave differently when the ceiling is hit. CPU is compressible: a container that wants more CPU than its limit is simply slowed down, called throttling. Memory is incompressible: you cannot take back memory that a program is already holding, so a container that exceeds its memory limit is killed and reports OOMKilled, short for out of memory.
Quality of Service classes
Based on the requests and limits you set, Kubernetes puts every pod into one of three classes. These decide who is sacrificed first when a node runs short.
BestEffort
No requests or limits at all. These pods get leftovers and are evicted first.
Burstable
Some requests set, but limits are higher or missing. They may use spare room, and are evicted next if they exceed their requests.
Guaranteed
Requests equal limits for every container. These are the last to be touched.
By default, the kubelet begins evicting pods when available memory falls below 100 MiB or when free disk space on the main filesystem drops under 10 percent. It also caps each node at 110 pods, a number you can change but should think about carefully, because more pods on a node means more networking and bookkeeping work.
Pods without requests look free to the scheduler, so it happily stacks dozens of them on one node. Everything works until traffic rises, and then the node runs out of memory and pods start dying at random.
8How a Pod Lands on a Node: Data Flow and Lifecycle
Let us follow one request from the moment you press Enter until your container is serving traffic.
Suppose you ask Kubernetes for a Deployment, which is a request such as “keep three copies of my web app running.” Behind the scenes, controllers turn that into three pod records that have no node assigned yet. Then the real journey to a node begins.
sequenceDiagram
participant U as Developer
participant A as kube-apiserver
participant E as etcd
participant S as kube-scheduler
participant K as kubelet on the node
participant R as Container runtime
participant C as CNI plugin
U->>A: Submit Deployment
A->>E: Save desired state
Note over A,S: Controllers create Pod records with no node assigned
S->>A: Watch for unassigned pods
S->>A: Bind pod to the chosen node
A->>E: Save node assignment
K->>A: Watch for pods on my node
K->>R: Create pod sandbox
R->>C: Set up pod network
K->>R: Pull image and start containers
K->>A: Report status Running
The scheduler does the choosing, but it does not touch the node. It first filters out nodes that cannot host the pod, for instance those without enough allocatable memory or those carrying a taint the pod does not tolerate. Then it scores the survivors and picks the best. It records its decision by binding the pod to that node in the API server. From then on, the story belongs to the kubelet.
Scheduled
The pod now names a node. Its status is still Pending because nothing is running yet.
Sandbox created
The runtime builds the pod’s private space and starts the pause container.
Network attached
The CNI plugin assigns the pod its IP address and connects it to the cluster network.
Volumes mounted
Storage, secrets, and configuration files are placed where the containers expect them.
Containers started
Images are pulled if the node does not already hold them, then the containers begin. The status changes to Running.
Ready for traffic
Once the readiness probe passes, the pod joins the Service and real users can reach it.
How a pod leaves
Shutdown is polite by design. When a pod is deleted, Kubernetes first removes it from Service lists so no new traffic arrives. The kubelet then sends the container a gentle stop signal, SIGTERM, giving the program time to finish current work and close connections. By default it waits 30 seconds. If the container is still alive after that, the kubelet forcibly kills it. Well-behaved applications listen for SIGTERM, finish in-flight requests, and exit cleanly, which is what makes rolling updates invisible to users.
The slowest step is usually pulling a large image on a fresh node. Nodes cache images they have already downloaded, so the second pod of the same app on the same node starts much faster than the first.
9Node Health, Conditions, and Failure Recovery
Machines fail. Kubernetes is built on the assumption that they will, and it has a clear routine for noticing and recovering.
Each node keeps a list of conditions, which act like a health report card. The kubelet updates them and the control plane reads them.
| Condition | True means |
|---|---|
| Ready | The node is healthy and can accept pods |
| MemoryPressure | Free memory is dangerously low |
| DiskPressure | Free disk space or inodes are dangerously low |
| PIDPressure | Too many processes are running |
| NetworkUnavailable | The node’s network is not set up correctly |
Heartbeats
How does the control plane know a node is alive? The kubelet sends two kinds of heartbeat. The lightweight one is a Lease, a tiny record in a special namespace called kube-node-lease that the kubelet refreshes about every 10 seconds. The heavier one is the full node status, sent whenever something changes and at least every five minutes. Leases were introduced because thousands of large status updates were putting needless load on the API server and etcd.
What happens when a node goes silent
flowchart TB
A["Node stops sending heartbeats"] --> B["Node controller waits about 40 seconds"]
B --> C["Node marked NotReady or Unknown"]
C --> D["Taints added to the node"]
D --> E["Pods wait out a 5 minute default tolerance"]
E --> F["Pods on the node are evicted"]
F --> G["Controllers create replacement pods"]
G --> H["Scheduler places them on healthy nodes"]
Follow the chain. After the grace period of about 40 seconds without a heartbeat, the node controller marks the node’s Ready condition as Unknown. It then adds taints, which are “keep away” labels, telling the cluster that the node is unreachable. Pods normally carry a built-in patience of 300 seconds, so they are not thrown out at the first hiccup. If the node does not return within that time, the pods are evicted. Their parent controllers notice that fewer copies are running than requested and create replacements, which the scheduler places on healthy nodes.
Pods that belong to a StatefulSet, such as database members, are handled more carefully. Kubernetes will not start a replacement until it is sure the old one is truly gone, because two copies writing to the same data could corrupt it. As a result, recovery may pause until the node is confirmed dead or removed by an operator.
Many clouds add their own repair layer on top. An auto-scaling group or a managed node group can notice that a machine failed its health check, terminate it, and launch a fresh one that joins the cluster automatically. This is why treating nodes as replaceable, rather than precious, works so well.
10Labels, Taints, Tolerations, Cordon, and Drain
Not every pod belongs on every node. Kubernetes gives you a small toolbox to steer pods toward or away from specific machines.
Real clusters are rarely made of identical machines. Some nodes have fast SSD disks, some have expensive GPUs, some run in a particular data center zone, and some are cheap short-lived spot machines. The following tools let you describe those differences and act on them.
Labels
Simple key and value tags attached to a node, such as disk type or zone. Cloud providers add many automatically, including operating system and availability zone.
Node selector and affinity
A pod says “I want to run on nodes with this label.” Affinity adds softer preferences like “try to, but it is fine if you cannot.”
Taints
A mark on a node that says “keep out unless you have permission.” Effects include NoSchedule, PreferNoSchedule, and NoExecute, which also removes pods already there.
Tolerations
A pod’s permission slip that lets it ignore a matching taint. A toleration allows a pod onto a tainted node but does not force it there.
Cordon
Marks a node unschedulable so no new pods arrive. Pods already running stay untouched.
Drain
Cordons the node, then gently evicts its pods so they restart elsewhere. This is the standard step before maintenance.
A taint is a “Reserved for staff” sign on a parking spot. A toleration is the staff badge that lets a car park there. Cordon is a rope across the car park entrance so no new cars enter. Drain is the attendant politely asking every parked car to move to another lot.
Use case: keeping expensive GPU machines for the jobs that need them
A team adds a taint to every GPU node. Ordinary web pods do not have the matching toleration, so they never land there and never waste the costly hardware. Machine-learning jobs carry the toleration and a node selector for the GPU label, so they go exactly where intended.
Drain respects a safety device called a PodDisruptionBudget, which lets an application say “never take more than one of my copies down at a time.” It also skips DaemonSet pods, which are meant to run on every node anyway. Without these rules, a routine maintenance drain could accidentally remove every copy of a service at once.
11Advantages, Disadvantages, and Trade-offs
The node model is powerful, but every design choice has a price. Knowing both sides helps you decide well.
Advantages
- Horizontal growth: Add more nodes to add more capacity, instead of buying an ever bigger machine.
- Failure isolation: A single dead node affects only the pods on it, and they are rescheduled elsewhere.
- Efficient packing: The scheduler fills nodes sensibly, so hardware is used more fully than one-app-per-server setups.
- Portable model: A node looks similar on any cloud or in your own data center.
- Safe maintenance: Cordon and drain let you patch machines with little or no downtime.
Disadvantages
- Operational upkeep: Someone must patch, upgrade, and monitor the operating system of every node.
- Fixed overhead: Each node spends CPU and memory on system agents before your pods get anything.
- Noisy neighbours: Pods on the same node compete for shared resources such as disk and network.
- Shared kernel: A serious flaw in the kernel can affect every container on that node.
- Idle cost: Half-empty nodes still cost full price.
The classic trade-off: big nodes or small nodes?
When you design a cluster you must pick machine sizes. There is no universal answer, only a balance.
| Question | Few large nodes | Many small nodes |
|---|---|---|
| Blast radius of one failure | Large; many pods disappear together | Small; only a few pods are affected |
| Per-node overhead | Low share, since agents are spread over more capacity | Higher share, because every node runs its own agents |
| Fitting big pods | Easy | Hard; a big pod may fit nowhere |
| Packing efficiency | Leftover gaps are larger | Leftover gaps are smaller |
| Pod count limit | May hit the 110 pod limit before using all CPU | Rarely an issue |
| Management effort | Fewer machines to maintain | More machines to maintain, usually automated |
Many teams choose medium-sized nodes and spread them over at least three availability zones. That keeps the blast radius acceptable, leaves room for larger pods, and avoids managing hundreds of tiny machines.
12Security on the Node
A node holds real credentials, real data, and a shared kernel. Protecting it protects everything on it.
A node is only as safe as the weakest workload running on it.
Lock the kubelet API
The kubelet’s port accepts powerful commands. Turn off anonymous access, require authentication, and check every request against the API server’s rules. Keep the old read-only port closed.
Node authorizer
A special rule set ensures a kubelet may only read and change objects related to its own node. The NodeRestriction check stops a hijacked node from tampering with other nodes.
Automatic rotation
A kubelet proves who it is with a certificate that expires. Enabling rotation renews it automatically, so a stolen certificate has a short useful life.
Least privilege
Run containers as a non-root user, drop unneeded Linux powers, use the runtime’s default seccomp profile, and avoid privileged containers and host paths.
Minimal and hardened
Container-focused systems such as Bottlerocket, Flatcar, and Talos ship with only what nodes need, giving attackers less to work with.
Patch by replacing
Instead of patching machines in place, build a fresh image and roll nodes onto it. Every node then matches a known, tested state.
Every cloud VM can ask a local metadata service for temporary credentials belonging to the machine’s role. A compromised pod might do the same and gain the power of the whole node. On AWS, require the newer IMDSv2 with a hop limit of one, and give pods their own narrow identities through IAM Roles for Service Accounts or EKS Pod Identity.
Network rules matter too. By default, any pod can talk to any other pod. NetworkPolicy objects, enforced by the CNI plugin on each node, let you say which pods may talk to which, so that a breach in one place cannot spread freely. Finally, remember the shared-kernel point from Chapter 5: for code you do not trust, use a sandboxed runtime or put it on its own dedicated nodes.
13Monitoring, Logging, and Metrics
You cannot fix what you cannot see. Nodes generate a steady stream of signals, and reading them early prevents late-night surprises.
metrics-server
Collects current CPU and memory figures from every kubelet. It powers commands such as “top” and feeds autoscalers.
node-exporter
A popular Prometheus agent that reports detailed operating-system numbers, including disk, network, and load.
kube-state-metrics
Turns Kubernetes objects into numbers, for example how many pods are Pending or which nodes are NotReady.
cAdvisor
Already inside the kubelet; supplies per-container usage data to the tools above.
node-problem-detector
Watches the kernel log and system services for trouble such as disk errors and reports them as node conditions.
Log agents
Tools like Fluent Bit run on every node as a DaemonSet and ship container logs to a central place.
What to watch
| Signal | Why it matters | Warning sign |
|---|---|---|
| CPU usage and throttling | Slow apps often mean throttled containers | Usage near allocatable, high throttled time |
| Available memory | Running out triggers evictions and OOM kills | Approaching the eviction threshold |
| Disk space and inodes | Images and logs fill disks silently | DiskPressure turns true |
| Node Ready status | Shows whether the node is usable | Flapping between Ready and NotReady |
| Pod count per node | There is a fixed slot limit | Pods Pending with “too many pods” |
| Pod start time | Reveals slow image pulls or runtime trouble | Long ContainerCreating periods |
Container logs live as files on the node itself, under the /var/log/pods folder, and the kubelet rotates them, by default at 10 MiB per file with five files kept. That means logs vanish when a node is replaced. This is exactly why a log agent should copy them off the machine continuously. Alert on symptoms that affect users, such as rising error rates, and use node metrics to explain the cause.
14Design Patterns and Anti-patterns
Teams that run nodes well tend to repeat the same habits. Teams that struggle tend to repeat the same mistakes.
Patterns that work
Node pools by workload
Group similar machines together, for example general, memory-heavy, GPU, and spot pools, and use taints and labels to guide pods to the right pool.
Spread across zones
Place nodes in several availability zones and ask the scheduler to spread copies of each app, so losing one data center does not take the service down.
Immutable, replaceable nodes
Never repair a node by hand. Replace it with a fresh one built from the same tested image.
DaemonSet helpers
Run one copy of logging, monitoring, or security agents on every node using a DaemonSet, which automatically covers new nodes as they join.
Node autoscaling
Let tools such as Cluster Autoscaler or Karpenter add nodes when pods cannot be scheduled and remove nodes that sit mostly empty.
Anti-patterns to avoid
What people do
They log in to a misbehaving node over SSH and change settings, install tools, or restart services by hand.
Why it hurts
Each node slowly becomes different from the rest. Nobody remembers what was changed, and the fix disappears when the node is replaced.
Do this instead
Fix the node image or configuration in one place, then roll fresh nodes out. Use debugging tools that attach to a node temporarily without leaving lasting changes.
What people do
They deploy pods with no CPU or memory requests and limits.
Why it hurts
The scheduler is flying blind and overpacks nodes. When load rises, pods fight for memory and important ones get killed.
Do this instead
Measure real usage, set sensible requests and limits, and use namespace-level defaults so nothing slips through.
What people do
They run production on one or two large nodes in a single zone to save money.
Why it hurts
One failure, or one routine upgrade, removes most of the capacity at once, and there is nowhere for pods to go.
Do this instead
Use at least three nodes across at least two or three zones, with enough spare room to absorb the loss of one.
15Best Practices and Common Mistakes
A short checklist you can apply to almost any cluster, followed by the traps that catch newcomers most often.
Best practices
Set requests and limits everywhere
They are the information the scheduler and the kubelet need to protect your nodes.
Reserve room for the system
Configure kube-reserved and system-reserved so the operating system and agents never starve.
Keep versions in step
A kubelet must never be newer than the API server, and it may lag by at most three minor versions in current releases. Upgrade the control plane first, then the nodes in small batches.
Protect apps during maintenance
Use PodDisruptionBudgets and enough replicas so a drain never removes every copy.
Automate node lifecycle
Use managed node groups or an autoscaler so machines are created, replaced, and removed without manual work.
Ship logs and metrics off the node
Anything stored only on a node disappears with it.
Common mistakes
Ignoring disk usage
Old images and busy logs fill the disk, DiskPressure appears, and pods are evicted. Set image garbage collection and log rotation.
Confusing limits with requests
Setting only a limit does not reserve capacity for scheduling purposes in the way many people expect. Set both deliberately.
Draining without a budget
A drain with no PodDisruptionBudget and a single replica creates an outage on purpose.
Treating nodes as pets
Giving machines names, hand-tuning them, and fearing their replacement makes every failure a crisis.
16Real-World and Industry Examples
These stories show how the ideas in this guide look at large scale.
OpenAI: thousands of GPU nodes in one cluster
OpenAI has publicly described running a single Kubernetes cluster of about 7,500 nodes to train large machine-learning models. At that size, details such as API server load, network design, and how quickly nodes can pull images become serious engineering topics. It is a good reminder that the 5,000-node guideline is a tested target rather than a hard wall.
Niantic and Pokémon GO: growth that outran the plan
When Pokémon GO launched in 2016, its backend ran on Google Kubernetes Engine. Player demand was many times higher than the team had planned for. Because capacity is just a matter of adding nodes to a cluster, the team could keep growing the fleet while the game stayed online.
Spotify: moving to a shared platform
Spotify moved its microservices from an in-house orchestrator called Helios to Kubernetes. A common pool of nodes gave many teams the same way to deploy, monitor, and scale, instead of every team managing its own servers.
Managed platforms: nodes as a service
Amazon EKS, Google GKE, and Azure AKS run the control plane for you and offer managed node groups that handle creation, health checks, and upgrades. Google has documented GKE clusters supporting up to 15,000 nodes. Options such as AWS Fargate and GKE Autopilot go one step further and hide node management almost entirely, though machines still exist underneath.
17Frequently Asked Questions
18Summary and Key Takeaways
Key Takeaways
- A node is a machine, physical or virtual, that runs your pods. A worker node is one that runs applications, while control plane nodes manage the cluster.
- Three agents make a node useful: the kubelet follows instructions and reports health, the container runtime starts containers, and kube-proxy makes Services reachable.
- Networking and storage come from plugins: the CNI plugin gives each pod an address, and the CSI plugin provides its volumes.
- Capacity is not allocatable. Reserve room for the system, and always set requests and limits so scheduling and eviction behave predictably.
- Failure is normal. Heartbeats, conditions, taints, and eviction let the cluster detect a lost node and reschedule its pods automatically.
- Steer and protect with the toolbox: labels, taints, tolerations, cordon, drain, and PodDisruptionBudgets control where pods run and keep maintenance safe.
- Treat nodes as replaceable. Harden them, monitor them, spread them across zones, and fix problems by replacing machines rather than repairing them by hand.