Back to Blog

GitOps 101: How to Manage Infrastructure and Deployments with Git

Transform your infrastructure and deployment management with GitOps. Learn how to use Git as a single source of truth, automate deployments with Argo CD and Flux, and implement declarative, auditable infrastructure workflows.

Published

9 min read

Reading time

GitOps 101: How to Manage Infrastructure and Deployments with Git

What if your entire infrastructure could be managed the same way you manage code—through Git commits, pull requests, and version control? What if deployments were as simple as merging a PR, with automatic rollbacks if something goes wrong?

This is GitOps: a paradigm shift in how we think about infrastructure and deployments. Instead of manual kubectl commands, SSH sessions, or clicking through cloud consoles, GitOps treats Git as the single source of truth for your entire system state.

If you're managing cloud infrastructure, Kubernetes clusters, or complex deployment pipelines, GitOps can dramatically improve reliability, auditability, and developer velocity. Let's explore how.

What is GitOps?

GitOps is an operational framework that applies DevOps best practices—version control, collaboration, compliance, and CI/CD—to infrastructure automation.

Core principle: Your Git repository describes the desired state of your system. Automated agents continuously ensure the actual state matches the desired state declared in Git.

The Four Pillars of GitOps

Pillar Description
1. Declarative Your system is described declaratively (YAML, HCL, etc.)
2. Versioned and Immutable All changes are tracked in Git with full audit history
3. Pulled Automatically Agents pull changes from Git (not pushed from CI)
4. Continuously Reconciled Agents continuously sync actual state to match desired state

GitOps vs. Traditional DevOps

Let's compare the traditional push-based approach to GitOps:

Traditional Approach (Push-Based)

graph LR
    A[Developer] --> B[Git Commit];
    B --> C[CI Pipeline];
    C --> D[Build/Test];
    D --> E[Push to Cluster];
    E --> F[Production];
    style E fill:#ff9999

Problems:

  • CI system needs cluster credentials (security risk)
  • Manual intervention often required
  • Difficult to audit who changed what
  • Drift between Git and actual state

GitOps Approach (Pull-Based)

graph LR
    A[Developer] --> B[Git Commit];
    B --> C[Git Repository];
    D[GitOps Agent in Cluster] -.->|Polls| C;
    D --> E[Auto-sync to Match Desired State];
    E --> F[Production];
    style D fill:#99ff99

Benefits:

  • No cluster credentials in CI (agent pulls from Git)
  • Automatic, continuous reconciliation
  • Complete audit trail in Git
  • Self-healing infrastructure

The GitOps Workflow

Here's a typical GitOps workflow for deploying a web application:

  1. Developer makes a change:

    # Update image tag in Kubernetes manifest
    git checkout -b update-api-v2
    # Edit deployment.yaml: image: myapp:v2
    git commit -m "Update API to v2.0.0"
    git push origin update-api-v2
    
  2. Code review: Team reviews the PR, checking:

    • Correct image tag
    • Resource limits appropriate
    • Environment variables correct
  3. Merge to main:

    git merge update-api-v2
    
  4. GitOps agent detects change:

    • Argo CD or Flux polls the repository
    • Notices the new commit
    • Applies changes to the cluster
    • Reports success/failure
  5. Observability:

    • Git provides full audit trail
    • Slack/email notifications on deployment
    • Prometheus monitors application health

Tools: Argo CD vs. Flux

The two leading GitOps tools for Kubernetes are Argo CD and Flux. Both are CNCF projects with strong communities.

Feature Argo CD Flux
UI Rich web UI with visual app topology CLI-focused (UI via extensions)
Multi-tenancy Built-in with Projects Via RBAC and repository structure
Git Source Git, Helm repos Git, Helm, OCI registries
Sync Strategy Manual or auto Always automatic
Notifications Built-in (Slack, email, webhooks) Via Notification Controller
Architecture Centralized controller Distributed, per-cluster agents
Learning Curve Moderate (UI helps) Steeper (CLI-first)
Best For Teams wanting visibility via UI Large-scale, multi-cluster setups

Both are excellent. Choose based on your team's preferences and infrastructure complexity.

Getting Started with Argo CD

Installation

# Create namespace
kubectl create namespace argocd

# Install Argo CD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Expose the UI (for local testing)
kubectl port-forward svc/argocd-server -n argocd 8080:443

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

Creating Your First Application

Create a Git repository with Kubernetes manifests:

# git-repo/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: app
          image: nginx:1.21
          ports:
            - containerPort: 80

Define an Argo CD Application:

# argocd-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/my-app-config
    targetRevision: HEAD
    path: k8s
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Apply it:

kubectl apply -f argocd-app.yaml

Argo CD will:

  • Clone your Git repository
  • Apply the manifests to the production namespace
  • Continuously sync on every Git commit
  • Self-heal if someone manually changes resources

Getting Started with Flux

Installation

# Install Flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash

# Bootstrap Flux on your cluster
flux bootstrap github \
  --owner=myorg \
  --repository=fleet-infra \
  --branch=main \
  --path=clusters/production \
  --personal

This command:

  • Creates a fleet-infra repository in your GitHub account
  • Installs Flux controllers in your cluster
  • Configures Flux to sync from the repository

Defining a GitRepository and Kustomization

# clusters/production/my-app-source.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/myorg/my-app-config
  ref:
    branch: main
# clusters/production/my-app-kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  path: ./k8s
  prune: true
  sourceRef:
    kind: GitRepository
    name: my-app

Commit these files to your fleet-infra repository. Flux will automatically apply your application manifests.

GitOps for Multi-Environment Deployments

A common pattern is using branches or directories for different environments:

Directory-Based (Recommended)

my-app-config/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
├── overlays/
│   ├── dev/
│   │   └── kustomization.yaml
│   ├── staging/
│   │   └── kustomization.yaml
│   └── production/
│       └── kustomization.yaml

Each environment has its own Argo CD Application or Flux Kustomization pointing to the appropriate overlay.

Staging Argo CD App:

spec:
  source:
    repoURL: https://github.com/myorg/my-app-config
    path: overlays/staging

Production Argo CD App:

spec:
  source:
    repoURL: https://github.com/myorg/my-app-config
    path: overlays/production

Branch-Based (Alternative)

  • dev branch → dev environment
  • staging branch → staging environment
  • main branch → production environment

This approach is simpler but can lead to drift between environments.

Benefits of GitOps

1. Complete Audit Trail

Every change is a Git commit. You can answer:

  • Who deployed version X?
  • When did this configuration change?
  • Why was this change made? (commit message)

2. Easy Rollbacks

Made a mistake? Revert the Git commit:

git revert HEAD
git push

GitOps agent automatically rolls back the deployment.

3. Disaster Recovery

If your cluster is destroyed, you can recreate it entirely from Git:

# Provision new cluster
# Install Argo CD or Flux
# Point it at your Git repo
# All applications and configs are restored

4. Enhanced Security

  • No need to distribute cluster credentials to CI systems
  • Git access controls dictate who can deploy
  • All changes go through code review

5. Developer Self-Service

Developers can deploy by merging PRs without needing cluster access or DevOps intervention.

Challenges and Best Practices

Challenge 1: Secret Management

Problem: You can't store secrets in Git in plain text.

Solutions:

  • Sealed Secrets: Encrypt secrets that only the cluster can decrypt
  • External Secrets Operator: Sync secrets from AWS Secrets Manager, HashiCorp Vault, etc.
  • SOPS: Encrypt YAML files with keys managed externally

Example with Sealed Secrets:

# Create a sealed secret
kubectl create secret generic my-secret --from-literal=password=supersecret --dry-run=client -o yaml | \
  kubeseal -o yaml > sealed-secret.yaml

# Commit sealed-secret.yaml to Git (safe)
git add sealed-secret.yaml
git commit -m "Add database password"

Challenge 2: Image Tag Updates

Problem: How do you update image tags in a GitOps workflow?

Solution: Use image automation controllers (Flux Image Automation, Argo CD Image Updater):

# Flux ImageUpdateAutomation
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
  name: my-app
spec:
  interval: 1m
  sourceRef:
    kind: GitRepository
    name: my-app-config
  git:
    commit:
      author:
        email: fluxbot@example.com
        name: Flux Bot
  update:
    path: ./overlays/production
    strategy: Setters

When a new image is pushed, Flux automatically updates the Git repository.

Challenge 3: Drift Detection

Problem: Someone manually edits resources in the cluster (they shouldn't, but it happens).

Solution: Both Argo CD and Flux detect and report drift. Enable self-healing:

# Argo CD
syncPolicy:
  automated:
    selfHeal: true

# Flux
spec:
  prune: true
  force: true

The agent will automatically revert manual changes to match Git.

GitOps Beyond Kubernetes

While GitOps is most commonly associated with Kubernetes, the principles apply to any infrastructure:

  • Terraform GitOps: Atlantis, Terraform Cloud, env0
  • AWS/Azure GitOps: CloudFormation, ARM templates in Git with automated deployment
  • Configuration Management: Ansible, Chef, Puppet playbooks in Git

Conclusion

GitOps isn't just a tool—it's a mindset. By treating Git as the single source of truth, you gain auditability, reliability, and velocity. Deployments become routine, rollbacks become trivial, and your infrastructure becomes code that your entire team can collaborate on.

Start small: pick one application, set up Argo CD or Flux, and experience the GitOps workflow firsthand. Once you see how powerful it is to deploy with a git push, there's no going back.

Ready to streamline your deployment workflows? Sign up for ScanlyApp and integrate GitOps best practices into your QA and delivery pipeline.

Related articles: Also see the CI/CD pipeline that makes GitOps workflows testable, testing the infrastructure code that your GitOps pipeline deploys, and deployment strategies that pair naturally with GitOps workflows.

Related Posts