Foundations · What Is GitOps, and Why

What Is GitOps, and Why

GitOps is the practice of keeping a Git repository as the single, versioned description of what a system should look like, and running an automated agent whose only job is making that description true — continuously, without a human running the command that applies it. That's the whole idea in one sentence. It exists because teams running Kubernetes at any real scale kept hitting the same three problems no amount of process discipline actually fixed: the cluster's live state quietly drifting away from whatever anyone last intended, deployments that behaved differently depending on which laptop or which CI runner happened to execute them, and no single place anyone could look to answer "what is actually supposed to be running right now." This page traces where the term came from — a 2017 blog post from a company called Weaveworks, not a committee — and makes the case for why GitOps specifically needs Kubernetes' declarative, reconciled API underneath it to work the way it's described, rather than being a rebrand of CI/CD that happens to use Git.

☺ Explain it like I'm 10

Imagine a fridge with a chore chart taped to the door: "always keep 3 juice boxes, 2 apples, 1 milk." Without the chart, everyone in the house restocks the fridge from memory, and memory is different for every person — one sibling swears there were supposed to be 4 juice boxes, another thought apples were optional this week. With the chart, nobody needs to remember or guess: you just open the fridge, compare it to the chart, and fix whatever's missing. GitOps is that chart, except the chart lives in Git, the "fridge" is your cluster, and instead of a sibling checking it once a day, a tireless little program checks it every few minutes, forever, and nobody has to argue about what the fridge was "supposed" to have in it — the chart already says.

🦉Your host for this topic: Professor Owl — the architect who starts every course with the mental model before anyone touches a manifest, and GitOps is a mental model wearing the clothes of a deployment tool.

Three problems that show up the moment nobody's watching closely enough

☺ Like you're 10: A cluster with a handful of deploys a week is easy to keep in your head. A cluster with dozens of teams shipping dozens of times a day is not — and "not easy to keep in your head" is exactly where these three problems live.

None of the three problems below are exotic. Every team that's operated a Kubernetes cluster past its first few months has lived at least one of them, usually without a name for it.

Config drift is the gap between what a cluster is supposed to be running and what it's actually running, opened by any change that bypasses the normal deploy path — someone runs kubectl edit at 2 a.m. to stop the bleeding during an incident, a well-meaning teammate bumps a resource limit by hand to fix an OOMKill and forgets to write it down anywhere, an autoscaler quietly changes a replica count nobody remembers is autoscaled. Every one of those changes is individually reasonable. The problem isn't any single edit — it's that nothing is comparing the live cluster against an intended state, so the gap between them only grows, silently, until something breaks in a way that makes someone go looking.

"Works on my machine" deploys is the Kubernetes-era version of a decades-old complaint, moved one layer up the stack. Containers were supposed to have ended this — the same image runs identically everywhere. But the deployment step usually didn't get the same treatment: one engineer's laptop has kubectl pointed at a slightly different context than they think, a CI job's Helm values file has drifted from what's actually documented, a manual helm upgrade run by hand from a bastion host behaves differently depending on whichever local chart version happens to be cached there. The artifact is reproducible. The act of getting that artifact running was, for years, whatever ad hoc combination of tools and habits a given person or pipeline happened to use that day.

Tribal knowledge of what's actually running is the compounding cost of the first two problems, and it's the one that hurts most during an incident. If drift has been accumulating for months and deploys have never gone through one consistent path, the honest answer to "what version of the checkout service is in production right now, and why" often lives in one senior engineer's memory rather than in any system a new hire — or a 3 a.m. on-call responder — can just go read. That's not a documentation problem you can fix by writing better runbooks; runbooks go stale the same way clusters drift. It's a problem of there being no single, current, checkable source that both humans and machines agree is the truth.

# The tribal-knowledge problem, made concrete: this command answers
# "what's running right now" — but not "why," or "was this reviewed"
$ kubectl get deployment checkout -n checkout -o jsonpath='{.spec.template.spec.containers[0].image}'
registry.example.com/checkout:1.4.2-hotfix3
# -hotfix3? Nobody on the team you can reach tonight remembers building
# that tag, let alone approving it. Nothing here says who, when, or why —
# only what the API server currently reports as true, right now.
Without GitOps With GitOps 🧑‍💻 A laptop CI pipeline A CI pipeline B Manual hotfix script ? Actual state unknown — no single record of why anything changed, or when Git repo one legible history 🤖 Reconciler runs inside the cluster Actual state always derivable by reading git observe, again — forever Config drift, mismatched deploys, and tribal knowledge all start here One path in. One place to read. "What's running?" has an answer.

Where the term actually came from

☺ Like you're 10: Nobody in a standards meeting invented this word — one company wrote down what they were already doing and gave it a name, in 2017.

The word "GitOps" was coined by Weaveworks, and it's specifically credited to Alexis Richardson, the company's co-founder and CEO, in a 2017 blog post describing how Weaveworks' own engineering team was running its Kubernetes-based product. The pitch wasn't abstract: Weaveworks' team had noticed that once you're deploying to Kubernetes, you already have a declarative description of what you want (a set of YAML manifests) and you already have the best tool humanity has for tracking versioned, collaboratively-reviewed changes to text (Git) — so why maintain a second, separate deployment tool at all when a pull request, merged to a repo a controller is already watching, does the whole job? That framing — "operations by pull request" — is the origin of the name, and it's worth noticing what it was not: it wasn't a new invention. Declarative infrastructure, version control, and continuous delivery all predate 2017 by years. What Weaveworks named was a specific combination already forming around Kubernetes' particular shape, not a technique nobody had used before.

Weaveworks didn't stop at naming it — the same team went on to build Flux, one of the two GitOps engines this course covers in depth, as the tool that put the idea into practice at their own customers. The GitOps community grew from there into what it is now: the CNCF's OpenGitOps project later took the informal idea and wrote it down as four precise, checkable principles (the subject of the next page), and a second major engine, Argo CD, emerged independently and now sits alongside Flux as the field's other dominant implementation. Both are graduated or incubating CNCF projects today, and both are covered across this course's Argo CD and Flux deep-dive tracks.

◆ Key idea

GitOps isn't a new invention bolted onto Kubernetes — it's a name for what falls out naturally once you notice that Kubernetes already wants a declarative description of state, and Git is already the best tool available for storing a declarative description of anything with full history and review built in. The insight was recognizing the fit, not building new machinery.

Why this is a Kubernetes/declarative-API story, not a general CI/CD rebrand

☺ Like you're 10: You can write down a wish list for almost anything, but GitOps only works this cleanly because Kubernetes already has a machine inside it whose entire job is reading wish lists and making them true, on its own, forever.

It's tempting to hear "store your desired state in Git and deploy from there" and file GitOps under "CI/CD, but the pipeline reads from Git" — genuinely just a rebrand. That undersells what's actually different, and the difference is specific: it's not about where the configuration lives, it's about what happens after it lands there.

Configuration management tools that predate Kubernetes by a decade or more — Puppet, Chef, Ansible, and later Terraform — are also declarative: you describe a desired state (packages installed, files present, cloud resources provisioned) rather than a sequence of steps. Plenty of teams already stored that declarative configuration in Git, reviewed changes as pull requests, and ran it from a pipeline on merge. None of that, on its own, is usually called GitOps, and the reason is the same one the OpenGitOps principles spell out precisely: a pipeline that applies configuration once, on merge, and then walks away has satisfied "declarative" and "versioned," but it has no ongoing mechanism to notice or correct anything that changes afterward. If a server the Ansible playbook configured yesterday drifts today — a package gets removed by hand, a config file gets hand-edited — nothing is watching for that unless someone re-runs the playbook, on purpose, again.

Kubernetes is different in one specific, structural way: it ships with its own reconciliation machinery already running, for every object it manages, all the time. A Deployment's controller doesn't apply the spec once and stop — it watches continuously, and if the real world drifts from the spec (a Pod gets deleted by hand, a node dies), the controller notices on its own next pass and corrects it, with nobody re-running anything. The reconciliation loop, explained covers this pattern in full, but the point for this page is narrower: a GitOps controller doesn't have to invent that continuous-correction machinery from scratch. It borrows the exact same pattern Kubernetes already uses internally for Pods and ReplicaSets, and simply points it at Git instead of only at objects already sitting in etcd. That's why GitOps grew up specifically around Kubernetes and its declarative API, rather than as a general practice that happens to apply equally well to configuring bare-metal servers or provisioning cloud VMs by hand — the continuous, automatic, self-correcting half of the definition needs a target that's already built to be continuously reconciled, and outside Kubernetes' API model, that target usually doesn't exist without someone building it themselves.

⚠ Watch out

"We run terraform apply from a GitHub Actions job on every merge" is a genuinely good practice, and it is not, by the definition this course uses, GitOps — it's CI-driven infrastructure delivery. It satisfies declarative and versioned, but nothing is continuously reconciling; drift between merges goes undetected until the next merge triggers another apply. Don't let a Git-triggered pipeline get called GitOps just because Git is in the sentence — the next page gives you the precise test.

✎ Try it

Pick any Kubernetes Deployment you have access to and run kubectl scale deployment/<name> --replicas=0, then immediately kubectl get deployment <name> -w. If nothing is reconciling it beyond the built-in ReplicaSet controller, it stays at zero. Now imagine that same manifest is watched by a GitOps controller with self-heal on, and Git still says replicas: 3 — that's the exact moment "continuously reconciled" stops being an abstract phrase and starts being something you'd actually notice.

🦆 Dot's-eye view

"Before any of this, shipping a fix meant SSHing into a bastion host, finding the right kubeconfig, and running a Helm command I half-remembered the flags for — and hoping I hadn't fat-fingered the namespace. Now I open a pull request that bumps an image tag, a teammate reviews it, and I never touch the cluster directly at all. I didn't learn a new deploy tool. I stopped needing one."

🎬 At the Sync Loop
🦉

Professor Owl: Before we open a single manifest, I want everyone to be able to answer one question: what problem is actually being solved here?

👺

Gizmo: Easy — deploying is annoying, so we made deploying involve more steps. Genius.

🦉

Professor Owl: One more step up front — open a PR instead of running a command — in exchange for a cluster that never silently drifts away from what anyone intended, and a history that says exactly why every change happened. That's not more steps, Gizmo, that's the same one step, just written down where everyone can see it.

🦆

Dot: Honestly the PR step feels the same as before to me. I just... don't SSH anywhere afterward anymore.

🦉

Professor Owl: Which is the whole trick. Weaveworks didn't invent a new motion for you — they noticed Kubernetes already had a machine that reconciles state forever, and pointed it at the one place your team already reviews changes.

👺

Gizmo: Still sounds like CI/CD with extra vocabulary to me.

🦉

Professor Owl: Then explain what your CI/CD pipeline does the moment someone hand-edits a Deployment at 2 a.m. and never tells it. Recon can answer that question. Your pipeline can't — it already finished running.

🐢 Timmy's checkpoint

1. Name the three problems this page describes as GitOps's original motivation, in your own words. 2. Who is credited with coining the term "GitOps," at what company, and in what year? 3. What tool did that same team go on to build? 4. A team runs terraform apply from a CI pipeline on every merge to main. Is that GitOps by this page's definition? Why or why not? 5. What specific capability does Kubernetes already have, before any GitOps tooling is added, that makes GitOps a natural fit for it rather than a general-purpose technique?

Check your answers
  1. Config drift (live cluster state silently diverging from intended state), "works on my machine" deploys (deployment behaving differently depending on who or what ran it), and tribal knowledge of what's actually running (no single, current, checkable source of truth for "what's live and why").
  2. Alexis Richardson, co-founder and CEO of Weaveworks, in a 2017 blog post.
  3. Flux, one of the two major GitOps engines this course covers.
  4. No — it's CI-driven delivery, not GitOps by this definition. It satisfies "declarative" and "versioned," but nothing continuously reconciles afterward; drift introduced between merges goes uncorrected until the next merge happens to trigger another apply.
  5. Built-in, continuous reconciliation — Kubernetes controllers already watch objects and correct drift from their declared spec automatically, all the time, without anyone re-running a command. GitOps tooling borrows that exact same always-on reconciliation pattern and points it at Git instead of only at objects already in etcd.