GitOps & ArgoCD Cheat Sheet¶
Name origin: GitOps was coined by Alexis Richardson (Weaveworks CEO) in 2017. The core insight: if Git already tracks every change with author, timestamp, and diff, then Git itself becomes the audit log, rollback mechanism, and access control layer for infrastructure. ArgoCD is named after the ship "Argo" from Greek mythology (Jason and the Argonauts) — continuing the Kubernetes nautical naming tradition.
Core Principles¶
Git Repo (desired state)
│
▼
ArgoCD (reconciler)
│ compare
▼
Live Cluster (actual state)
│
▼
Sync if different → apply manifests
- Git is the single source of truth
- All changes through Git (no kubectl apply in prod)
- Continuous reconciliation (drift detection + self-heal)
- Declarative, not imperative
ArgoCD CLI Essentials¶
# Login
argocd login argocd.example.com --grpc-web
# List apps
argocd app list
# Get app details
argocd app get <app-name>
# View diff (Git vs live)
argocd app diff <app-name>
# Sync (apply Git state to cluster)
argocd app sync <app-name>
# Hard refresh (clear cache, re-read Git)
argocd app get <app-name> --hard-refresh
# Rollback to previous sync
argocd app rollback <app-name> <history-id>
# Set parameters
argocd app set <app-name> -p image.tag=v2.0.0
Application Resource¶
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: grokdevops
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/repo.git
targetRevision: main
path: k8s/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # Delete resources removed from Git
selfHeal: true # Revert manual changes
syncOptions:
- CreateNamespace=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
App-of-Apps Pattern¶
# Parent app points to a directory of Application manifests
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app-of-apps
spec:
source:
path: argocd-apps/ # Directory containing Application YAMLs
destination:
namespace: argocd
ApplicationSet (Dynamic App Generation)¶
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-apps
spec:
generators:
- git:
repoURL: https://github.com/org/repo.git
revision: main
directories:
- path: apps/* # One app per subdirectory
template:
metadata:
name: '{{path.basename}}'
spec:
source:
repoURL: https://github.com/org/repo.git
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
Gotcha:
prune: trueinsyncPolicy.automatedmeans ArgoCD will delete any resource in the cluster that is not in Git. If you accidentally change thesource.pathto an empty directory, ArgoCD will delete everything in the target namespace. Always test new applications withprune: falsefirst, and only enable pruning after you have verified the source path is correct.
Ignore Differences (HPA Fix)¶
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas # Let HPA manage replicas
- group: ""
kind: Service
jqPathExpressions:
- .spec.clusterIP # Server-set field
Debug clue: The #1 cause of "OutOfSync" loops is HPA fighting with the Git-declared
replicascount. ArgoCD sees Git saysreplicas: 3but the cluster showsreplicas: 7(set by HPA), so it keeps marking the app as OutOfSync. Fix withignoreDifferenceson/spec/replicasas shown below.
Sync Waves & Hooks¶
# Run in order: wave 0 → wave 1 → wave 2
metadata:
annotations:
argocd.argoproj.io/sync-wave: "0" # Lower runs first
---
# Hook: run before sync
metadata:
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
Health Status Reference¶
| Status | Meaning |
|---|---|
| Healthy | All resources healthy |
| Progressing | Rollout in progress |
| Degraded | Resource has errors |
| Suspended | Paused (e.g., Rollout) |
| Missing | Resource not in cluster |
| Unknown | Health not assessable |
Common Gotchas¶
| Issue | Cause | Fix |
|---|---|---|
| OutOfSync loop | HPA vs Git replicas | ignoreDifferences on /spec/replicas |
| Prune deletes everything | Wrong path in source | Always test with prune: false first |
| Sync fails with hooks | Hook Job failed | Check hook logs, add delete policy |
| App stuck Progressing | Deployment stuck | Check pod events, resource limits |