Module 5: Gitops With Argocd
1. Module introduction: the other half of GitOps
Description
Module 4 left andes-cargo-status-api with a real HTTP door (Ingress) and a real network guardrail (NetworkPolicy), both verified together in the previous project. But there's something that hasn't changed since Module 2, and this module is going to change it from the root: each of the nine manifests that exist today — namespace.yaml, deployment.yaml, service.yaml, configmap.yaml, secret.yaml, hpa.yaml, ingress.yaml, and the two NetworkPolicy — reached the cluster because you ran kubectl apply -f with your own hands, in your own terminal. That means andes-cargo-cluster, today, only knows what you told it directly — there's no place outside your terminal where anyone can see "this is what the cluster should have," and nothing watches whether the cluster keeps matching that intent over time. This module resolves exactly that: a real Git repository as the single source of truth, and an operator that lives inside the cluster, comparing it against that repository without anyone having to run anything by hand.
Connection to the module
This guide doesn't invent this idea's vocabulary — it inherits it, with a textual citation, from a sibling guide that already named it on purpose.
The thread cicd-and-gitops-on-aws-guide left open
cicd-and-gitops-on-aws-guide, in its Module 7 ("GitOps beyond Terraform"), built a complete push-based infrastructure pipeline: a git push to main triggers apply.yml, a GitHub Actions job runs terraform apply, and the change reaches AWS because a system external to AWS — the CI runner — pushes the credentials outward to write there. That same guide, in lessons 3 and 4 of that module, named — without installing anything, with an explicit hard boundary — the opposite mechanism:
"In the Kubernetes model with ArgoCD or Flux, an operator running inside the cluster constantly watches the Git repository and pulls the changes in when it detects them — this is called pull-based."
And, with even more precision, in its lesson 3:
"ArgoCD and Flux need a real Kubernetes cluster (...) to install and run on — they aren't a binary that runs on top of your Terraform HCL, they're controllers (...). Building this in depth — installing a cluster, installing ArgoCD inside it, connecting a repository, watching the first sync happen — is exactly the content of
kubernetes-and-eks-in-production-guide."
That citation points at you, right now, in this lesson. cicd-and-gitops-on-aws-guide gave you ArgoCD's Application YAML verified against official documentation, but never applied against a real cluster — it couldn't; act simulates GitHub Actions runners, not Kubernetes clusters. This module takes that same resource, the same syncPolicy.automated with prune: true and selfHeal: true that guide could only show on paper, and installs it, connects it to a real Git repository, and watches — with literal, not promised, evidence — how a real cluster converges.
What you're going to build, in one sentence
A real Git repository (served by Gitea, running inside your own kind cluster, with no GitHub account or SaaS involved) that holds Andes Cargo's nine manifests; an operator (ArgoCD, also running inside the cluster) that compares that repository against the real state every few seconds and corrects any difference without anyone running kubectl apply; and, as the final proof, a real change — bumping andes-cargo-status-api's replicas from 3 to 5 — that you're going to push to Git with git push and watch appear in the cluster without touching kubectl for anything other than observing.
FROM THIS (Modules 1-4) TO THIS (Module 5)
You, in your terminal A Git repository (Gitea, inside the cluster)
│ │
│ kubectl apply -f deployment.yaml │ git push
│ kubectl apply -f service.yaml │
│ kubectl apply -f ingress.yaml ▼
│ ... (every change, by hand) ┌───────────────┐
▼ │ ArgoCD │ compares every
andes-cargo-cluster │ (Application) │ few seconds
(state = the last └───────┬───────┘
thing you applied) │ corrects the difference
▼
andes-cargo-cluster
(state = what Git says,
always, with no intervention)
Analogy: the butler who checks the list, not the messenger who knocks on the door
Think of Modules 1-4 as a homeowner who, every time they want to change something — paint a wall, move a piece of furniture — has to do it personally, with their own hands, at the exact moment they decide to. It works, but it requires the owner to be present every single time. This module introduces a butler who lives inside the house: every few minutes, they check a to-do list the owner wrote in a notebook (the Git repository) and, if they find something on the list the house doesn't have yet — or something the house has that the list no longer asks for — they fix it themselves, without waiting for the owner to repeat it in person. The owner never stops deciding what goes on the list — Git is still the only source of truth — what changes is that they no longer have to be physically present, executing every change with their own hands, for the house to reflect their decisions.
This module's map
| # | Lesson | What it covers |
|---|---|---|
| 2 | Pull-based GitOps: an operator that watches, not a pipeline that pushes | The exact technical difference from apply.yml in cicd-and-gitops-on-aws-guide: there, a CI job runs the change; here, a Pod inside the cluster looks for it on its own |
| 3 | Hands-on: Gitea in the cluster | The real Git repository, running inside andes-cargo-cluster, with no GitHub |
| 4 | Hands-on: installing ArgoCD | The operator, running inside the cluster, with access to its UI |
| 5 | Anatomy of an ArgoCD Application | source, destination, syncPolicy — manual sync versus automated sync |
| 6 | Hands-on: syncing andes-cargo-status-api from Git | The first real convergence, verified with argocd app get |
| 7 | Deployment strategies: rolling, blue/green, and canary | RollingUpdate, already configured since Module 2, against what a cluster would need to add for blue/green or canary |
| 8 | Project: a Git change, reflected on its own | replicas: 3 → 5, pushed with git push, with not a single kubectl apply — the cluster converges on its own |
By the end of this module, andes-cargo-cluster is going to have an external, verifiable source of truth (a real Git repository, not your command history), and an operator that enforces it at all times — the piece that, until today, no earlier module of this guide built.
Common mistakes
Thinking this module replaces kubectl (expectation, the most common one when starting with GitOps). What happens: someone assumes that, after this module, kubectl apply stops making sense forever. Why it happens: the module's central promise — "no one runs kubectl apply by hand" — reads, if misread, as "kubectl isn't used anymore." How to spot it: if you think you're going to stop needing kubectl get/describe/logs for the rest of this guide. How to fix it: what this module eliminates is kubectl apply/create/delete as the mechanism for changing the cluster's state — kubectl remains, and is going to remain for the rest of this guide, the tool for observing that state (get, describe, logs, top). ArgoCD doesn't replace kubectl: it replaces the habit of using it to write.
Believing ArgoCD needs GitHub or some external SaaS (assumption, with no technical basis). What happens: someone, upon hearing "Git repository," automatically assumes a GitHub, GitLab, or Bitbucket account. Why it happens: in industry practice, most of the Git repositories people use daily do live on a service like that. How to spot it: if you're looking for where to create an account before lesson 3. How to fix it: ArgoCD speaks the standard Git protocol against any server that implements it — this guide uses Gitea, an open-source Git server, running inside the kind cluster itself, at $0 and with no external account. Lesson 3 builds it end to end.
Confusing "pull-based" with "slower because you have to wait" as an unqualified downside (simplification, picked back up from lesson 4 of cicd-and-gitops-on-aws-guide, which already warned about it). What happens: someone, upon learning that ArgoCD compares "every few seconds" instead of reacting instantly like a push, concludes that pull is strictly worse. How to spot it: if your conclusion is "this is slower, therefore worse." How to fix it: lesson 2 of this module picks back up the security-implications table cicd-and-gitops-on-aws-guide already built — pull latency is real, but it's traded for eliminating an entire category of risk (there are never write credentials traveling into the cluster from outside). Neither mechanism "wins" in the abstract.
Exercises
Exercise 1 — Cite this module's source, from memory. Without re-reading the corresponding section, write the exact sentence from cicd-and-gitops-on-aws-guide that distinguishes push-based from pull-based, and name the two tools that guide cited as real implementations of pull.
See solution
"In the Kubernetes model with ArgoCD or Flux, an operator running inside the cluster constantly watches the Git repository and pulls the changes in when it detects them — this is called pull-based." The two tools: ArgoCD and Flux. This guide builds the first of the two; Flux is named by contrast in lesson 2, without being installed — the same honesty pattern cicd-and-gitops-on-aws-guide used with both.
Exercise 2 — Explain the butler analogy to a colleague who never used GitOps. In two or three sentences, without using the word "GitOps," explain the difference between what you did in Modules 1-4 and what this module is going to build.
See solution
A reasonable explanation: "Until now, every time I wanted to change something on the cluster, I had to write the exact command and run it myself, at the exact moment I decided to. Starting with this module, I'm going to write the decision in a Git repository, and a program that lives inside the cluster is going to check that repository on its own, all the time, and apply the change itself — without me having to be present executing anything at the moment the change happens."
Exercise 3 — Predict what happens if someone deletes a Pod by hand after this module. With what you already know about selfHeal (named in this lesson's citation from cicd-and-gitops-on-aws-guide, even though you haven't seen it in action yet), predict: if someone runs kubectl delete pod against an andes-cargo-status-api Pod after ArgoCD is syncing this namespace with selfHeal: true, what would you expect to happen?
See solution
The Deployment's ReplicaSet is going to recreate the Pod immediately — that's normal Deployment behavior, already seen since Module 2, with no relation to ArgoCD. What selfHeal: true adds is an extra layer: if instead someone directly modified a Deployment field (for example, with kubectl scale or kubectl edit), ArgoCD would detect that difference against what Git declares and revert it too, without waiting for anyone to fix the mistake by hand. Lesson 5 of this module confirms it with real, executed evidence.
Summary and next step
This lesson connected this module with the thread cicd-and-gitops-on-aws-guide left open on purpose: the pull-based GitOps mechanism, precisely named in that guide but never built because it required a real Kubernetes cluster — exactly what this guide has had since Module 1. You saw the complete map of the eight lessons and the final promise: a change pushed to Git with git push, reflected on the cluster on its own, with not a single kubectl apply.
Before moving on you should be able to: cite the push vs. pull distinction from memory; explain why ArgoCD doesn't need GitHub; and name the three new pieces this module is going to install (Gitea, ArgoCD, and the Application object that connects them).
Next lesson: pull-based GitOps, the exact mechanism. There you're going to see, side by side, the diagram that compares apply.yml (the pipeline that pushes) against the operator this module is going to install (the one that pulls) — the same pair of diagrams cicd-and-gitops-on-aws-guide built on paper, now with the second one about to stop being paper.
Resources
cicd-and-gitops-on-aws-guide(NIEVA), Module 7, lessons 3 and 4 — the complete textual source of the push/pull distinction and theApplicationYAML this module actually installs.- Argo CD — Documentation — official documentation for the tool this module installs and operates end to end.
- Gitea — Documentation — official documentation for the Git server that serves as the repository for this entire module.
kubernetes-and-eks-in-production-guide(NIEVA), Module 4, lesson 8 — the exact state this module starts from:andes-cargo-status-apiwith realIngressandNetworkPolicy, nine manifests applied by hand.