Skip to main content

GitOps

Learn how to use Git as the single source of truth for infrastructure and application configuration.

GitOps Workflow​

GitOps Architecture and Flow​


What is GitOps?​

GitOps is a developer-centric approach to continuous delivery where Git is the single source of truth for both application code and infrastructure configuration. Changes go through Git workflows (pull requests, code review, merge) rather than direct deployments.

Core Principles​

  1. Git as Source of Truth — All desired state is declared in Git
  2. Declarative Configuration — Describe desired state, not commands
  3. Version Control — All changes tracked with full history
  4. Automated Reconciliation — Controllers continuously sync actual state to desired state
  5. Human Review — All changes go through pull request review

Traditional Deployment vs GitOps​

Traditional Deployment (Push-based)​

Developer commits code
↓
CI Pipeline builds artifact
↓
CI Pipeline pushes to production
↓
Application runs

Issues:

  • Credentials stored on CI/CD server
  • Limited visibility into what's deployed
  • Difficult to replicate deployments
  • Hard to track configuration changes

GitOps Deployment (Pull-based)​

Developer commits code + config to Git
↓
CI Pipeline validates and builds artifact
↓
Developer merges to main branch
↓
GitOps Controller detects change in Git
↓
GitOps Controller pulls latest from Git
↓
Controller syncs cluster to match Git

Advantages:

  • Git has full audit trail
  • Configuration as code
  • Easy rollback (revert commit)
  • Self-healing (controller fixes drift)
  • Better security (credentials on cluster, not CI/CD)

Key Components​

1. Git Repository Structure​

Typical GitOps repo layout:

gitops-repo/
apps/
app-1/
base/
deployment.yaml
service.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml
staging/
kustomization.yaml
prod/
kustomization.yaml
infrastructure/
networking/
network-policies.yaml
storage/
storage-classes.yaml
README.md

2. Application Manifests​

Kubernetes manifests describing desired state:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1.2.3
ports:
- containerPort: 8080

3. GitOps Controller​

Continuously monitors Git repository and reconciles cluster state:

  • ArgoCD — Kubernetes-native GitOps controller
  • Flux — Lightweight GitOps controller
  • Jenkins X — Kubernetes-native CI/CD
  • GitKube — Kubernetes-native Git push deployment

4. Synchronization​

Controller detects differences and applies changes:

Git Desired State: app:v2.0
↑
Diff Check
↓
Cluster State: app:v1.0

When diff detected, controller reconciles cluster to match Git.

GitOps Workflow​

Step 1: Update Configuration​

Developer updates deployment configuration in Git:

git checkout -b update-app-version
# Edit app deployment version in deployment.yaml
git commit -am "Update app to v1.2.3"
git push origin update-app-version

Step 2: Code Review​

Create pull request for review:

Pull Request: Update app to v1.2.3
- Changes app image from v1.2.2 to v1.2.3
- Approved by lead engineer
- CI/CD validates YAML syntax

Step 3: Merge​

Reviewer approves and merges to main:

git checkout main
git merge --no-ff update-app-version
git push origin main

Step 4: Automatic Sync​

GitOps controller detects change and syncs cluster:

Controller polling Git repository...
Latest commit: Update app to v1.2.3
Desired state: app:v1.2.3
Current state: app:v1.2.2
Status: OUTOFSYNCH
→ Applying changes to cluster
→ Rolling out new deployment
→ Waiting for pods to become healthy
Status: SYNCHED

Step 5: Verification​

Monitor deployment status:

argocd app get myapp
→ Status: Synced
→ Desired commit: abc123def
→ Live commit: abc123def
→ Replicas: 3/3 running

ArgoCD​

Popular GitOps tool for Kubernetes.

Installation​

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Get initial password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

Creating an Application​

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/user/gitops-repo.git
targetRevision: main
path: apps/myapp/overlays/prod
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true

Key Features​

  • Multi-cluster — Deploy to multiple clusters from single Git source
  • Kustomize/Helm support — Use templating tools
  • Progressive sync — Sync waves, hooks for ordered deployment
  • Diff visualization — See exactly what will change
  • Rollback — Revert to previous Git commit
  • Notifications — Slack, email on sync events

Flux​

Lightweight GitOps toolkit for Kubernetes.

Installation​

curl -s https://fluxcd.io/install.sh | sudo bash
flux install --version=latest

Creating Sources​

Define where to get configuration:

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: myapp-repo
namespace: flux-system
spec:
interval: 1m0s
url: https://github.com/user/gitops-repo.git
ref:
branch: main

Creating Kustomizations​

Define what to deploy:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: myapp
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: myapp-repo
path: ./apps/myapp
prune: true
wait: true

Push vs Pull Deployment​

Push Deployment (Traditional)​

  • CI/CD pushes directly to cluster
  • Faster feedback (immediate)
  • Credentials on CI/CD server
  • Hard to manage drift
  • Difficult for multiple clusters

Pull Deployment (GitOps)​

  • Controller pulls from Git
  • Slight delay (polling interval)
  • Credentials on cluster only
  • Self-healing from drift
  • Consistent multi-cluster management

Repository Structure Patterns​

Pattern 1: Kustomize-based​

repo/
apps/
myapp/
base/
deployment.yaml
kustomization.yaml
overlays/
dev/kustomization.yaml
prod/kustomization.yaml

Pattern 2: Helm-based​

repo/
releases/
myapp-dev.yaml # HelmRelease for dev
myapp-prod.yaml # HelmRelease for prod
charts/
myapp/
templates/
values.yaml

Pattern 3: Environment-per-directory​

repo/
development/
namespace.yaml
apps/
app1/deployment.yaml
app2/deployment.yaml
staging/
namespace.yaml
apps/
app1/deployment.yaml
production/
namespace.yaml
apps/
app1/deployment.yaml

Pattern 4: Mono-repo​

repo/
infrastructure/
networking/
storage/
applications/
app-1/
src/
charts/
deployments/
app-2/
src/
charts/
deployments/

GitOps Best Practices​

1. Keep Git Repository Clean​

  • Only store declarative configuration
  • Don't store binary files or large assets
  • Organize logically
  • Clear naming conventions

2. Environment Parity​

  • Keep dev, staging, prod configs as similar as possible
  • Use overlays for differences
  • Minimize custom per-environment logic

3. Version Control Everything​

  • Application code in Git
  • Infrastructure code in Git
  • Configuration in Git
  • Deployment manifests in Git

4. Implement Proper Code Review​

Feature branch → Pull request → Review → Approval → Merge → Auto-deploy

5. Use RBAC for Git Access​

  • Developers can propose changes
  • Team leads approve changes
  • Automated tools can't bypass review

6. Monitor Sync Status​

  • Watch for OutOfSync applications
  • Alert when sync fails
  • Track sync frequency and duration
  • Monitor controller health

7. Plan Rollback Strategy​

Rollback = Revert Git commit
git revert abc123def
git push origin main
→ Controller automatically syncs cluster

8. Secrets Management​

Don't store secrets in Git directly!

Options:

  • Sealed Secrets — Encrypt secrets in Git
  • External Secrets Operator — Fetch from vault
  • ArgoCD Vault — Store secrets in separate system
  • CI/CD integration — Inject at deployment time

Exercises​

Exercise 1: Basic GitOps Setup​

Set up ArgoCD and create an application that:

  • Syncs from a Git repository
  • Deploys a simple web application
  • Automatically syncs when Git changes
  • Shows application status in ArgoCD UI

Exercise 2: Multi-environment Deployment​

Create a GitOps structure for dev, staging, and prod that:

  • Uses Kustomize overlays
  • Has different replica counts per environment
  • Uses different resource limits
  • Shares common base manifests

Exercise 3: Implement Self-healing​

Configure ArgoCD to:

  • Detect drift between Git and cluster
  • Automatically sync when drift detected
  • Prune resources not in Git
  • Prevent manual changes by overwriting them

Exercise 4: Secrets Management​

Implement secret management where:

  • Database passwords not stored in Git
  • Secrets encrypted in Git (Sealed Secrets)
  • Secrets rotated without Git changes
  • Different secrets per environment

Comparison: ArgoCD vs Flux​

AspectArgoCDFlux
UI DashboardYes (excellent)No
ComplexityMore features, steeper learning curveLightweight, simpler
GitOps ModelPull-basedPull-based
Multi-clusterExcellent supportGood support
CommunityLarge, very activeGrowing, active
RBACBuilt-inVia Kubernetes RBAC
NotificationsBuilt-inVia controllers
Use CaseLarge teams, complex deploymentsSmaller teams, lightweight

Common Pitfalls​

1. Manual Changes Outside GitOps​

Problem: Team makes manual changes directly on cluster Solution: Enforce GitOps for all changes, educate team

2. Credentials in Git​

Problem: Database passwords stored in repository Solution: Use secrets management (Sealed Secrets, Vault)

3. Git Branch Strategy Issues​

Problem: Developers push to main without review Solution: Implement branch protection, require PRs

4. Sync Strategy Too Aggressive​

Problem: Controller constantly syncs, causes noise Solution: Configure appropriate sync intervals and policies

5. Not Monitoring Sync Status​

Problem: Changes don't apply but nobody notices Solution: Monitor ArgoCD/Flux, set up alerts

Key Takeaways​

  • GitOps makes Git the single source of truth for infrastructure and application configuration
  • Pull-based deployment is more secure than push-based (credentials on cluster, not CI/CD)
  • Controllers continuously reconcile actual state to desired state in Git
  • Self-healing automatically fixes drift without manual intervention
  • Git history provides full audit trail of all infrastructure changes
  • Code review workflow applies to infrastructure changes as well
  • Rollback is as simple as reverting a Git commit with automatic cluster sync
  • ArgoCD and Flux are popular GitOps tools with different trade-offs
  • Secrets must be handled separately, not stored directly in Git