GitOps belooft dat Git de source of truth is. Maar wat als iemand kubectl edit runt op een deployment? Wat als een mutating webhook een resource verandert? Wat als het cluster stilletjes afwijkt van wat Git zegt dat het zou moeten zijn?

Dit is configuratie drift, en het is een van de meest verraderlijke problemen in Kubernetes operations. ArgoCD kan je helpen het te detecteren — als je het correct configureert.

Wat Is Configuratie Drift?

Drift gebeurt wanneer de daadwerkelijke staat van je cluster verschilt van de gewenste staat in Git.

flowchart LR
    subgraph git["Git zegt (Source of truth)"]
        G1["replicas: 3"]
        G2["image: v1.2.3"]
        G3["cpu: 100m"]
    end

    subgraph cluster["Cluster heeft (Actuele staat)"]
        C1["replicas: 5"]
        C2["image: v1.2.3"]
        C3["cpu: 200m"]
    end

    git -.->|"≠"| cluster

Hoe werd replicas 5 terwijl Git 3 zegt? Mogelijke oorzaken:

  1. Handmatige wijzigingen: Iemand runde kubectl scale of kubectl edit
  2. Horizontal Pod Autoscaler: HPA paste replicas aan
  3. Mutating webhooks: Admission controllers wijzigden resources
  4. Controller side effects: Operators maakten wijzigingen
  5. Gedeeltelijke syncs: Sync faalde halverwege

Sommige drift is intentioneel (HPA). De meeste niet. Het probleem is niet weten welke welk is.

Waarom Drift Ertoe Doet

Zonder drift detectie heb je geen garantie dat Git de realiteit vertegenwoordigt. Dit breekt:

  1. Audit trails: “Wat is gedeployed?” wordt “check het cluster” in plaats van “check Git”
  2. Disaster recovery: Herbouwen vanuit Git matcht niet de oude staat
  3. Security: Ongeautoriseerde wijzigingen worden niet opgemerkt
  4. Reproduceerbaarheid: Twee clusters van dezelfde Git zijn niet identiek

Het moment dat je ongedetecteerde drift hebt, heb je het kernvoordeel van GitOps verloren.

ArgoCD’s Sync Status

ArgoCD vergelijkt continu Git met cluster state. De sync status vertelt je:

  • Synced: Cluster matcht Git exact
  • OutOfSync: Verschillen gedetecteerd
  • Unknown: ArgoCD kan staat niet bepalen
ApplicationSync StatusHealth
frontendSyncedHealthy
backendOutOfSyncHealthy
databaseSyncedHealthy
cacheSyncedDegraded

“OutOfSync” = drift gedetecteerd

OutOfSync betekent drift. Maar ArgoCD’s standaard gedrag kan je verrassen.

Self-Heal: Automatische Drift Correctie

ArgoCD kan drift automatisch terugdraaien:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: frontend
spec:
  syncPolicy:
    automated:
      selfHeal: true  # Draai handmatige wijzigingen terug
      prune: true     # Verwijder orphaned resources

Met selfHeal: true, wanneer iemand kubectl scale deployment frontend --replicas=5 runt, zal ArgoCD het binnen seconden terugzetten naar wat Git zegt.

Dit is krachtig maar heeft implicaties:

  • Intentionele wijzigingen worden teruggedraaid
  • HPA aanpassingen worden overschreven
  • Je kunt niet snel productie hotfixen

Voor de meeste applicaties zou selfHeal ingeschakeld moeten zijn. Het is de “GitOps purist” aanpak.

Intentionele Drift Afhandelen: Ignore Differences

Sommige velden moeten buiten Git beheerd worden:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: autoscaled-app
spec:
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas
    - group: ""
      kind: Service
      jsonPointers:
        - /spec/clusterIP

Dit vertelt ArgoCD: “Rapporteer geen drift voor deze velden.”

Veelvoorkomende velden om te negeren:

  • /spec/replicas (als je HPA gebruikt)
  • /spec/clusterIP (toegewezen door Kubernetes)
  • /metadata/annotations (controller-toegevoegd)
  • /status (altijd beheerd door controllers)

Drift Detecteren Zonder Auto-Fix

Soms wil je weten over drift maar niet automatisch fixen:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: critical-app
spec:
  syncPolicy:
    automated:
      selfHeal: false  # Niet auto-fixen
      prune: false     # Niet auto-deleten

Nu toont ArgoCD OutOfSync status maar wacht op handmatige interventie. Dit is nuttig voor:

  • Kritieke productie systemen waar je menselijke review wilt
  • Debuggen van drift bronnen
  • Applicaties gedeeltelijk beheerd buiten GitOps

Notificaties: Alert op Drift

Staar niet naar het dashboard. Krijg notificaties:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  trigger.on-sync-status-unknown: |
    - when: app.status.sync.status == 'OutOfSync'
      send: [app-out-of-sync]
  template.app-out-of-sync: |
    message: |
      Application {{.app.metadata.name}} is OutOfSync.
      Sync Status: {{.app.status.sync.status}}
      Health: {{.app.status.health.status}}
      Repository: {{.app.spec.source.repoURL}}

Koppel dit aan Slack, PagerDuty, of email. Drift zou alerts moeten triggeren.

De Diff View: Drift Begrijpen

Wanneer drift optreedt, toont ArgoCD precies wat veranderde:

argocd app diff frontend

Of in de UI, klik op een OutOfSync applicatie om de diff te zien:

--- Git (desired)
+++ Cluster (actual)
@@ -1,4 +1,4 @@
 spec:
-  replicas: 3
+  replicas: 5
   template:
     spec:

Dit is onmisbaar voor begrijpen wat driftte en waarom.

Refresh vs Sync

Twee verschillende operaties:

Refresh: Vergelijk Git met cluster, update status. Geen wijzigingen gemaakt.

argocd app get frontend --refresh

Sync: Pas Git staat toe op cluster. Wijzigingen gemaakt.

argocd app sync frontend

Refresh is veilig en frequent (elke 3 minuten standaard). Sync is destructief en zou bewust moeten zijn (tenzij automated).

Drift Detectie Strategie

Dit is mijn aanpak:

Voor Development/Staging

  • selfHeal: true — Draai alle drift terug
  • prune: true — Verwijder orphaned resources
  • Snelle feedback, pure GitOps

Voor Production (Meeste Apps)

  • selfHeal: true — Draai drift terug
  • prune: true — Verwijder orphaned
  • Alerts op elk OutOfSync event
  • Onderzoek waarom drift gebeurde

Voor Production (Kritiek/Speciaal)

  • selfHeal: false — Menselijke review vereist
  • prune: false — Alleen handmatige verwijdering
  • Strikte alerts
  • Expliciete sync approval

Voor HPA-Managed Apps

ignoreDifferences:
  - group: apps
    kind: Deployment
    jsonPointers:
      - /spec/replicas
syncPolicy:
  automated:
    selfHeal: true  # Voor andere velden

De Drift Bron Vinden

Wanneer je drift ziet, onderzoek:

  1. Check audit logs: Wie runde kubectl?

    kubectl get events --field-selector reason=Update
    
  2. Check controller logs: Maakte een operator wijzigingen?

  3. Check admission webhooks: Gebeuren er mutaties?

    kubectl get mutatingwebhookconfigurations
    
  4. Check de diff: Wat veranderde precies?

    argocd app diff app-name
    

Drift Voorkomen bij de Bron

Beter dan drift detecteren is het voorkomen:

  1. RBAC restricties: Beperk wie resources kan wijzigen

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: readonly
    rules:
      - apiGroups: ["*"]
        resources: ["*"]
        verbs: ["get", "list", "watch"]  # Geen create/update/delete
    
  2. Policy enforcement: Gebruik Kyverno om handmatige wijzigingen te blokkeren

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: require-gitops
    spec:
      rules:
        - name: block-manual-changes
          match:
            resources:
              kinds:
                - Deployment
          exclude:
            subjects:
              - kind: ServiceAccount
                name: argocd-application-controller
          validate:
            message: "Wijzigingen moeten via GitOps"
            deny: {}
    
  3. Training: Leer teams om Git te wijzigen, niet het cluster

Drift Monitoren Over Tijd

Track drift als metric:

# Prometheus query voor out-of-sync apps
count(argocd_app_info{sync_status="OutOfSync"})

Alert als het te lang non-zero is:

- alert: GitOpsDriftDetected
  expr: count(argocd_app_info{sync_status="OutOfSync"}) > 0
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: "GitOps drift gedetecteerd"
    description: "Eén of meer applicaties zijn OutOfSync met Git"

Mijn Checklist voor Drift-Vrije GitOps

[ ] selfHeal ingeschakeld voor meeste applicaties
[ ] ignoreDifferences geconfigureerd voor HPA-managed replicas
[ ] Notificaties ingesteld voor OutOfSync events
[ ] RBAC beperkt directe cluster wijzigingen
[ ] Policy enforcement voorkomt handmatige wijzigingen
[ ] Monitoring alerteert op drift
[ ] Team getraind op GitOps workflow

Configuratie drift is de vijand van betrouwbare infrastructuur. Detecteer het direct, fix het automatisch waar veilig, en onderzoek meedogenloos wanneer het gebeurt. Git zou altijd de realiteit moeten reflecteren — dat is het hele punt.