Bonnes pratiques GitOps
Table des matières
- Patterns recommandés
- Anti-patterns à éviter
- Sécurité
- Monitoring et alerting
- Documentation
- Exercices pratiques
1 - Patterns recommandés
Separation of Concerns
gitops-repo/
├── apps/ # Équipe dev
├── infrastructure/ # Équipe platform
└── clusters/ # Équipe SRE
# Permissions RBAC par dossier
# apps/* → développeurs
# infrastructure/* → platform team
# clusters/* → SRE uniquement
Small, Frequent Commits
# ✅ Bon : Un changement par commit
git commit -m "feat(frontend): update to v2.3.0"
git commit -m "fix(backend): increase memory to 1Gi"
# ❌ Mauvais : Tout dans un commit
git commit -m "Update frontend, backend, monitoring, ingress..."
Pull Request Workflow
# Branch protection rules
- Require PR reviews (2 approvers)
- Require status checks (lint, validate)
- No force push
- No direct commits to main
GitOps Validation Pipeline
# .github/workflows/validate.yml
name: Validate GitOps
on:
pull_request:
paths:
- 'apps/**'
- 'infrastructure/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate YAML
run: |
find . -name '*.yaml' -exec yamllint {} \;
- name: Validate Kubernetes manifests
uses: instrumenta/kubeval-action@master
- name: Kustomize build
run: |
for dir in apps/*/overlays/*/; do
kustomize build $dir > /dev/null
done
Immutable Tags
# ✅ Bon : Tags immutables
image: myapp:v1.2.3
image: myapp:sha-abc123
# ❌ Mauvais : Tags mutables
image: myapp:latest
image: myapp:dev
🔝 Retour à la table des matières
2 - Anti-patterns à éviter
Direct kubectl Access
# ❌ JAMAIS en production
kubectl set image deployment/myapp myapp=myapp:v2
kubectl scale deployment/myapp --replicas=10
kubectl delete pod myapp-xxx
# ✅ Toujours via Git
git checkout -b hotfix/scale-myapp
# Modifier le fichier
git commit -m "fix: scale myapp to 10"
git push && créer PR
Secrets en clair
# ❌ JAMAIS
apiVersion: v1
kind: Secret
data:
password: bXlwYXNzd29yZA== # base64 n'est PAS sécurisé
# ✅ Utiliser Sealed Secrets, SOPS, Vault
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
spec:
encryptedData:
password: AgBj7...chiffré...
Mono-repo géant
# ❌ Tout dans un seul repo
gitops-monorepo/
├── team-a/
├── team-b/
├── team-c/
├── ... 50 équipes ...
└── infrastructure/
# ✅ Séparer par domaine/équipe
org/gitops-platform
org/gitops-team-a
org/gitops-team-b
Manque de validation
# ❌ Pas de CI sur les manifests
# → Erreurs détectées en production
# ✅ Pipeline de validation
- yamllint
- kubeval / kubeconform
- kustomize build
- helm template
- Policy checks (OPA/Kyverno)
Sync manuel constant
# ❌ Sync manuel = pas vraiment GitOps
syncPolicy: {} # Pas d'automated
# ✅ Auto-sync avec self-heal
syncPolicy:
automated:
prune: true
selfHeal: true
🔝 Retour à la table des matières
3 - Sécurité
Principe du moindre privilège
# GitOps controller avec permissions limitées
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gitops-controller
rules:
# Seulement ce qui est nécessaire
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
# PAS de delete sur certaines ressources
Audit et traçabilité
# Tout est dans Git
git log --oneline --since="2024-01-01"
# a1b2c3d deploy v2.0 - [email protected]
# d4e5f6g scale to 5 - [email protected]
# Git blame
git blame apps/myapp/deployment.yaml
Signed Commits
# Configurer GPG signing
git config --global commit.gpgsign true
git config --global user.signingkey YOUR_KEY_ID
# Vérifier les signatures
git log --show-signature
# ArgoCD - Exiger des commits signés
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
source:
repoURL: ...
syncPolicy:
automated: {}
# + GPG verification dans ArgoCD settings
Network Policies
# Limiter les connexions du controller
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: gitops-controller
spec:
podSelector:
matchLabels:
app: argocd-repo-server
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- port: 443
protocol: TCP
🔝 Retour à la table des matières
4 - Monitoring et alerting
Métriques GitOps
| Métrique | Description |
|---|---|
| Sync Status | Applications in-sync vs out-of-sync |
| Sync Duration | Temps de réconciliation |
| Drift Count | Nombre de drifts détectés |
| Failed Syncs | Échecs de synchronisation |
ArgoCD Metrics
# ServiceMonitor pour Prometheus
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-metrics
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-server
endpoints:
- port: metrics
Alerting
# PrometheusRule
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: gitops-alerts
spec:
groups:
- name: gitops
rules:
- alert: AppOutOfSync
expr: argocd_app_info{sync_status="OutOfSync"} == 1
for: 5m
labels:
severity: warning
annotations:
summary: "Application {{ $labels.name }} is out of sync"
- alert: AppDegraded
expr: argocd_app_info{health_status="Degraded"} == 1
for: 5m
labels:
severity: critical
Notifications
# ArgoCD Notifications
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
service.slack: |
token: $slack-token
template.app-sync-failed: |
message: |
Application {{.app.metadata.name}} sync failed.
Error: {{.app.status.operationState.message}}
trigger.on-sync-failed: |
- send: [app-sync-failed]
when: app.status.operationState.phase in ['Error', 'Failed']
🔝 Retour à la table des matières
5 - Documentation
README dans chaque dossier
# apps/myapp/README.md
## MyApp
Description de l'application.
### Environnements
| Env | Namespace | Replicas |
|-----|-----------|----------|
| Dev | dev | 1 |
| Prod | production | 5 |
### Déploiement
Pour déployer une nouvelle version :
1. Modifier `overlays/<env>/kustomization.yaml`
2. Créer une PR
3. Attendre la review
4. Merge = déploiement automatique
### Rollback
```bash
git revert HEAD
git push
```
Architecture Decision Records (ADR)
# docs/adr/001-gitops-tool-selection.md
# ADR 001: Choix de l'outil GitOps
## Status
Accepted
## Context
Nous devons choisir un outil GitOps pour gérer nos déploiements K8s.
## Decision
Nous utilisons ArgoCD car :
- UI native importante pour nos développeurs
- CNCF Graduated
- Grande communauté
## Consequences
- Formation nécessaire pour l'équipe
- Installation et maintenance du controller
Runbooks
# docs/runbooks/sync-failed.md
# Runbook: Application Sync Failed
## Symptôme
Alerte `AppSyncFailed` déclenchée
## Diagnostic
1. Vérifier l'état ArgoCD
```bash
argocd app get <app-name>
```
2. Voir les logs
```bash
argocd app logs <app-name>
```
## Résolution
- Si erreur de manifest : corriger dans Git
- Si erreur réseau : vérifier la connectivité
- Si ressource bloquée : voir les events K8s
🔝 Retour à la table des matières
6 - Exercices pratiques
Quiz
Q1. Pourquoi ne jamais utiliser kubectl directement en production ?
Réponse
- Pas de traçabilité (qui a fait quoi ?)
- Cause du drift (état cluster ≠ Git)
- Pas de review process
- Le self-healing va annuler le changement
- Non reproductible
Q2. Pourquoi éviter les tags latest ?
Réponse
- Non reproductible :
latestchange au fil du temps - Pas de rollback : impossible de revenir en arrière
- Audit difficile : quelle version tourne vraiment ?
- Utiliser des tags immutables :
v1.2.3,sha-abc123
Exercice : Checklist GitOps
Créez une checklist pour valider votre setup GitOps :
Checklist complète
Repository
- README dans chaque dossier
- .gitignore configuré
- Branch protection activée
- PR reviews obligatoires
CI/CD
- Validation YAML (yamllint)
- Validation K8s (kubeval)
- Kustomize/Helm build test
- Policy checks
Sécurité
- Secrets chiffrés (Sealed Secrets/SOPS)
- Pas de credentials en clair
- RBAC configuré
- Signed commits (optionnel)
Monitoring
- Métriques GitOps exposées
- Alertes configurées
- Notifications Slack/Teams
Documentation
- ADR pour les décisions
- Runbooks pour les incidents
- Diagrammes d'architecture
🔝 Retour à la table des matières
Points clés à retenir
- Patterns : Small commits, PR workflow, immutable tags
- Anti-patterns : kubectl direct, secrets en clair, pas de validation
- Sécurité : Moindre privilège, signed commits, audit trail
- Monitoring : Métriques sync, alertes drift
- Documentation : README, ADR, runbooks