Module 7: Gitops Beyond Terraform
3. GitOps for Kubernetes: ArgoCD and Flux, named
Description
The previous lesson showed you three tools that solve the same problem you already know, with different syntax. This lesson is different: ArgoCD and Flux aren't "GitHub Actions, but for Kubernetes" — they're a fundamentally different kind of system, designed specifically for a problem this guide never had: keeping a Kubernetes cluster's state continuously synced against what Git says should exist. You're going to meet what they are, what their configuration resources look like, and why this guide names them precisely instead of just saying "there are other options for Kubernetes" — without building or installing either one. This is a hard boundary: there's no Kubernetes cluster in this guide, and there won't be.
Connection to the module
Module 1, lesson 4, precisely flagged this lesson ahead of time: "Module 7 (lesson 4) revisits this distinction with the complete technical detail" — referring to push vs. pull. This lesson (3) is the necessary prior step: before comparing the two mechanisms in lesson 4, you need to meet, by name and concrete shape, the two tools that implement the pull mechanism in the real world. After this lesson and the next, lesson 5 moves one step further from infrastructure territory, toward an application's deployment strategies — another territory Kubernetes makes possible and that Terraform, by design, doesn't have.
Why this boundary is hard, not soft
You've already seen boundaries in this guide —end-to-end OIDC (Module 4), conftest as a system (Module 6)— where the reason for not building something was a specific technical limitation of act or the $0 scope. This boundary is different, and it's worth understanding why: ArgoCD and Flux need a real Kubernetes cluster (or at least a local one, like kind or minikube) to install and run — they're not a binary that runs on your Terraform HCL, they're controllers (software that runs inside the cluster, continuously watching its own state). There's no way to "simulate" this with act, because act simulates GitHub Actions runners, not Kubernetes clusters. Building this in depth —installing a cluster, installing ArgoCD inside it, connecting a repository, watching the first sync— is exactly kubernetes-and-eks-in-production-guide's content, a complete guide dedicated to that territory. This lesson gives you the vocabulary and the exact shape of those tools, so when you reach that guide —or a real job that uses them— it isn't the first time you're seeing them.
What ArgoCD is, precisely
According to its official documentation, Argo CD is "a declarative, GitOps continuous delivery tool for Kubernetes." It's a Cloud Native Computing Foundation (CNCF) project, accepted in 2020 and graduated —the highest maturity level the CNCF grants— in December 2022, which confirms it isn't an experimental project: it's production infrastructure used by thousands of organizations.
The mechanism, in its simplest form: you install ArgoCD inside your Kubernetes cluster (it runs as a set of Pods, just like any application that cluster can run). You tell it which Git repository to watch and which folder inside that repository holds the Kubernetes manifests (YAML for Deployment, Service, etc.) that describe the desired state. From there, ArgoCD continuously compares that desired state against what really exists in the cluster, and —if syncPolicy.automated is turned on— corrects any difference automatically, with nobody running a command.
ArgoCD's central resource is called Application — a CRD (Custom Resource Definition, the way Kubernetes lets you define your own resource types beyond native ones like Pod or Deployment). Here's what one looks like, verified against the official documentation:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: andes-cargo-shipment-api
spec:
source:
repoURL: https://github.com/andes-cargo/shipment-api-manifests.git
path: k8s/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
Read this with the same eye you'd read a Terraform resource with: source says where the desired state comes from (a Git repository and a folder inside it); destination says where to apply it (which cluster, which namespace); syncPolicy.automated with prune: true and selfHeal: true is the most important of the three — it tells ArgoCD to correct differences automatically (selfHeal: if someone changes something directly in the cluster, ArgoCD reverts it to match Git) and to delete resources no longer in Git (prune: if a Deployment gets removed from the repository, ArgoCD removes it from the cluster too). This is, with different names, exactly GitOps's property #4 you already know from Module 1 —continuous reconciliation— but taken to an extreme drift.yml (Module 5) never implemented: your drift.yml detects and warns; ArgoCD's selfHeal: true fixes it on its own, with no human intervention.
What Flux is, precisely
According to its official documentation, Flux is a way of managing infrastructure and applications so that the entire system is described declaratively and version-controlled, with an automated process that guarantees the deployed environment matches the state specified in one or more Git repositories. Like ArgoCD, it's a CNCF project — in fact, Flux was created by Weaveworks, the same company that coined the term "GitOps" in 2017 (Module 1, lesson 4) — Flux is, in a sense, the reference implementation of the concept that gave this entire domain its name.
Flux is organized into specialized controllers, more granular than ArgoCD's single Application. The two most important resources for understanding its basic shape:
GitRepository — tells Flux which repository to watch and how often:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: andes-cargo-shipment-api
namespace: flux-system
spec:
interval: 5m0s
url: https://github.com/andes-cargo/shipment-api-manifests.git
ref:
branch: main
Kustomization — tells Flux what to do with what it found in that repository (Flux uses this name because, by default, it expects manifests organized with Kustomize, Kubernetes's native tool for composing YAML — don't confuse it with this lesson's Kustomization, which is the name of Flux's controller, not the composition tool itself):
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: andes-cargo-shipment-api
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: andes-cargo-shipment-api
path: "./k8s/production"
prune: true
interval: 5m0s in GitRepository tells Flux how often to check the repository for new changes — that number (5m0s, Go's duration format) is, in a different format, the same kind of decision you made in Module 5 with schedule: cron: for drift.yml, except here it controls the complete sync, not just detection. sourceRef connects the Kustomization to the GitRepository by name — the same "one piece references another by name" pattern you already saw with needs: between GitHub Actions jobs (Module 5, lesson 3), applied here between two Kubernetes resource types instead of between two jobs in the same workflow.
ArgoCD and Flux, in quick contrast
| ArgoCD | Flux | |
|---|---|---|
| Origin | Intuit (2018) | Weaveworks (2016-2017, the same company that coined "GitOps") |
| CNCF status | Graduated (Dec. 2022) | Graduated |
| Central resource | Application (one per app) | GitRepository + Kustomization (separate, more granular) |
| Interface | Included web dashboard, widely used in practice | Mainly CLI (flux) and pure GitOps, no official included dashboard |
| Philosophy | One complete, visual tool | A set of specialized, composable controllers |
Neither one "wins" in an absolute sense — it's a team decision, similar in spirit to the GitHub Actions vs. Jenkins choice you already saw: ArgoCD is usually preferred when the team values a clear visual interface for seeing sync status at a glance; Flux is usually preferred by teams that want to compose smaller, specialized pieces, or that already use Kustomize heavily.
The point this lesson can't demonstrate, and why
There's no "What to expect" block in this lesson, and that's intentional, not an oversight: act doesn't run Kubernetes clusters, so none of the kubectl apply -f commands for the YAML above ever ran at any point while writing this lesson. If you wanted to confirm this syntax on your own, at $0, the real path would be installing kind (Kubernetes-in-Docker) or minikube on your machine, installing ArgoCD or Flux inside that local cluster, and connecting a real repository — exactly kubernetes-and-eks-in-production-guide's first modules' content. This lesson prepared you with the vocabulary and exact shape for that moment, not with the hands-on experience of having done it.
Common mistakes
Thinking ArgoCD/Flux are "a special GitHub Actions for Kubernetes" (the most common one). What happens: someone, after six modules thinking in terms of "a pipeline that runs steps," assumes ArgoCD is also a pipeline with steps, just pointed at Kubernetes. Why it happens: the word GitOps shows up in both contexts, and the brain reaches for the closest mental model it already has. How to spot it: if you look for something resembling steps: or jobs: in the Application YAML above and don't find it. How to fix it: ArgoCD and Flux don't have "steps" in a pipeline's sense — they're controllers that run continuously, comparing state, not a process that starts, runs a sequence, and ends. Lesson 4 develops this difference with the exact technical detail.
Confusing Flux's Kustomization with Kustomize, the tool. What happens: someone reads kind: Kustomization and assumes it's exactly the same as a kustomization.yaml file from Kubernetes's native Kustomize tool. Why it happens: the name is, on purpose, the same — and it's no coincidence, Flux builds on Kustomize. How to spot it: if you don't distinguish between "Flux's Kustomization CRD, which tells the controller what to sync" and "the kustomization.yaml file Kustomize uses to compose manifests inside a folder." How to fix it: they're two related but distinct things — Flux's Kustomization (this lesson's YAML) is the sync instruction; its path can point to a folder that does use Kustomize's kustomization.yaml to compose its manifests, or to a plain YAML folder with no Kustomize at all.
Believing this lesson gives you enough to install ArgoCD or Flux at a real job (overconfidence-based, already seen in lesson 1). What happens: someone reads this lesson's two YAML files and feels ready to configure Kubernetes GitOps in production. Why it happens: the examples are concrete and verified, and that creates a false sense of completeness. How to spot it: if you couldn't explain, without looking it up, how to install ArgoCD inside a cluster (the first step, before any Application exists to apply). How to fix it: this lesson gives you the resources' shape and vocabulary —Application, GitRepository, Kustomization, syncPolicy, selfHeal— not installation experience, RBAC configuration, secrets management inside the cluster, or real troubleshooting. That's, explicitly, kubernetes-and-eks-in-production-guide's content.
Exercises
Exercise 1 — Name each tool's central resource. Without looking at this lesson, what's the name of ArgoCD's main resource, and what are Flux's two main resources that work together?
See solution
ArgoCD: Application — a single CRD that groups source (where the desired state comes from), destination (where it gets applied), and syncPolicy (how it syncs). Flux: GitRepository (which repository to watch and how often) and Kustomization (what to do with what was found there, referencing the GitRepository by name via sourceRef) — two separate resources that work together, instead of ArgoCD's single resource.
Exercise 2 — Trace which GitOps property selfHeal: true implements. Of the four GitOps properties you learned in Module 1, lesson 4 (declarative, Git as source of truth, automatic application, continuous reconciliation), which one does ArgoCD's selfHeal: true implement, and how does it differ from how this guide implemented that same property?
See solution
selfHeal: true implements property #4: continuous reconciliation against Git. The difference from this guide: drift.yml (Module 5) implements that property passively — it runs terraform plan on a schedule and warns if something changed, but doesn't fix anything automatically (the fix requires someone to review the plan and approve an apply, just like any other change). selfHeal: true implements it actively — ArgoCD detects the difference and fixes it on its own, with nobody approving anything, the moment it detects it. It's a more aggressive design decision, with its own risks (what happens if someone changed something in the cluster on purpose, for a valid operational reason, and ArgoCD reverts it without asking?) this guide doesn't explore, because it's outside its scope.
Exercise 3 — Explain why this lesson doesn't have a "What to expect" block. In two or three sentences, explain to a colleague why, unlike almost every hands-on lesson in this guide, this lesson doesn't show any executed command's literal output.
See solution
A complete explanation sounds, roughly, like this: "Everything this guide has run so far ran with act, which simulates a GitHub Actions runner inside Docker — but ArgoCD and Flux aren't GitHub Actions workflows, they're controllers that run inside a real Kubernetes cluster (or at least a local cluster like kind). act has no way to simulate that, so there's no command this lesson could have really run without first installing a complete cluster — exactly the work that belongs to kubernetes-and-eks-in-production-guide, not this guide."
Summary and next step
In this lesson you met ArgoCD and Flux with technical precision: what they are (GitOps tools for Kubernetes, both graduated CNCF projects), what their central configuration looks like (Application in ArgoCD; GitRepository + Kustomization in Flux), and why selfHeal: true takes continuous reconciliation one step further than what drift.yml implements in this guide. You confirmed, with a hard, explained boundary, why this lesson names without building: neither tool runs without a real Kubernetes cluster, something that's, by design, outside this guide's scope.
Before moving on you should be able to: name ArgoCD's central resource and Flux's two; explain what selfHeal: true does and how it differs from drift.yml; and say, without hesitation, which ecosystem guide would teach you to actually install and use either one for real.
Lesson 4 takes everything you just learned and compares it, point by point, against the mechanism you did build in this guide — the exact technical distinction between push-based and pull-based GitOps, closing the thread Module 1 left open on purpose.
Resources
- Argo CD — Documentation — official ArgoCD documentation, the source for the definition and the
ApplicationYAML used in this lesson. - CNCF — Argo — ArgoCD's graduation status at the Cloud Native Computing Foundation.
- Flux — Concepts — official Flux documentation, the source for its definition.
- Flux — GitRepository and Flux — Kustomization — exact reference for the two CRDs used in this lesson.
- CNCF — Flux — Flux's graduation status at the CNCF, already cited in Module 1, lesson 4.
kubernetes-and-eks-in-production-guide(NIEVA) — the guide where ArgoCD and Flux really get installed and used, this lesson's hard boundary.