GitOps veranderde hoe ik over deployments denk. In plaats van commando’s tegen een cluster uitvoeren, push ik naar Git en kijk ik hoe het cluster convergeert naar de gewenste staat. Het klinkt simpel, maar de implicaties zijn diepgaand.

ArgoCD is mijn tool of choice voor GitOps. Laat me je laten zien waarom, en hoe je ermee begint.

Waarom GitOps? De Filosofie Eerst

Voordat we in ArgoCD duiken, laten we begrijpen waarom GitOps ertoe doet.

Traditionele deployment:

Developer → kubectl apply → Cluster

Het probleem: Wat is gedeployed? Je moet het cluster queryen. Configuration drift gebeurt stilletjes. Rollbacks zijn handmatig en foutgevoelig. Er is geen audit trail behalve “iemand heeft kubectl gerund.”

GitOps deployment:

Developer → Git Push → ArgoCD → Cluster

Het verschil: Git is de source of truth. Wat in Git staat is wat in het cluster staat. Altijd. Als iemand handmatig iets verandert, draait ArgoCD het terug. Als je wilt weten wat gedeployed is, check Git. Als je wilt rollbacken, revert de commit.

Dit past bij mijn kernfilosofie: systemen moeten expliciet en begrijpbaar zijn. Imperatieve commando’s zijn vluchtig. Declaratieve staat in Git is permanent en auditeerbaar.

ArgoCD Installeren

Laten we ArgoCD draaien. Ik gebruik eerst een simpele installatie, dan leg ik de onderdelen uit.

# Maak namespace
kubectl create namespace argocd

# Installeer ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Wacht tot pods ready zijn
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=300s

Dat is het. ArgoCD draait nu. Laten we het benaderen:

# Haal het initiële admin wachtwoord op
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

# Port-forward de UI
kubectl port-forward svc/argocd-server -n argocd 8080:443

# Open https://localhost:8080, login als 'admin' met het wachtwoord hierboven

De Kernconcepten

ArgoCD heeft een paar key concepts om te begrijpen:

Application

Een Application is de fundamentele unit in ArgoCD. Het definieert:

  • Source: Waar je manifests leven (Git repo, Helm chart, Kustomize)
  • Destination: Naar welk cluster en namespace te deployen
  • Sync Policy: Hoe om te gaan met verschillen tussen Git en cluster
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/yourorg/yourrepo.git
    targetRevision: main
    path: manifests/my-app
  destination:
    server: https://kubernetes.default.svc
    namespace: my-app
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Project

Een Project groepeert applicaties en definieert access controls. Het default project staat alles toe, maar in productie wil je restricties.

Sync

Sync is het proces van het cluster laten matchen met Git. Het kan zijn:

  • Handmatig: Je klikt op een knop
  • Automated: ArgoCD doet het wanneer Git verandert
  • Self-healing: ArgoCD draait handmatige cluster wijzigingen terug

Je Eerste Deployment

Laten we iets echts deployen. Ik maak een simpele nginx deployment beheerd door ArgoCD.

Stap 1: Maak een Git Repository

Maak een nieuwe repo (of gebruik een bestaande) met deze structuur:

my-gitops-repo/
└── apps/
    └── nginx/
        ├── deployment.yaml
        ├── service.yaml
        └── kustomization.yaml

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80

kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

Commit en push dit naar je repo.

Stap 2: Maak de ArgoCD Application

# argocd-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/YOURUSER/my-gitops-repo.git
    targetRevision: main
    path: apps/nginx
  destination:
    server: https://kubernetes.default.svc
    namespace: nginx
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
    automated:
      prune: true
      selfHeal: true

Apply het:

kubectl apply -f argocd-application.yaml

Stap 3: Kijk naar de Magie

Open de ArgoCD UI. Je ziet je applicatie verschijnen. Als je automated sync hebt ingeschakeld, deployt het direct. Anders klik je op “Sync.”

flowchart LR
    subgraph dashboard["ArgoCD Dashboard - nginx"]
        direction LR
        DEP["Deployment<br/>nginx"] --> RS["ReplicaSet<br/>nginx"]
        RS --> POD["Pod x2<br/>nginx"]
        DEP --> SVC["Service<br/>nginx"]
    end

ArgoCD toont de resource tree, health status, en sync status. Het is direct duidelijk wat gedeployed is.

De GitOps Workflow

Nu komt het mooie deel. Wil je iets veranderen?

  1. Edit in Git: Verander replicas: 2 naar replicas: 3 in deployment.yaml
  2. Commit en push
  3. ArgoCD detecteert de wijziging (binnen 3 minuten standaard, of direct met webhooks)
  4. Cluster update automatisch

Geen kubectl. Geen scripts. Geen “heb ik dat commando gerund?” Git is de waarheid.

Rollback? Gewoon Reverten

Iets kapot? Revert de commit in Git. ArgoCD synct. Klaar.

git revert HEAD
git push

# ArgoCD rollbackt automatisch het cluster

De cluster staat is nu auditeerbaar via git log:

git log --oneline apps/nginx/
# a1b2c3d Scale nginx to 3 replicas
# d4e5f6g Initial nginx deployment

Self-Healing in Actie

Schakel selfHeal: true in en probeer dit:

# Handmatig de deployment schalen
kubectl scale deployment nginx -n nginx --replicas=5

# Wacht even...
kubectl get deployment nginx -n nginx
# NAME    READY   UP-TO-DATE   AVAILABLE
# nginx   3/3     3            3

ArgoCD merkte de drift op en draaide het terug. Het cluster matcht altijd Git.

Dit voorkomt configuration drift — een van de meest verraderlijke problemen in infrastructuur. Geen “iemand heeft die instelling vorig jaar veranderd en niemand weet waarom” meer.

Sync Policies Uitgelegd

De sync policy bepaalt hoe ArgoCD zich gedraagt:

syncPolicy:
  automated:
    prune: true      # Verwijder resources die uit Git verwijderd zijn
    selfHeal: true   # Draai handmatige wijzigingen terug
    allowEmpty: false # Sync niet als source leeg is
  syncOptions:
    - CreateNamespace=true
    - PruneLast=true  # Prune na andere syncs
    - ApplyOutOfSyncOnly=true  # Alleen gewijzigde resources applyen
  retry:
    limit: 5
    backoff:
      duration: 5s
      factor: 2
      maxDuration: 3m

Mijn aanbeveling: Begin met automated sync, prune, en selfHeal allemaal ingeschakeld. Dit geeft je de volledige GitOps ervaring. Je kunt altijd uitschakelen voor specifieke applicaties die speciale handling nodig hebben.

Private Repositories

De meeste echte repos zijn private. ArgoCD heeft credentials nodig:

# Met de CLI
argocd repo add https://github.com/yourorg/private-repo.git \
  --username git \
  --password ghp_yourtoken

# Of als Kubernetes secret
kubectl create secret generic private-repo \
  -n argocd \
  --from-literal=url=https://github.com/yourorg/private-repo.git \
  --from-literal=username=git \
  --from-literal=password=ghp_yourtoken

kubectl label secret private-repo -n argocd \
  argocd.argoproj.io/secret-type=repository

Voor SSH:

argocd repo add git@github.com:yourorg/private-repo.git \
  --ssh-private-key-path ~/.ssh/id_rsa

Helm en Kustomize

ArgoCD ondersteunt native Helm en Kustomize.

Helm Charts

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus
  namespace: argocd
spec:
  source:
    repoURL: https://prometheus-community.github.io/helm-charts
    chart: prometheus
    targetRevision: 25.0.0
    helm:
      values: |
        server:
          persistentVolume:
            enabled: true
            size: 10Gi
  destination:
    server: https://kubernetes.default.svc
    namespace: monitoring

Kustomize Overlays

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-production
spec:
  source:
    repoURL: https://github.com/yourorg/yourrepo.git
    path: apps/my-app/overlays/production
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: production

ArgoCD detecteert kustomization.yaml en past het automatisch toe.

Veelvoorkomende Fouten om te Vermijden

Fout 1: Prune Niet Inschakelen

Zonder prune: true verwijdert ArgoCD geen resources die je uit Git verwijdert. Je eindigt met orphaned resources.

Fout 2: Secrets in Git Zetten

Commit nooit plain secrets naar Git. Gebruik:

Fout 3: Handmatige Wijzigingen “Alleen Deze Keer”

Het moment dat je handmatig iets verandert, heb je drift geïntroduceerd. Of update Git of schakel selfHeal in om je wijziging terug te draaien.

Fout 4: Enkele Monolithische Application

Eén grote Application met alles is moeilijk te beheren. Splits in meerdere applications per service of team.

Wat Volgt?

Dit is nog maar het begin. ArgoCD heeft veel meer:

Mijn Aanbeveling

  1. Begin met één applicatie. Raak vertrouwd met de workflow.
  2. Schakel automated sync + selfHeal in. Ervaar het volledige GitOps voordeel.
  3. Gebruik een dedicated gitops repo. Scheid infrastructuur van applicatie code.
  4. Stel webhooks in. Snellere sync dan polling.
  5. Vecht er niet tegen. Als je handmatige controle wilt, vraag jezelf waarom.

GitOps is niet alleen een deployment methode. Het is een mindset shift. Als je eenmaal “Git is waarheid” ervaart, wil je niet meer terug naar imperatieve commando’s en configuration drift.