Skip to content

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
  1. Git is the single source of truth
  2. All changes through Git (no kubectl apply in prod)
  3. Continuous reconciliation (drift detection + self-heal)
  4. 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: true in syncPolicy.automated means ArgoCD will delete any resource in the cluster that is not in Git. If you accidentally change the source.path to an empty directory, ArgoCD will delete everything in the target namespace. Always test new applications with prune: false first, 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 replicas count. ArgoCD sees Git says replicas: 3 but the cluster shows replicas: 7 (set by HPA), so it keeps marking the app as OutOfSync. Fix with ignoreDifferences on /spec/replicas as 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