KubernetesXXXI · Node LifecycleNode lifecycle
Node conditions — Ready, MemoryPressure, DiskPressure, PIDPressure
What you'll learn
- Identify the five canonical Node conditions
- Trace the kubelet's role and the node controller's role in setting conditions
- Apply the operational patterns for alerting on conditions
- Diagnose a node in a non-Ready state
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
The Node object’s Status.Conditions is the cluster’s
view of a node’s health. There are five canonical
conditions: Ready, MemoryPressure, DiskPressure,
PIDPressure, and NetworkUnavailable. Each has a
status (True, False, or Unknown), a reason, and a
message. This lesson walks the conditions, the
observers that set them, and the operational patterns.
The five canonical conditions
stateDiagram-v2
[*] --> Ready: kubelet registered
Ready --> NotReady: kubelet fails
NotReady --> Ready: kubelet recovers
Ready --> Unknown: lease stale
Unknown --> Ready: lease renewed
Note right of Ready: MemoryPressure = False
Note right of NotReady: MemoryPressure = False
Note right of Unknown: conditions unclear
The conditions:
# Substitute your own value before running:
NODE=worker-03
kubectl describe node "$NODE" | grep -A 10 "Conditions"
Conditions:
Type Status LastHeartbeatTime Reason
---- ------ ----------------- ------
Ready True 2026-08-16T10:00:00Z KubeletReady
MemoryPressure False 2026-08-16T10:00:00Z KubeletHasInsufficientMemory
DiskPressure False 2026-08-16T10:00:00Z KubeletHasNoDiskSpace
PIDPressure False 2026-08-16T10:00:00Z KubeletHasInsufficientPID
NetworkUnavailable False 2026-08-16T10:00:00Z KubeletReady
The conditions:
| Condition | True means | False means |
|---|---|---|
Ready | Node is healthy and serving | Node is unhealthy or unreachable |
MemoryPressure | Memory is under pressure | Memory is fine |
DiskPressure | Disk is under pressure | Disk is fine |
PIDPressure | PIDs are under pressure | PIDs are fine |
NetworkUnavailable | Network is not configured | Network is configured |
The Ready condition is the primary signal. The other
four are negative signals: True means there is a
problem; False means there is no problem.
The Ready condition
The Ready condition is set by the kubelet (when the
kubelet is healthy) and by the node controller (when the
kubelet is unreachable).
The kubelet’s Ready:
NodeCondition {
type: "Ready",
status: "True",
reason: "KubeletReady",
message: "kubelet is posting ready status"
}
The kubelet updates the Ready condition every 10
seconds. The kubelet reports True when the runtime,
the CNI, and the local services are healthy.
The node controller’s Ready:
NodeCondition {
type: "Ready",
status: "False",
reason: "NodeStatusNeverUpdated",
message: "kubelet has not reported ready status for 5m"
}
The node controller sets Ready=False when the
kubelet’s lease is not renewed for the configured grace
period. The controller’s Ready overrides the
kubelet’s.
The cluster’s view of Ready is the most recent update.
A kubelet that is healthy but whose lease is stale is
Ready=False according to the node controller.
The MemoryPressure condition
The MemoryPressure condition is set by the kubelet. The
kubelet checks the memory pressure periodically; if the
kernel reports memory pressure (via the memory pressure
threshold or the PSI metrics), the kubelet sets
MemoryPressure=True.
The kubelet’s MemoryPressure:
NodeCondition {
type: "MemoryPressure",
status: "True",
reason: "KubeletHasInsufficientMemory",
message: "kubelet has memory pressure"
}
MemoryPressure=True triggers the kubelet’s memory
eviction loop. The kubelet evicts Pods based on the
Pod’s QoS class and the resource requests.
The MemoryPressure condition is a signal that the
node is under memory pressure. The fix is to:
- Add capacity.
- Reduce the Pod’s memory requests.
- Investigate the memory leak.
The DiskPressure condition
The DiskPressure condition is set by the kubelet. The
kubelet checks the disk usage; if the usage exceeds the
threshold (default 85% of the filesystem), the kubelet
sets DiskPressure=True.
The kubelet’s DiskPressure:
NodeCondition {
type: "DiskPressure",
status: "True",
reason: "KubeletHasNoDiskSpace",
message: "kubelet has disk pressure"
}
DiskPressure=True triggers the kubelet’s disk eviction
loop. The kubelet evicts Pods based on the Pod’s
ephemeral-storage usage.
The DiskPressure condition is a signal that the
node’s filesystem is filling. The fix is to:
- Clean up the image cache.
- Clean up the container logs.
- Add disk capacity.
The PIDPressure condition
The PIDPressure condition is set by the kubelet. The
kubelet checks the PID usage; if the ratio exceeds the
threshold (default 0.5 of pid_max), the kubelet sets
PIDPressure=True.
The kubelet’s PIDPressure:
NodeCondition {
type: "PIDPressure",
status: "True",
reason: "KubeletHasInsufficientPID",
message: "kubelet has insufficient PID"
}
PIDPressure=True triggers the kubelet’s PID eviction
loop. The kubelet evicts Pods based on the Pod’s PID
usage.
The PIDPressure condition is a signal that the node
is exhausting the PID space. The fix is to:
- Investigate the process that is consuming the PIDs.
- Increase the kernel’s
pid_max. - Reduce the Pod’s process count.
The NetworkUnavailable condition
The NetworkUnavailable condition is set by the node
controller. The condition is True when the CNI has
not yet configured the node.
The node controller’s NetworkUnavailable:
NodeCondition {
type: "NetworkUnavailable",
status: "True",
reason: "NoRouteCreated",
message: "node has no routes to Pods"
}
The condition is set to False when the CNI agent
reports ready via the node-status update. The
NetworkUnavailable=True is rare in production; it
indicates a CNI failure.
The NetworkUnavailable condition is a signal that the
node has no network connectivity. The fix is to:
- Investigate the CNI plugin.
- Investigate the network on the node.
- Restart the CNI agent.
The condition transitions
The kubelet transitions the conditions based on the
local state. The transition is recorded in the
lastTransitionTime field:
NodeCondition {
type: "Ready",
status: "True",
lastTransitionTime: "2026-08-16T09:00:00Z",
reason: "KubeletReady"
}
The cluster’s kube_node_status_condition metric
records the condition’s status. The lastTransitionTime
is the time of the most recent transition.
The cluster’s controllers react to the transitions:
Ready=False→ node controller adds thenot-readyNoExecute taint.MemoryPressure=True→ kubelet evicts Pods.DiskPressure=True→ kubelet evicts Pods.PIDPressure=True→ kubelet evicts Pods.NetworkUnavailable=False→ node controller removes theNetworkUnavailabletaint.
The condition’s reason field
The reason field is a short string that explains the
condition. The standard reasons:
| Condition | Reason (kubelet) | Reason (node controller) |
|---|---|---|
Ready | KubeletReady | NodeStatusNeverUpdated, NodeStatusUpdated |
MemoryPressure | KubeletHasInsufficientMemory | (not set) |
DiskPressure | KubeletHasNoDiskSpace | (not set) |
PIDPressure | KubeletHasInsufficientPID | (not set) |
NetworkUnavailable | (not set) | NoRouteCreated, RouteCreated |
The reason is the operator’s quick way to identify the cause. The cluster’s events complement the reason with the full message.
The alert thresholds
The cluster’s alerts should be based on the conditions:
# Alert: node is not Ready for more than 5 minutes
- alert: NodeNotReady
expr: kube_node_status_condition{condition="Ready",status="true"} == 0
for: 5m
labels:
severity: critical
# Alert: node memory pressure
- alert: NodeMemoryPressure
expr: kube_node_status_condition{condition="MemoryPressure",status="true"} == 1
for: 5m
labels:
severity: warning
# Alert: node disk pressure
- alert: NodeDiskPressure
expr: kube_node_status_condition{condition="DiskPressure",status="true"} == 1
for: 5m
labels:
severity: warning
# Alert: node PID pressure
- alert: NodePIDPressure
expr: kube_node_status_condition{condition="PIDPressure",status="true"} == 1
for: 5m
labels:
severity: warning
The for duration gives the cluster time to recover the
node. The 5-minute threshold is a balance; lower
thresholds produce more false positives, higher
thresholds delay the alert.
Quiz
Knowledge check · 4 questions
Q1. Which Node condition does the node controller own rather than the kubelet?
Q2. `Ready=False` and `Ready=Unknown` describe the same situation from different components.
Q3. Identify which component owns a node condition that is blocking Pod startup after a networking change.
After rolling a new CNI DaemonSet version, 3 of 40 nodes show `NetworkUnavailable True` with reason `NoRouteCreated` while `Ready` is still `True` on all three. Pods scheduled to those nodes sit in `ContainerCreating`. `kubectl describe node node-17` shows `MemoryPressure False`, `DiskPressure False`, `PIDPressure False`, and a `node.kubernetes.io/network-unavailable:NoSchedule` taint. The CNI Pod on each of the three nodes is `Running` but its readiness probe is failing.
Q4. Of the five canonical Node conditions, which does the kubelet set and which does the node controller set, and what does `status: "False"` mean on the four non-Ready conditions?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- The
Readycondition is the primary signal. The cluster’s controllers react toReady=False. The operator should alert onReady=Falsefor more than 5 minutes. - The pressure conditions are warnings. The
MemoryPressure,DiskPressure, andPIDPressureconditions are warnings that the node is under pressure. The operator should investigate the cause. - The
NetworkUnavailablecondition is a signal of CNI failure. The condition is set by the node controller; the fix is to investigate the CNI. - Audit the conditions at every node repave. A new
node that joins the cluster with a
Ready=Falsecondition is a node that is failing silently. The audit catches the failure. - The
reasonfield is the cause. The reason identifies the condition’s cause. The operator should read the reason first. - The
lastTransitionTimeis the timing. The transition time is the time of the most recent change. The operator should review the transition history.