KubernetesIX · Pod LifecyclePod lifecycle
Pod conditions — PodScheduled, Initialized, ContainersReady, Ready
What you'll learn
- Identify the standard Pod condition types and what each means
- Read conditions for fine-grained diagnosis (scheduled but not ready, ready but not initialised)
- Use conditions to distinguish issues that phase alone cannot
- Set up alerts based on specific conditions
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
status.phase is a single string; containerStatuses[*].state
is per-container. status.conditions is a list of typed
conditions that together describe the Pod’s state at a finer
grain than phase but broader than per-container. This lesson
covers the standard condition types and the diagnostic
patterns they enable.
The standard condition types
status:
conditions:
- type: PodScheduled
status: "True"
lastTransitionTime: "2026-08-16T12:00:00Z"
- type: Initialized
status: "True"
lastTransitionTime: "2026-08-16T12:00:05Z"
- type: ContainersReady
status: "True"
lastTransitionTime: "2026-08-16T12:01:00Z"
- type: Ready
status: "True"
lastTransitionTime: "2026-08-16T12:01:01Z"
The five standard types:
| Type | Meaning |
|---|---|
PodScheduled | The scheduler has bound the Pod to a node |
Initialized | All init containers have completed successfully |
ContainersReady | All containers are ready (readiness probes passed) |
Ready | The Pod is ready to serve traffic (Initialized + ContainersReady) |
DisruptionTarget | The Pod is being disrupted (drain, eviction, deletion) |
Each condition has:
type: the condition name (from the list above or a custom type).status:True,False, orUnknown.lastTransitionTime: when the status last changed.reason: a programmatic reason string (optional).message: a human-readable description (optional).
flowchart TD
Start[Pod created] --> Sched[PodScheduled=True]
Sched --> Init[Initialized=True]
Init --> ContReady[ContainersReady=True]
ContReady --> Ready[Ready=True]
Ready --> Traffic[Service routes traffic]
The Ready condition is the union of Initialized and ContainersReady. When a Pod is Ready, a Service’s Endpoints list includes it. When Ready is False or Unknown, the Pod is excluded.
PodScheduled — has the scheduler chosen a node?
- type: PodScheduled
status: "False"
reason: "SchedulingGated"
message: "Pod is waiting for scheduling gate to clear"
PodScheduled=False is the diagnostic key for “the Pod has
not been bound to a node yet.” Common reasons:
Unschedulable: no node fits the Pod’s constraints. Check the events forFailedScheduling.SchedulingGated: a scheduling gate is blocking the Pod. Scheduling gates are an opt-in feature where a Pod has a list of gate names that must all be cleared before the scheduler considers it. ThePodSchedulingReadinessfeature gate and thespec.schedulingGatesfield.Reason: "Unknown": the API server cannot determine scheduling state; rare.
PodScheduled=True does not mean the Pod is running; it
means the scheduler has assigned a node. The kubelet on that
node still needs to pull images, create the sandbox, and
start the containers.
Initialized — have the init containers finished?
- type: Initialized
status: "True"
lastTransitionTime: "2026-08-16T12:00:05Z"
Initialized=True means all init containers have completed
successfully. Init containers run sequentially; each must
succeed before the next starts. When the last init container
exits 0, Initialized transitions to True.
Initialized=False means at least one init container has
not completed. Common reasons:
- The init container is still running (check
initContainerStatuses[*].state). - The init container failed (check events for
Failed). - The init container is in ImagePullBackOff.
Part XI covers init containers in depth.
ContainersReady — are all containers ready?
- type: ContainersReady
status: "True"
ContainersReady=True means every container’s readiness
probe has succeeded at least once. If any container’s
readiness probe fails or has never succeeded, ContainersReady
is False.
For a Pod with one container, ContainersReady is the container’s ready state. For multi-container Pods, all must be ready.
Ready — the Pod is serving traffic
- type: Ready
status: "True"
Ready=True is the union of Initialized + ContainersReady.
It is the condition the Service’s Endpoints controller uses
to decide whether to add the Pod’s IP to the Endpoints list.
The Pod is excluded from Endpoints when Ready is False or Unknown. This is what implements “no traffic to a Pod that isn’t ready.”
DisruptionTarget — the Pod is being disrupted
- type: DisruptionTarget
status: "True"
reason: "DeletionByKubelet"
message: "Pod is being deleted due to node drain"
DisruptionTarget=True means the Pod is being evicted or
deleted. Common reasons:
DeletionByKubelet: node drain or manual deletion.EvictionByKubelet: kubelet-initiated eviction (memory pressure, disk pressure).PreemptionByScheduler: scheduler preempted the Pod for a higher-priority Pod.
The DisruptionTarget condition is the signal that the Pod is on its way out. Production discipline: respect this condition in your application — start graceful shutdown when you see it.
Reading conditions
kubectl get pod web-7c8 -o jsonpath='
{range .status.conditions[*]}
{.type}={.status}{" reason="}{.reason}{" message="}{.message}{"\n"}
{end}'
Output:
PodScheduled=True
Initialized=True
ContainersReady=False reason="containers with unready status: [nginx]"
Ready=False
DisruptionTarget=False
This Pod is scheduled, initialised, but the nginx container is not ready. The Ready condition is False as a consequence.
Conditions vs phase vs container state
Three layers of state. Use them together:
| Question | Field |
|---|---|
| Where is the Pod in its lifecycle? (coarse) | status.phase |
| Is each container running, waiting, or terminated? | containerStatuses[*].state |
| Is the Pod scheduled, initialised, ready? | status.conditions |
| Are init containers finished? | status.conditions[].type=Initialized |
| Is the Pod about to be deleted? | status.conditions[].type=DisruptionTarget |
Production discipline: read all three. The phase is the first filter; the conditions narrow down to a specific subsystem; the container states give the per-container truth.
Alerting on conditions
A common Prometheus alert pattern uses kube-state-metrics:
# Pods that are not Ready for more than 5 minutes
kube_pod_status_ready{namespace="prod"} == 0
The kube_pod_status_ready metric exposes the Ready condition
status. An alert with for: 5m catches sustained
not-ready Pods.
- alert: PodNotReady
expr: kube_pod_status_ready{namespace="prod"} == 0
for: 5m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is not ready"
The alert fires on Pods whose Ready condition is False or Unknown for 5 minutes. Transient rollout downtime does not trigger it; sustained readiness issues do.
Cross-course references
- The Linux course part
VI-Linux-Processescovers process states and signal handling; Pod conditions are the cluster-level equivalent. - The Ansible course part
XXXV-Ansible-Scriptingcovers service health states; conditions are the cluster-level equivalent for containerised services. - The Observability course part
LXXXV-Kubernetes-Observabilitycovers kube-state-metrics and the conditions-to-metrics pipeline.
Quiz
Knowledge check · 4 questions
Q1. Which condition type determines whether a Pod is included in a Service's Endpoints list?
Q2. `status.conditions` and `status.phase` are redundant — both report the same state in different forms.
Q3. A Pod is in `Running` phase but has `Ready=False`. Walk through the diagnosis using conditions.
Pod `web-7c8` is in Running phase. `kubectl get pod web-7c8 -o jsonpath='{.status.conditions}'` shows: `PodScheduled=True`, `Initialized=True`, `ContainersReady=False`, `Ready=False`. The readiness probe is `httpGet /healthz on port 8080`.
Q4. What does the DisruptionTarget condition indicate, and how should an application respond to it?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Use conditions for fine-grained triage. Phase is the first filter; conditions narrow the diagnosis.
- Alert on
Ready=Falsesustained. A 5-minutefor:clause catches readiness issues without false positives on rollouts. - Respect DisruptionTarget in application code. Treat it as an early shutdown signal; start draining before SIGTERM arrives.
- Distinguish ContainersReady from Ready. ContainersReady is per-container; Ready is the union with Initialized. Endpoints use Ready.
- Read conditions before reading events. Conditions are declarative (current state); events are a stream of what happened. Use both, but conditions are faster.