Skip to main content

GitOps vs traditional CI/CD


Table of Contents

  1. Traditional CI/CD
  2. The Push model
  3. The Pull model (GitOps)
  4. Detailed comparison
  5. When to choose what?
  6. 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

ProblemImpact
Exposed credentialskubeconfig in CI
Possible driftUntracked manual changes
No self-healingIf someone modifies directly
Incomplete auditActions 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

AspectCI/CD PushGitOps Pull
DirectionCI → ClusterCluster ← Git
CredentialsCI has cluster accessInternal agent only
DriftPossibleAuto-corrected
RollbackRe-run pipelinegit revert
AuditCI logsGit history
Self-healingNoYes
ComplexitySimpleMore complex initially

Security

CriterionPushPull
External credentials✅ Yes❌ No
Attack surfaceLargeReduced
Inbound connectionsRequiredNot 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

🔝 Back to table of contents


← Previous chapter | Next chapter: Source of truth →