pa-08 — The Hitchhiker's Guide to GitOps
Companion to CONCEPTS.md, with the runnable reconciler in
src/go/gitops/. This is pa-07's plan/apply turned into a continuous, self-healing control loop — the ArgoCD/Flux model.
bash scripts/verify.sh runs the loop end to end:
initial sync (sync-wave order): apply crd -> apply config -> apply workload
manual drift on 'config': healed=[config] (reverted to "v1")
git removes 'config': pruned=[config]; workload updated to "v2"
progressive delivery: healthy -> v2; unhealthy -> v1 rolledBack=true
1. The reconcile loop (reconcile.go)
Reconcile(desired, live, prune) is the loop body, meant to run
continuously. It does three things, and the second is the GitOps
superpower:
- Sync — create missing resources, update changed ones
(
TestSyncCreates,TestSyncUpdatesOnGitChange). - Self-heal — the "update changed" branch also catches manual
drift:
TestSelfHealRevertsManualDrifthand-editssvctoHACKEDand the next reconcile reverts it to git'sv1. Sync and self-heal are the same mechanism; running it continuously is what makes the cluster unable to drift from git for long. - Prune — delete what git dropped (
TestPruneDeletesRemoved), but only when enabled (TestNoPrunePreservesExtra) because prune is destructive.
TestReconcileIsIdempotent confirms a converged pass is a no-op — the
property that makes running this every few seconds safe, shared with
pa-07, gw-08, and gw-10.
2. Sync waves (reconcile.go)
TestSyncWaveOrdering applies crd (wave 0) → config (wave 1) → deploy (wave 2) regardless of declaration order. This is pa-07's dependency
ordering as explicit phases — CRDs before the workloads that use them,
namespaces before their contents — the same declaration-before-use
concern as ADS in xDS (gw-08).
3. Pull, not push (the architecture decision)
The deep point isn't in the code, it's in the direction. A Jenkins
pipeline pushes (kubectl apply from CI, with cluster credentials,
once). GitOps pulls: an agent in the cluster watches git and
converges. Consequences an architect cares about:
- No drift survives — self-heal continuously corrects (vs push, where the cluster drifts freely between deploys).
- No cluster creds in CI — the cluster reaches out; you don't expose it to the pipeline.
- Git is change control + audit + rollback — every change is a
reviewed PR (pa-10), every state a commit, rollback is
git revert. - It scales — one reconciler per cluster handles thousands of apps.
4. Progressive delivery + the off switch
PromoteOrRollback(current, candidate, healthy) is the SLO-gated cutover
in miniature (TestProgressiveDeliveryGate): healthy → promote;
unhealthy → keep current (instant rollback, the old version never left).
The full shadow → canary → ramp ladder with automated analysis is gw-12;
GitOps makes the rollout state itself declarative and revertable.
The maturity detail the GUIDE insists on: automation needs a break-glass. Continuous self-heal will revert an on-call engineer's emergency manual fix. Real GitOps lets you pause reconcile for that window — and treats recurring drift as a signal that git is wrong.
5. The pattern, one more time
IaC (pa-07), GitOps (here), Kubernetes operators (gw-10), and xDS (gw-08) are the same level-triggered, idempotent, converge-to-desired-state loop. ArgoCD/Flux are literally Kubernetes operators for "the app in git." An architect who internalizes this designs every control plane the same way and reuses one operational playbook — the db-17 instinct ("drive the system to a replicated desired state") at the platform layer.
6. Hands-on
cd src/go
bash ../scripts/verify.sh
go run ./cmd/gitopssim
7. Exercises
- Continuous loop: run
Reconcileon a ticker against a "live" map that a goroutine randomly drifts; show convergence within one tick. - Break-glass: add a
pausedflag that suspends self-heal so an emergency manual change survives; log that drift exists while paused. - Owner-ref-scoped prune: only prune resources this app owns, so a mis-scoped app can't delete another's resources.
- Wire SLO gating: replace the boolean
healthywith a real burn-rate check (pa-09) and the canary ladder (gw-12). - Multi-env: model
dev/prodas separate desired sets and a promotion that's a git merge from dev→prod (the GitOps promotion pattern).