Git, CI/CD & GitOpsFinal · Final AssessmentFinal Review
GitOps reconciliation and drift — recap
What you'll learn
- State the four GitOps principles and identify which one a given violation breaks
- Trace the reconciliation loop from observed state through diff to apply, for both Argo CD and Flux
- Distinguish the three drift types (manual, accidental, emergency) and match each to a control
- Read the Argo CD and Flux status fields (Synced/Healthy, Ready/Ready) to diagnose a controller failure
- Decide when self-heal helps, when prune is safe, and when a break-glass is the only correct response
Prerequisites
- The GitOps principles — declarative, versioned, pulled, reconciled
- Declarative desired state — describing what should be, not how to get there
- Versioned and immutable — Git as the canonical record of desired state
- Pulled automatically — the controller reaches out to Git
- Continuously reconciled — observed versus desired, and the loop
- The pull model — a controller inside the cluster reaches out to Git
- The reconciliation loop — observed, desired, difference, action
- Observed versus desired — what "actual" and "what should be" mean
- Argo CD reconciliation mechanics — the three components, the cache, the diff
- Flux reconciliation mechanics — GitRepository, Kustomization, the source controller
- What drift is — the actual diverging from the desired
- Drift detection and alerting — what metrics show drift and what the alerts look like
- Argo CD architecture — the three components and the data flow
- The Flux architecture — the toolkit composition and the controller model
- Self-heal — when automatic correction is right and when it is wrong
- What prune is — Git desired state deletes cluster actual
- What Synced means — desired state matches actual state
- What Healthy means — the workload is functioning correctly
- The Synced and Healthy matrix — four combinations
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
GitOps is not a product; it is a set of four properties that any system can implement: the desired state is declarative, the desired state is versioned in Git, the controllers pull the desired state, and reconciliation runs continuously. Get any one of the four wrong and the system is no longer GitOps — it is “configuration in Git” with some pieces missing.
The four principles and what breaks when each one is violated
flowchart TD
A["Desired state"] -->|declarative| B["YAML, manifests, Helm chart"]
B -->|versioned| C["Git commit, signed, immutable ref"]
C -->|pulled| D["Controller reads Git"]
D -->|reconciled| E["Loop: observed = desired"]
style A fill:#dff
style B fill:#dff
style C fill:#dff
style D fill:#dff
- Declarative. The desired state is expressed as
data, not procedure. A
Deploymentmanifest is declarative; a bash script that creates aDeploymentis not. Violation: imperative operators that produce state without leaving a record. - Versioned. The desired state lives in Git, with
every change a commit and a pull request. Violation:
manifests edited in place via
kubectl editor applied from a laptop. - Pulled. The controller in the cluster fetches the
desired state from Git; the deploy system does not push
manifests into the cluster’s API. Violation: CI
systems that
kubectl applyagainst the cluster API. - Continuously reconciled. The controller runs the diff-and-apply loop on a schedule (or on Git webhook) for as long as the application exists. Violation: one-shot apply pipelines that do not retry.
The reconciliation loop
The loop, in five steps, is identical in Argo CD and Flux:
- Fetch. The controller reads the desired state
from Git (Argo CD: from the configured repo URL;
Flux: via the
GitRepositoryandKustomizationCRDs). - Observe. The controller reads the observed state from the cluster (via the Kubernetes API).
- Diff. The controller computes the difference between desired and observed.
- Apply. The controller applies the diff to the cluster (Argo CD: server-side apply; Flux: server-side apply with owner annotations).
- Report. The controller updates the status
(
Application.Statusin Argo CD,Kustomization.Statusin Flux) to reflect whether the observed state now matches the desired state.
flowchart LR
A[Fetch] --> B[Observe]
B --> C[Diff]
C -->|"desired != observed"| D[Apply]
D --> B
C -->|"desired = observed"| E[Healthy]
The synced and healthy matrix
A controller’s status is two orthogonal fields, and a failure in one is not a failure in the other:
- Synced / NotSynced. Does the observed state in
the cluster match the desired state in Git? A
NotSyncedstatus means a sync is pending or has failed. - Healthy / Degraded. Are the resources in the
desired state actually working? A
Degradedstatus means the resources are applied but failing (aCrashLoopBackOff, anImagePullBackOff, a failed readiness probe).
The four combinations map to four operational states:
| Synced | Healthy | Meaning |
|---|---|---|
| Synced | Healthy | Steady state. The loop is happy. |
| Synced | Degraded | The manifests are applied but the workload is failing. Investigate the workload, not the controller. |
| NotSynced | Healthy | A new commit is pending or a sync is in progress. Wait, or check the controller logs. |
| NotSynced | Degraded | Either the sync failed (manifest error) or the workload was failing before the new commit. Read both layers. |
Drift — the three types and the matching controls
Drift is any change to the observed state that did not come through the reconciliation loop:
- Manual drift. Someone ran
kubectl edit,kubectl scale, orkubectl patchto change a resource directly. The next reconciliation will revert the change if self-heal is enabled; otherwise it persists. - Accidental drift. A node failure, a network partition, or a controller crash left the cluster in a partial state. Self-heal converges back to the desired state on the next reconciliation.
- Emergency drift. A break-glass change made
during an incident, applied via
kubectl applyor a hot-patch. The change is real and may need to stay; the after-incident work is to reconcile Git to match the cluster, or to revert the cluster to match Git.
Production discipline
The five rules that recur across every GitOps deployment:
- The controller is the only writer. Any change to a managed resource that does not go through the controller is drift. The cluster’s API is reached by the controller and by emergency break-glass procedures, full stop.
- Self-heal on, prune off by default. Self-heal converges drift; prune removes orphans. The first is a guardrail; the second is a footgun.
- Break-glass is logged. A break-glass change bypasses Git; the after-incident work is to put the change back into Git so the audit trail survives.
kubectl editis not a workflow. If a change is worth making in the cluster, it is worth committing in Git so the next reconciliation does not undo it.- The status fields are the dashboard. Synced and
Healthy are not metrics; they are the controller
telling you whether the cluster matches what you
said it should match. An
Applicationthat isNotSyncedfor an hour is anApplicationwhose desired state has drifted from its observed state.
Cross-course references
- Kubernetes for Production Sysadmins — Controllers and reconciliation loops are the core pattern of Kubernetes itself; the GitOps controller is a specialisation of the same loop.
- Terraform for Production Sysadmins — Terraform apply is a one-shot reconciliation; Terraform drift detection is the same question as Argo CD’s drift detection, with a different cadence.
Quiz
Knowledge check · 4 questions
Q1. An `Application` in Argo CD shows `Status: Synced` and `Health: Degraded`. What is the most likely cause?
Q2. Self-heal and prune are independent controls: self-heal converges a managed resource back to its declared state, while prune deletes resources that are no longer declared in Git.
Q3. Name the four GitOps principles and the one non-obvious reason the controller pulls the desired state from Git rather than having a CI system push manifests to the cluster.
Q4. During an incident, an on-call engineer runs `kubectl scale deployment api --replicas=10` to handle a load spike. The change works and the incident is resolved. The next morning, the application is back to 3 replicas and the engineer is confused. Walk through what happened, why, and what should have been done instead.
Production is running with an Argo CD `Application` for the `api` service. Self-heal is enabled; prune is disabled. The `Deployment` manifest in Git declares `replicas: 3`. During the incident, the engineer ran `kubectl scale deployment api --replicas=10` directly against the cluster. Argo CD's reconciliation interval is 3 minutes. The next morning, the engineer sees `replicas: 3` again.
Passing score: 75%. Answers are checked in this browser.