GitOps with Argo CD and Flux
Topic 43

GitOps with Argo CD and Flux

DeliveryGitOps

GitOps makes Git the single source of truth for what runs in a cluster. A controller in the cluster continuously compares the live state to the manifests in a Git repository and reconciles any difference. You change the cluster by changing Git; the controller does the applying.

It is the reconcile loop extended to delivery: desired state lives in version control, and a controller drives the cluster toward it, forever. Argo CD and Flux are the two dominant implementations.

The GitOps Model

GitOps reconciliation
Gitdesired state (manifests)
Controllerpulls & compares
Clusterreconciled to Git
Driftmanual change reverted

The principles are simple: the desired state of the system is declared in Git; a controller continuously pulls from Git and reconciles the cluster to match; and changes happen through Git commits and pull requests, not kubectl. This makes the repository an auditable, reviewable record of every change, gives you rollback by reverting a commit, and means the cluster self-corrects drift — if someone edits a live object, the controller changes it back to what Git says.

Pull vs Push

GitOps is pull-based: a controller inside the cluster watches Git and applies changes. This differs from push-based CI/CD, where a pipeline outside the cluster runs kubectl apply with cluster credentials. Pull-based is more secure (no cluster credentials handed to CI) and self-healing (drift is corrected continuously, not only at deploy time). It is the reason GitOps and plain CI deployment are different things, covered next topic.

Argo CD and Flux

Argo CD is application-centric with a strong UI: it models Application resources, shows sync status and diffs visually, and supports the app-of-apps pattern for managing many applications. Flux is a set of composable controllers, GitOps-toolkit style, with no built-in UI but deep native support for Helm and Kustomize sources. Both reconcile Git to cluster, detect drift, and sync; the choice is largely UI-and-app-centric (Argo) versus controller-and-composable (Flux).

An Argo CD Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web
spec:
  source:
    repoURL: https://github.com/example/manifests
    path: overlays/prod
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: shop
  syncPolicy:
    automated:
      selfHeal: true
      prune: true

Drift, Secrets, and Promotion

Three practical concerns. Drift and self-heal: with automated sync the controller reverts manual changes — powerful, but it means break-glass edits get undone unless you pause sync. Secrets: you cannot commit plaintext secrets to Git, so GitOps pairs with sealed secrets or an external secrets operator. Promotion: moving a change from staging to prod is a Git operation — a commit or PR that updates the prod path or image tag — which is what makes the whole pipeline auditable. A common structure is a separate repo or directory per environment.

Argo CD vs Flux

Argo CD — application-centric with a rich UI, sync diffs, and app-of-apps. Easy to see and operate visually.

Flux — composable GitOps-toolkit controllers, no built-in UI, deep Helm/Kustomize integration. Lean and modular.

Common Mistakes
  • Committing plaintext secrets to the GitOps repo — use sealed or external secrets.
  • Deploying with push-based CI credentials in parallel with GitOps, causing conflicting sources of truth.
  • Making manual kubectl changes that the controller silently reverts (self-heal) and being confused.
  • One giant repo for every environment with no separation, so a change can't be promoted cleanly.
  • Enabling auto-prune without understanding it can delete resources removed from Git.
Best Practices
  • Make Git the single source of truth; change the cluster only through commits and PRs.
  • Use pull-based reconciliation so no cluster credentials live in CI.
  • Handle secrets with sealed secrets or an external secrets operator, never plaintext in Git.
  • Separate environments by repo or directory so promotion is a clear Git operation.
  • Understand self-heal and prune before enabling them; pause sync for deliberate break-glass changes.
RelatedHelm / Kustomize — what the GitOps controller renders (Topics 41-42)CI/CD — where the pipeline hands off to GitOps (Topic 44)Secrets management — sealed/external secrets for GitOps (Topic 35)

Knowledge Check

What makes a delivery workflow GitOps?

  • Git is the source of truth and a controller continuously reconciles the cluster to it
  • A CI pipeline runs kubectl apply against the cluster on every commit merged to main
  • Manifests are stored as versioned artifacts in a container registry
  • Developers SSH to each node and apply manifests by hand

Why is pull-based GitOps more secure than push-based CI deployment?

  • The in-cluster controller pulls from Git, so cluster credentials never leave for any external system
  • It automatically encrypts every manifest and Secret stored at rest in the Git repository and registry
  • It does away with the need for any Git repository at all
  • It runs entirely without any in-cluster controller

Your manual kubectl edit keeps getting reverted under Argo CD. Why?

  • Automated self-heal reconciles the cluster back to what Git declares
  • A NetworkPolicy on the namespace blocked and rolled back the edit
  • Argo CD deleted the whole namespace and recreated it clean
  • The API server rejects all manual edits while GitOps is active

You got correct