Skip to main content
RunBook Academy

KubernetesIX · Pod LifecyclePod lifecycle

Pod conditions — PodScheduled, Initialized, ContainersReady, Ready

Intermediate⏱ ~16 minkubectl

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

Not yet marked complete on this device.

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:

TypeMeaning
PodScheduledThe scheduler has bound the Pod to a node
InitializedAll init containers have completed successfully
ContainersReadyAll containers are ready (readiness probes passed)
ReadyThe Pod is ready to serve traffic (Initialized + ContainersReady)
DisruptionTargetThe 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, or Unknown.
  • 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 for FailedScheduling.
  • 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. The PodSchedulingReadiness feature gate and the spec.schedulingGates field.
  • 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:

QuestionField
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-Processes covers process states and signal handling; Pod conditions are the cluster-level equivalent.
  • The Ansible course part XXXV-Ansible-Scripting covers service health states; conditions are the cluster-level equivalent for containerised services.
  • The Observability course part LXXXV-Kubernetes-Observability covers kube-state-metrics and the conditions-to-metrics pipeline.

Quiz

Knowledge check · 4 questions

  1. Q1. Which condition type determines whether a Pod is included in a Service's Endpoints list?

  2. Q2. `status.conditions` and `status.phase` are redundant — both report the same state in different forms.

  3. 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`.

  4. 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=False sustained. A 5-minute for: 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.