Overview
GitOps is an operating model, not a specific tool: the desired state of a system is declared in a Git repository, and an automated agent continuously reconciles the live system toward whatever that repository currently describes. The practical difference from "we deploy via CI" is the direction of control, a CI pipeline pushes changes out on trigger, while a GitOps agent pulls from Git on a loop and keeps enforcing it, catching and correcting drift even if nobody touched the pipeline. That single property, a continuously enforced, Git-sourced desired state, is what gives GitOps its rollback, audit, and drift-detection properties essentially for free.
Quick Reference
| Concept | What it means |
|---|---|
| Source of truth | Git repository, not the live cluster |
| Reconciliation | Pull-based, continuous, an in-cluster agent compares and corrects drift |
| Rollback | A Git revert, using the same mechanism as any other change |
| Audit trail | Git commit history, author, timestamp, review, diff |
| Drift | Any live-state divergence from Git is automatically detected and (optionally) corrected |
Syntax
# Argo CD Application - points a cluster at a Git path and keeps it in sync
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api
spec:
source:
repoURL: 'https://github.com/org/infra-config'
path: apps/api
targetRevision: main
destination:
server: 'https://kubernetes.default.svc'
namespace: api
syncPolicy:
automated:
selfHeal: true
prune: trueExamples
# A rollback is just a Git revert - no separate rollback tooling
git revert HEAD
git push origin main
# The GitOps agent detects the new commit and reconciles the cluster
# back to the previous declared state automatically.selfHeal vs manual sync
selfHeal: true makes the agent correct drift automatically, even without a new commit, someone manually editing a live resource gets silently reverted. Some teams prefer manual sync approval for production, trading that safety net for an explicit human confirmation step.
Visual Diagram
Common Mistakes
- Confusing "we deploy from a CI pipeline triggered by Git" with GitOps, without a continuous, pull-based reconciliation loop, there's no drift detection or self-healing, just a scripted push.
- Granting engineers standing
kubectl applyaccess to production alongside a GitOps agent, any manual change either gets silently reverted (confusing) or causes permanent drift (defeats the point). - Storing secrets in plaintext in the Git repository that GitOps reconciles from, the repository needs the same access control as production credentials, or secrets need to be kept out of it entirely (sealed secrets, external secret managers).
- Treating the GitOps repository structure as an afterthought, a disorganized repo with unclear environment boundaries makes "what's actually running in production" as hard to answer as it was before GitOps.
Performance
- Reconciliation interval (how often the agent polls or reacts to Git changes) trades responsiveness for load on the Git provider and cluster API, very tight intervals on a large cluster with many Applications can add real API server pressure.
- Large repositories with many resources per sync can make individual reconciliation passes slow; splitting by application or environment (multiple smaller Application/Kustomization objects) keeps each sync fast and isolates blast radius.
- Self-healing on every drift detection adds reconciliation overhead but is usually worth it; the alternative is silent, undetected drift accumulating over time.
Best Practices
- Keep application config and infrastructure config in separate repositories or clearly separated paths, since they change at different rates and often need different review policies.
- Require pull-request review on the GitOps repository for anything touching production; this is the actual audit/approval mechanism, so it needs to be enforced, not optional.
- Keep secrets out of the plain Git repository (sealed secrets, external secret operators) even though everything else lives there.
- Start with manual sync approval for production and move to automated self-heal only once the team trusts the pipeline and monitoring around it.