GitOps vs traditional CI/CD
Table of Contents
- Traditional CI/CD
- The Push model
- The Pull model (GitOps)
- Detailed comparison
- When to choose what?
- Hands-on exercises
1 - Traditional CI/CD
Classic architecture
Example with GitHub Actions
# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t myapp:${{ github.sha }} .
- run: docker push myapp:${{ github.sha }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: azure/k8s-set-context@v1
with:
kubeconfig: ${{ secrets.KUBECONFIG }}
- run: kubectl set image deployment/myapp myapp=myapp:${{ github.sha }}
Problems with traditional CI/CD
| Problem | Impact |
|---|---|
| Exposed credentials | kubeconfig in CI |
| Possible drift | Untracked manual changes |
| No self-healing | If someone modifies directly |
| Incomplete audit | Actions outside Git not tracked |
🔝 Back to table of contents
2 - The Push model
How it works
Characteristics
- CI/CD pushes changes to the cluster
- CI holds credentials to access the cluster
- Deployment triggered by the pipeline
- The cluster state can diverge from Git
Security
# Le CI doit stocker des secrets sensibles
KUBECONFIG=...
# ou
kubectl config set-credentials ...
# Risques :
# - Fuite des credentials
# - Accès direct au cluster
# - Surface d'attaque élargie
🔝 Back to table of contents
3 - The Pull model (GitOps)
How it works
Characteristics
- The agent pulls changes from Git
- No external credentials to the cluster
- The cluster self-reconciles
- Git is the absolute source of truth
Improved security
# Le CI n'a PAS accès au cluster
# Seul l'agent GitOps (dans le cluster) a accès
# Avantages :
# - Pas de credentials CI vers cluster
# - Surface d'attaque réduite
# - Principe du moindre privilège
GitOps workflow
# 1. CI: Build et push l'image
# .github/workflows/ci.yml
build:
steps:
- run: docker build -t myapp:${{ github.sha }} .
- run: docker push registry/myapp:${{ github.sha }}
# Mise à jour du repo GitOps
- run: |
git clone $GITOPS_REPO
cd gitops-repo
yq -i '.spec.template.spec.containers[0].image = "myapp:${{ github.sha }}"' apps/myapp/deployment.yaml
git commit -am "Update myapp to ${{ github.sha }}"
git push
# 2. GitOps Agent détecte le changement et l'applique
🔝 Back to table of contents
4 - Detailed comparison
Comparison table
| Aspect | CI/CD Push | GitOps Pull |
|---|---|---|
| Direction | CI → Cluster | Cluster ← Git |
| Credentials | CI has cluster access | Internal agent only |
| Drift | Possible | Auto-corrected |
| Rollback | Re-run pipeline | git revert |
| Audit | CI logs | Git history |
| Self-healing | No | Yes |
| Complexity | Simple | More complex initially |
Security
| Criterion | Push | Pull |
|---|---|---|
| External credentials | ✅ Yes | ❌ No |
| Attack surface | Large | Reduced |
| Inbound connections | Required | Not required |
Reconciliation
# Scénario : Quelqu'un fait kubectl directement
kubectl scale deployment/myapp --replicas=10
# Push Model :
# - Le changement persiste
# - Drift par rapport à Git
# - Pas de correction automatique
# Pull Model (GitOps) :
# - L'agent détecte la différence
# - Rétablit l'état de Git (ex: replicas=3)
# - Le changement manuel est annulé
🔝 Back to table of contents
5 - When to choose what?
Choose CI/CD Push if
- ✅ Simple application, few deployments
- ✅ Small team without a GitOps culture
- ✅ No Kubernetes
- ✅ Infrequent deployments
Choose GitOps Pull if
- ✅ Kubernetes in production
- ✅ Need for full audit
- ✅ Multiple teams
- ✅ Multi-environments (dev, staging, prod)
- ✅ High security requirements
- ✅ Need for self-healing
Gradual migration
# Étape 1 : Séparer le repo GitOps
# Le CI met à jour le repo GitOps au lieu de kubectl
# Étape 2 : Installer l'agent GitOps
# ArgoCD ou Flux dans le cluster
# Étape 3 : Désactiver le push direct
# Le CI ne fait plus kubectl
🔝 Back to table of contents
6 - Hands-on exercises
Quiz
Q1. What is the main security difference between Push and Pull?
Answer
In Push, CI holds credentials to access the cluster (large attack surface). In Pull, only the cluster-internal agent accesses Git (reduced attack surface).
Q2. What happens if someone runs kubectl scale manually in GitOps?
Answer
The GitOps agent detects the drift between the actual state and the state in Git, then reconciles automatically by restoring the state from Git.
Exercise: Scenario analysis
Your team is hesitating between Push and Pull. Analyze:
- 50 microservices on Kubernetes
- 3 environments (dev, staging, prod)
- Compliance requirements (SOC2)
- Team of 15 developers
Recommendation
GitOps Pull is recommended because:
- Multi-environments → GitOps excels
- SOC2 → Complete audit trail in Git
- 50 services → Drift would be a nightmare without self-healing
- 15 devs → Risk of untracked manual changes
🔝 Back to table of contents
Key takeaways
- Push: CI pushes to the cluster (exposed credentials)
- Pull: Agent pulls from Git (more secure)
- GitOps = self-healing and full audit
- Push = simple but risk of drift
- Gradual migration is possible