← Back to Home

GitOps From Scratch — Git as Your Deployment Engine

Visual guide to GitOps for Kubernetes. Compare ArgoCD vs FluxCD, understand pull-based deployment, repo structure patterns, and avoid common production pitfalls.

“Just push to Git and it deploys.” That’s the promise of GitOps. Your Git repository becomes the single source of truth for what runs in your cluster. No SSH’ing into servers. No CI pipeline with kubectl credentials. No “who deployed that?” Slack messages.

The cluster watches Git. When Git changes, the cluster changes. When someone manually edits the cluster, it gets reverted.

1. The GitOps Loop

GitOps is a continuous reconciliation loop. An agent inside the cluster constantly compares “desired state” (Git) with “actual state” (cluster). When they differ, the agent acts.

The GitOps Loop

Git is the single source of truth. The cluster converges to match what's in the repo.

1
Developer pushesChanges manifests in Git (K8s YAML, Helm, Kustomize)
2
GitOps agent detects diffArgoCD / FluxCD watches repo, sees desired ≠ actual
3
ReconciliationAgent applies changes to cluster: create, update, or delete resources
4
Drift detectionContinuous loop. If someone `kubectl edit`s manually, agent reverts it.
↻ Repeat

The key word is “declarative.” You don’t tell the cluster “run this command.” You declare “I want 3 replicas of this image.” The agent figures out what needs to change to get there. This is the same model as Kubernetes itself — desired state reconciliation — just extended to the deployment process.

2. Why Not Just CI/CD Push?

Traditional CI/CD works. You’ve been deploying from pipelines for years. But push-based deployments have a fundamental problem: your CI system needs cluster admin credentials. And there’s no mechanism to detect or fix drift.

Push Deploy vs GitOps (Pull)

Traditional (Push)
FlowCI builds → CI deploys to cluster
CredentialsCI needs cluster admin access
DriftManual changes persist forever
RollbackRe-run old pipeline (if you find it)
Audit trailCI logs (scattered, expire)
GitOps (Pull)
FlowCI builds → Agent in cluster pulls
CredentialsAgent only needs Git read access
DriftAuto-corrected to match Git
Rollbackgit revert → automatic
Audit trailGit history (permanent, signed)

The security improvement is significant. In push mode, your CI/CD system has write access to your production cluster — if it gets compromised, your cluster is compromised. In pull mode, the GitOps agent runs inside the cluster and only needs read access to a Git repo. The attack surface shrinks dramatically.

3. Repo Structure

The most common mistake in GitOps: putting Kubernetes manifests in the same repo as application code. This couples deployment to code changes, makes rollbacks messy, and gives all developers access to production configs.

Repo Structure — Two Repos, Not One

Separate application code from deployment manifests. Different lifecycles, different access.

App Repo
src/ tests/ Dockerfile .github/workflows/ci.yml
CI builds image, pushes to registry, updates image tag in config repo
→ image:tag →
Config Repo (GitOps)
base/ ├─ deployment.yaml ├─ service.yaml └─ kustomization.yaml overlays/ ├─ dev/ ├─ staging/ └─ prod/
ArgoCD watches this repo. Changes here = changes in cluster.

The two-repo pattern separates concerns cleanly. App developers push code → CI builds and pushes an image → CI opens a PR to the config repo updating the image tag → GitOps agent deploys the new image. Each step has its own review process, its own access controls, its own audit trail.

4. Picking Your Tool

ArgoCD and FluxCD are the two dominant GitOps tools. Both are CNCF projects. Both work well. The choice comes down to whether you want a dashboard or prefer pure CLI/CRD workflows.

ArgoCD vs FluxCD

FeatureArgoCDFluxCD v2
UIBeautiful web dashboardCLI only (Weave GitOps for UI)
Multi-clusterBuilt-in, central managementPer-cluster agents
Config toolsHelm, Kustomize, JsonnetHelm, Kustomize
Sync strategyManual or auto syncAlways auto-reconcile
RBACGranular project-levelK8s native RBAC
Image updateArgoCD Image UpdaterBuilt-in image automation
Learning curveMediumHigher (CRD-heavy)
Pick ArgoCD if you want a dashboard and multi-cluster from day one. Pick FluxCD if you prefer CLI-first, GitOps-native image automation, and tighter K8s integration.

If you’re new to GitOps: start with ArgoCD. The web UI is invaluable for understanding what’s happening. You can see sync status, diffs, resource health, and logs in one place. Once your team is comfortable with GitOps concepts, you can evaluate FluxCD if the CRD-native approach appeals to you.

5. Pitfalls

GitOps adoption fails not because the concept is wrong, but because teams underestimate the operational changes required. It’s a different workflow — and old habits (manual kubectl, direct cluster edits) actively conflict with it.

Pitfalls I've Seen in Production

⚠️
Secrets in Git (plaintext)GitOps means everything in Git — but secrets must be encrypted. Use SOPS, Sealed Secrets, or External Secrets Operator.
⚠️
Monorepo config for 50 appsOne config repo is fine for 10 services. At 50, ArgoCD's sync time slows, PRs conflict, and blast radius is the entire platform.
⚠️
No promotion strategySame manifests for dev and prod. Without Kustomize overlays or Helm values, you deploy untested configs to production.
⚠️
Manual kubectl editsSomeone "fixes" a prod issue with kubectl edit. ArgoCD reverts it 3 minutes later. Panic. The fix must go through Git.

The cultural shift is the hardest part. Engineers who’ve been SSH’ing into servers for 10 years don’t want to wait for a PR merge to fix a production issue. But that PR is your audit trail. That PR is your rollback point. That PR is what keeps your cluster state reproducible. The discipline is worth it.