KubernetesXXXI · Node LifecycleNode lifecycle
Unknown and NotReady nodes — partial observability
What you'll learn
- Distinguish the Unknown state from the NotReady state
- Trace the node controller's transitions for each state
- Diagnose a node that is in the Unknown state
- Recover a node that is in the NotReady 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 has a Ready condition that resolves to
True, False, or Unknown. The False state is NotReady;
the Unknown state is Unknown. The two states have
different diagnostics; the two states have different
recoveries. This lesson walks the states, the
controller’s transitions, and the operational patterns.
The Ready condition states
The Ready condition is a tri-state:
| Status | Meaning | Set by |
|---|---|---|
True | Node is healthy | kubelet |
False | Node is unhealthy | kubelet (rare), node controller |
Unknown | Node is unreachable | node controller |
The True and False states are set by the kubelet.
The Unknown state is set by the node controller when
the controller cannot reach the kubelet.
The cluster’s components react to the Ready status.
A Pod’s spec.nodeName is the node the Pod is running
on; the Pod’s status is the cluster’s view of the Pod.
The NotReady state
The NotReady state (Ready=False) is set by the
kubelet when the kubelet detects a problem. The kubelet
reports:
NodeCondition {
type: "Ready",
status: "False",
reason: "KubeletNotReady",
message: "kubelet is not posting ready status"
}
A node in NotReady is a node whose kubelet is running
but is reporting a problem. The kubelet’s status update
is still being delivered to the API server.
The diagnostic:
# Substitute your own value before running:
NODE=worker-03.example.com
kubectl describe node "$NODE"
The events on the node indicate the failure. The fix is to investigate the kubelet’s logs and the node’s local state.
The recovery:
journalctl -u kubelet | tail -50
The kubelet’s logs show the failure. The fix is to restart the kubelet or to fix the underlying problem.
The Unknown state
The Unknown state (Ready=Unknown) is set by the node
controller when the Lease is not renewed for the grace
period. The controller’s report:
NodeCondition {
type: "Ready",
status: "Unknown",
reason: "NodeStatusNeverUpdated",
message: "kubelet has not reported ready status for 5m"
}
A node in Unknown is a node whose kubelet is not
reachable. The kubelet may be down, the network may be
partitioned, or the kubelet’s process may have crashed.
The diagnostic:
# Substitute your own value before running:
NODE=worker-03.example.com
kubectl get lease -n kube-node-lease "$NODE" -o yaml
The renewTime shows the last renewal. A renewTime
that is older than the grace period is a stale Lease.
The recovery:
- Check the node’s network. The kubelet may be unreachable because of a network partition.
- Check the kubelet’s process. The kubelet may have crashed.
- Restart the kubelet.
systemctl restart kubelet. - Wait for the kubelet to recover. The kubelet
updates the Lease; the node controller removes the
Unknownstate.
The transitions
The cluster’s transitions for the Ready condition:
stateDiagram-v2
[*] --> Ready: kubelet registered
Ready --> NotReady: kubelet fails
NotReady --> Ready: kubelet recovers
Ready --> Unknown: lease stale
Unknown --> Ready: lease renewed
Unknown --> NotReady: kubelet reports NotReady
NotReady --> Unknown: lease stale
The transitions are:
Ready→NotReady: the kubelet reports a problem.NotReady→Ready: the kubelet recovers.Ready→Unknown: the Lease is stale.Unknown→Ready: the Lease is renewed.Unknown→NotReady: the kubelet reports a problem (concurrency).NotReady→Unknown: the kubelet stops reporting (concurrency).
The most common transition is Ready → NotReady →
Ready (a transient kubelet failure). The Unknown
state is rare; it indicates a more severe problem.
The cluster’s view of the Pods
The cluster’s view of the Pods on a NotReady or Unknown node is the same as the cluster’s view of the Pods on a Ready node until the eviction timeout. The Pods are still running; the cluster’s services do not route to them (because the node is NotReady).
# Substitute your own value before running:
NODE=worker-03.example.com
kubectl get pods -o wide | grep "$NODE"
The Pods are listed as Running (until the eviction
timeout). The cluster’s controllers do not consider the
Pods as failed until the eviction timeout.
The Pod’s eviction
The Pod’s eviction is performed by the cluster’s
eviction logic. The eviction is triggered when the
Pod’s spec.nodeName is on a NotReady node for longer
than the eviction timeout.
The eviction timeout is the time the Pod is allowed to be on a NotReady node before eviction. The default is 5 minutes.
The eviction is performed by the Pod’s controller (the Deployment, StatefulSet, etc.). The controller creates a replacement Pod; the replacement Pod is scheduled by the scheduler.
The Pod’s eviction is destructive. The Pod’s state is lost. The Pod’s volume is preserved (the PVC is still bound).
The diagnostic workflow
The diagnostic workflow for a NotReady or Unknown node:
flowchart TD
A[Node NotReady or Unknown] --> B[Read events]
B --> C[Read kubelet logs]
C --> D[Check Lease]
D --> E{Lease stale?}
E -->|Yes| F[Read kubelet process]
E -->|No| G[Read node conditions]
F --> H[Restart kubelet]
G --> I[Investigate conditions]
The workflow:
- Read the node’s events. The events indicate the failure.
- Read the kubelet’s logs. The log shows the local failure.
- Check the Lease. The Lease’s
renewTimeis the last heartbeat. - Read the node’s conditions. The conditions indicate the failure type.
- Restart the kubelet. If the kubelet is failing, the restart may recover the node.
The recovery
The recovery for a NotReady node:
- Identify the failure. The kubelet’s logs show the cause.
- Fix the underlying problem. Restart the failing service, free the disk, or address the resource pressure.
- Restart the kubelet.
systemctl restart kubelet. - Wait for the node to be Ready. The kubelet
reports
Ready=True.
The recovery for an Unknown node:
- Identify the network failure. The kubelet may be unreachable because of a network partition.
- Restore the network. The fix is to restore the network on the node.
- Restart the kubelet. A kubelet that lost its API server connection re-registers and renews the Lease on start.
- Wait for the kubelet to renew the Lease. The
node controller removes the
Unknownstate.
Quiz
Knowledge check · 4 questions
Q1. Pods on a node in `Ready=Unknown` are still shown as Running. Are they?
Q2. For a workload that must never run twice, the cluster's automatic rescheduling from an unreachable node is sufficient protection.
Q3. Recover a StatefulSet whose Pods will not be recreated after an availability-zone network partition.
A network partition isolated one availability zone for 12 minutes. Eight nodes went to `Ready Unknown` with reason `NodeStatusUnknown`. The Deployment workloads recovered on other nodes within 6 minutes. The StatefulSet `postgres` in namespace `data` still shows `postgres-1 1/1 Running 0 9d` on the isolated `node-31`, and no replacement Pod exists 25 minutes later. `kubectl get lease -n kube-node-lease node-31` shows a `renewTime` from 25 minutes ago.
Q4. What is the operational difference between a node reporting `Ready=False` and one showing `Ready=Unknown`, and what is the first piece of evidence you check for each?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- A NotReady node is a node whose kubelet is failing. The diagnostic is the kubelet’s logs.
- An Unknown node is a node whose Lease is stale.
The diagnostic is the Lease’s
renewTime. - The cluster’s view of the Pods is the same as before the failure. The Pods are still running until the eviction timeout.
- The Pod’s eviction is destructive. The Pod’s state is lost. The Pod’s volume is preserved.
- Monitor the Ready condition. The cluster’s alerts
should fire on
Ready=Falsefor more than 5 minutes. - Audit the recovery at every node repave. A new node that joins the cluster with the wrong configuration is a node that is failing silently. The audit catches the failure.
- Test the kubelet’s restart in non-production. A kubelet that does not recover from a restart is a kubelet that is failing silently.