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:
- Handmatige wijzigingen: Iemand runde
kubectl scaleofkubectl edit - Horizontal Pod Autoscaler: HPA paste replicas aan
- Mutating webhooks: Admission controllers wijzigden resources
- Controller side effects: Operators maakten wijzigingen
- 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:
- Audit trails: “Wat is gedeployed?” wordt “check het cluster” in plaats van “check Git”
- Disaster recovery: Herbouwen vanuit Git matcht niet de oude staat
- Security: Ongeautoriseerde wijzigingen worden niet opgemerkt
- 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
| Application | Sync Status | Health |
|---|---|---|
| frontend | Synced | Healthy |
| backend | OutOfSync | Healthy |
| database | Synced | Healthy |
| cache | Synced | Degraded |
“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 terugprune: true— Verwijder orphaned resources- Snelle feedback, pure GitOps
Voor Production (Meeste Apps)
selfHeal: true— Draai drift terugprune: true— Verwijder orphaned- Alerts op elk OutOfSync event
- Onderzoek waarom drift gebeurde
Voor Production (Kritiek/Speciaal)
selfHeal: false— Menselijke review vereistprune: 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:
Check audit logs: Wie runde kubectl?
kubectl get events --field-selector reason=UpdateCheck controller logs: Maakte een operator wijzigingen?
Check admission webhooks: Gebeuren er mutaties?
kubectl get mutatingwebhookconfigurationsCheck de diff: Wat veranderde precies?
argocd app diff app-name
Drift Voorkomen bij de Bron
Beter dan drift detecteren is het voorkomen:
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/deletePolicy 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: {}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.
