GitOps & Argo CD
The cluster pulls its desired state from git, and anything that drifts gets corrected.
Git As The Source Of Truth
| Principle | In practice |
|---|---|
| Declarative | The whole system described as data, not as steps |
| Versioned | Every change is a commit with an author and a diff |
| Pulled automatically | An in-cluster agent applies, rather than CI pushing |
| Continuously reconciled | Manual changes are reverted, not merely detected |
The audit trail comes free: what is running is whatever the repository says, and git log is the deployment history — including who approved it.
Push Versus Pull
Traditional CI/CD pushes: the pipeline holds cluster credentials and runs kubectl apply. GitOps pulls: an agent in the cluster watches the repository and applies changes itself.
| Push (CI applies) | Pull (agent reconciles) | |
|---|---|---|
| Credentials | CI holds cluster admin | Nothing outside needs cluster access |
| Drift | Detected at best | Corrected automatically |
| Network | CI must reach the cluster | Cluster reaches out — no inbound path |
| State of truth | Whatever ran last | The repository, always |
Argo CD & Repository Layout
Argo CD and Flux both watch repositories and reconcile. An Argo Application ties a source path to a destination cluster and namespace.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: { name: orders-prod, namespace: argocd }
spec:
source:
repoURL: https://github.com/acme/deploy
path: envs/prod/orders # rendered manifests, not templates
targetRevision: main
destination: { server: https://kubernetes.default.svc, namespace: orders }
syncPolicy:
automated: { prune: true, selfHeal: true } # correct drift, remove orphans
| Convention | Why |
|---|---|
| Application code and deploy config in separate repos | A config change should not rebuild the image |
| A directory per environment | Diffs between environments are visible |
| Images pinned by digest | :latest makes the repo a lie |
prune: true | Deleting a file actually removes the resource |
selfHeal: true | Console edits are reverted within a cycle |
Promotion & Progressive Delivery
Promotion becomes a pull request: the image digest that passed in staging is proposed for production, reviewed and merged. There is no separate deploy button, and no way to ship something that is not in the repository.
| Step | Artefact |
|---|---|
| CI builds and tests | An image, tagged by digest |
| Automation updates staging | A commit to the staging path |
| Agent reconciles | Staging now runs it |
| Promotion | A pull request into the production path |
| Rollback | Revert the commit |
Controllers like Argo Rollouts add canary and blue-green on top, shifting traffic gradually and rolling back automatically when metrics degrade — the subject of the release strategies lesson.
Interview Questions
What is GitOps?
Desired state declared in git, with an in-cluster agent continuously reconciling reality against it. Deployment is a commit and rollback is a revert.
Why is pull safer than push?
CI never holds cluster credentials and needs no inbound network path. A compromised pipeline cannot deploy to production because it was never able to reach it.
What does self-heal do?
It reverts changes made outside git within a reconcile cycle, so manual console edits are corrected rather than merely reported as drift.
Why separate application and deploy repositories?
A configuration change should not trigger an image rebuild, and the deploy repository has a different review audience and change cadence.
How are secrets handled?
Never in plaintext. Sealed secrets, SOPS with a KMS key, or an external secrets operator that fetches from a real secret manager at reconcile time.
Why pin images by digest?
A moving tag means the repository no longer describes what is running, which removes the entire guarantee GitOps exists to provide.