KubernetesIV · Desired State and ReconciliationDesired state and reconciliation
Convergence — when does the system stabilise?
What you'll learn
- Define convergence and distinguish steady state from transient state
- Identify the grace periods that Kubernetes uses to dampen flapping
- Explain partial convergence and how it differs from full convergence
- Recognise non-convergent patterns and the production responses to them
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
Convergence is the property that distinguishes a working Kubernetes system from a broken one. A controller is convergent if repeated reconciliation eventually drives observed state to match desired state. This lesson covers what convergence looks like, what blocks it, and how to recognise when a system is partially or fully converged.
Convergence in one sentence
A Kubernetes system converges when the controllers’ repeated reconciliation drives the observed state of every object to match its desired state, and the system is at steady state.
stateDiagram-v2
[*] --> Transient
Transient --> Transient: diff != 0, retrying
Transient --> Steady: diff == 0
Steady --> Transient: spec changes
Steady --> [*]
The system is rarely at steady state — every spec change re-enters transient state until reconciliation closes the gap.
Steady state vs transient state
Steady state: every object’s status matches its spec
(as expressed by the controller’s satisfaction criteria). No
reconcile loop has a pending action.
Transient state: a spec change has occurred (or a node has
been lost, or a Pod has been rescheduled); reconcile loops are
running; some objects have a gap between spec and status.
The transient-to-steady transition is what Kubernetes calls convergence. The controller’s job is to make this transition as fast as possible (usually seconds) and as predictable as possible.
# Check a Deployment's convergence
kubectl rollout status deployment/web
deployment "web" successfully rolled out
The rollout status command polls until the controller’s
status.conditions reach the steady-state criteria.
What blocks convergence
A system fails to converge when:
- The desired state is unachievable —
replicas: 100on a 5-node cluster withrequests.cpu: 16per Pod - The desired state is inconsistent —
replicas: 5with a PodDisruptionBudget ofminAvailable: 10 - A dependency is broken — PVC Pending, ImagePullBackOff, Service has no Endpoints
- The controller is stalled — leader election lost, controller-manager OOMKilled
- The actions are non-idempotent — the controller’s acts have side effects that prevent convergence
A non-convergent system produces a gap that does not close.
The Pod events, the controller’s status.conditions, and the
workqueue metrics all show the same pattern.
Partial convergence
A system can be partially converged — some objects at steady state, others in transient. Production examples:
flowchart LR
A[Deployment A: 5/5 ready, converged]
B[Deployment B: 3/5 ready, gap=2]
C[StatefulSet C: 1/3 ready, PVC Pending]
D[DaemonSet D: 5/5 nodes, converged]
A --> OK[Steady]
B --> T[Transient<br/>2 missing]
C --> T2[Transient<br/>2 missing + PVC]
D --> OK
In the diagram, Deployment A and DaemonSet D are converged; Deployment B has a partial gap; StatefulSet C has a deeper gap (Pods Pending because PVC is Pending).
Partial convergence is normal during rollouts or after a node
loss. It is abnormal when it persists beyond the expected
transient window (a few minutes for typical workloads; longer
for StatefulSets and rollouts with maxUnavailable=0).
Grace periods
Many Kubernetes controllers have grace periods to avoid flapping. These are bounded waits before declaring failure or taking action:
| Grace period | Default | Purpose |
|---|---|---|
terminationGracePeriodSeconds (Pod) | 30s | Wait before SIGKILL after SIGTERM |
--node-monitor-grace-period (Node) | 50s | Wait before marking NotReady |
minReadySeconds (Deployment) | 0s | Wait before considering a Pod ready |
progressDeadlineSeconds (Deployment) | 600s | Wait before declaring rollout failure |
spec.ttlSecondsAfterFinished (Job) | unset | Wait before cleaning up a finished Job |
spec.activeDeadlineSeconds (Job) | unset | Total run time before failing |
Grace periods dampen transient noise at the cost of delaying failure detection. Production tuning is workload-specific:
- Latency-sensitive services: short
minReadySeconds(catch failures fast) - Slow-start services (databases, JVM warm-up): longer
minReadySeconds(avoid flapping) - Stateful workloads: longer
progressDeadlineSeconds(allow for ordered startup)
How to read convergence
For a Deployment
kubectl get deployment web -o jsonpath='{.status}'
{
"observedGeneration": 3,
"replicas": 5,
"updatedReplicas": 5,
"readyReplicas": 5,
"availableReplicas": 5,
"conditions": [
{"type": "Progressing", "status": "True", "reason": "NewReplicaSetAvailable"},
{"type": "Available", "status": "True"}
]
}
Convergence: readyReplicas == replicas and both conditions
True.
For a Node
kubectl get node worker-04 -o jsonpath='{.status.conditions}'
[
{"type": "Ready", "status": "True"},
{"type": "MemoryPressure", "status": "False"},
{"type": "DiskPressure", "status": "False"},
{"type": "PIDPressure", "status": "False"}
]
Convergence: Ready == True and no pressure conditions.
For a StatefulSet
kubectl rollout status statefulset/db
rollout status waits for status.readyReplicas == status.replicas and status.currentRevision == status.updateRevision.
Convergence vs health
Convergence is necessary but not sufficient for health. A system can be technically converged and unhealthy:
flowchart LR
C[Converged<br/>replicas == readyReplicas] --> H{Healthy?}
H -->|probes pass| OK[Healthy]
H -->|probes fail| UH[Unhealthy but converged]
UH --> OBS[Observable<br/>via metrics + logs]
A Pod that passes liveness but has a broken database connection is “ready” by the orchestrator’s standards but unhealthy by the application’s. Production observability must cover both:
- Convergence signal:
spec.replicas == status.readyReplicas - Health signal: probes (liveness, readiness, startup) pass; business KPIs are met
The role of kubectl rollout status
kubectl rollout status is a polling helper. It waits for the
controller to converge according to the controller’s
status criteria.
kubectl rollout status deployment web --timeout=300s
Returns:
0if the rollout converged within the timeout- non-zero if it did not
Useful in CI/CD pipelines as a gate: “is this rollout successful?”. But it does not check health, only convergence.
Patterns of non-convergence
Pattern 1: rollout stuck at progressDeadline
deployment "web" exceeded its progress deadlineSeconds: 600
The Deployment controller has tried for 10 minutes and the new ReplicaSet is not converging. Causes:
- New image fails its readiness probe (the new version is broken)
- New Pods cannot be scheduled (capacity, affinity)
- New Pods are failing their startup (config error)
Pattern 2: StatefulSet waiting for Pod N
statefulset "db" rollout: waiting for statefulset rolling update to complete 1 out of 3 pods...
The StatefulSet is at 1/3. Pod 1 is Pending because Pod 0
is not Ready. Common cause: Pod 0 is failing its readiness
probe (database is not accepting connections yet).
Pattern 3: EndpointSlice empty
A Service with selector: app=web but no Pods match. The
Service has no Endpoints; traffic to the Service ClusterIP is
dropped. The Deployment controller may show the Deployment as
converged (5/5 replicas), but the selector mismatch means the
Service does not see the Pods.
Convergence in custom controllers (Operators)
Custom controllers follow the same convergence rules. The Operator pattern:
- Define a CRD (e.g.,
PostgresCluster) - The Operator controller watches the CRD
- Reconcile: observe CR, diff against spec, create/update resources
Convergence in Operators can be more complex:
- Multiple resources must converge together (PVC, Service, Pod, etc.)
- Application-level state (database replication) is not in Kubernetes
- The Operator must report
status.conditionsaccurately to reflect partial convergence
A well-designed Operator reports status.conditions[].status: False for resources not yet converged, so the operator’s
state reflects reality.
Cross-course references
- The Linux course part
VI-Linux-Processescovers process state transitions; convergence is the cluster’s analogue of process state stability. - The Observability course part
CIX-Observability-InvestigationWorkflowscovers investigation methodology for “is the cluster converged?” questions. - The Docker course part
XXX-Docker-Lifecyclecovers the container lifecycle primitives that drive convergence. - The Linux course part
XXIV-Linux-Timecovers chrony — Node lease convergence depends on clock accuracy.
Quiz
Knowledge check · 4 questions
Q1. A Deployment has `spec.progressDeadlineSeconds: 600` and the rollout has been running for 7 minutes with `readyReplicas: 3` and `spec.replicas: 5`. Is the system converged?
Q2. A Kubernetes system that is converged is necessarily healthy.
Q3. A team deploys a new version of their web app. The Deployment shows `readyReplicas: 5/5` and `status.conditions: Progressing=True, Available=True`. The team's Prometheus alert fires: `up{job="web"} == 0`. The cluster has converged but the application is down. Diagnose and remediate.
Cluster state: ``` $ kubectl get deployment web -n prod -o jsonpath='{.status}' | jq . { "replicas": 5, "readyReplicas": 5, "availableReplicas": 5, "conditions": [ {"type": "Progressing", "status": "True"}, {"type": "Available", "status": "True"} ] } $ kubectl get pods -l app=web -n prod NAME READY STATUS RESTARTS AGE web-abc-1 1/1 Running 0 4m web-abc-2 1/1 Running 0 4m web-abc-3 1/1 Running 0 4m web-abc-4 1/1 Running 0 4m web-abc-5 1/1 Running 0 4m $ promtool query 'up{job="web"}' 0 Application logs: ``` 2026-08-15T12:01:01 request latency p99 = 4500ms (target: 200ms) 2026-08-15T12:01:01 ERROR: cannot connect to database at db.prod.svc:5432: connection refused 2026-08-15T12:01:01 ERROR: cannot connect to cache at redis.prod.svc:6379: timeout ```
Q4. Explain the role of grace periods in Kubernetes convergence. Give two examples and explain the trade-off they make.
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Distinguish convergence from health: a converged cluster can still be unhealthy.
- Monitor
status.conditionsof major objects, not justreplicas. Conditions carry the controller’s assessment. - Set alert thresholds shorter than grace periods so failures are caught before the controller’s deadline expires.
- Use
kubectl rollout statusin CI/CD as a convergence gate; pair it with a health check (Prometheus, business KPI) for full validation. - Recognise partial convergence during rollouts; don’t page on it; do page on persistent gaps.