Lesson 1 of 6
GitOps principles
Make Git the single source of truth so a controller continuously reconciles your cluster, catching drift and self-healing without anyone touching prod.
① Watch
Speed
📖 Read this walkthrough — every command, and why
GitOps Principles — git is the source of truth, an agent reconciles the cluster to it
Mental model: deploying by hand doesn't scale, and nobody can tell you what's actually
running. GitOps replaces "push kubectl at the cluster" with four tenets you can watch in
Argo CD:
1. Declarative — you describe the desired end state, not the steps to get there.
2. Versioned in git — that repo is the single source of truth; every sync pins an exact commit.
3. Pulled — an agent running INSIDE the cluster pulls desired state from git and applies it.
4. Reconciled — the agent keeps comparing live vs git and drives any drift back (self-heal).
Here an Argo CD Application named guestbook points at a git repo + path and says "make the
cluster look like this." Argo's application-controller (in-cluster) does the pulling and reconciling.
1 · The Application declares desired state FROM GIT
kubectl apply -f guestbook-app.yaml # source: repo + path -> destination cluster/namespace
# application.argoproj.io/guestbook created
2 · Inspect it — SYNC tells you live matches git, HEALTH tells you the workload is up
kubectl get application guestbook -n argocd
NAME REPO PATH SYNC HEALTH
guestbook https://github.com/argoproj/argocd-example-apps.git guestbook Synced Healthy
# Synced = live cluster == the manifests in git at the pinned revision
# Healthy = the resources Argo created are actually running/ready
3 · The workload Argo created FROM GIT — nobody ran kubectl by hand
kubectl get deploy,svc -l app=guestbook-ui
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/guestbook-ui 1/1 1 1 29s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/guestbook-ui ClusterIP 10.96.165.176 <none> 80/TCP 29s
# Both the Deployment and the Service came straight from the guestbook path in the repo.
4 · Git is the source of truth — the sync revision pins a REAL commit
# Synced @ revision 8088f4c0d970abb09e250248cc97e35623447cb5
A full commit SHA you can review, revert, and audit. To change production you change git,
not the cluster. The canonical rollback is `git revert <bad-commit>` -> the controller
reconciles the cluster back to the prior declared state.
5 · Continuous reconciliation / self-heal — delete a synced resource; Argo restores it
kubectl delete deploy guestbook-ui # drift: live no longer matches git
# with selfHeal=true the application-controller notices and recreates it
kubectl get deploy guestbook-ui
NAME READY UP-TO-DATE AVAILABLE AGE
guestbook-ui 1/1 1 1 25s
# Ready again seconds later. The controller doesn't apply once and walk away —
# it keeps driving live state back toward what git declares. THAT reconciliation is GitOps.
What each part does
Application (CRD) declares source (repo+path) -> destination + sync policy
SYNC = Synced live cluster == git at the pinned revision
HEALTH = Healthy the created resources are running/ready
revision 8088f4c0... the exact git commit that Synced state was computed from
selfHeal=true auto-correct out-of-band drift back to git
Notes and gotchas
- Git is truth. Don't `kubectl edit` prod. A hand edit is drift the controller will overwrite
(or, with selfHeal off, it just shows the app OutOfSync until you fix git). Either way your
change is untracked and gets lost.
- The controller never writes live state back INTO git. Bumping replicas with `kubectl scale`
while git still says 3 gets reconciled back to 3 — persist it by editing the manifest.
- Pulled, not pushed: the agent lives in-cluster and pulls from git, so cluster-admin creds
never leave the cluster for an external CI system — you only grant the agent repo read access.
- Declarative vs imperative: declarative states the end result and lets the reconciler figure
out how; imperative issues ordered step-by-step commands. GitOps needs declarative specs so
they can be stored in git and continuously reconciled.
Verify: kubectl get application guestbook -n argocd -o wide # expect SYNC=Synced, HEALTH=Healthy
Gotcha: Synced means matches git, NOT "correct" — if you commit a broken manifest, Argo will
faithfully sync the cluster to broken. Git being the source of truth cuts both ways.