Kubernetes · 3 min read
GitOps with Argo CD and Flux: when it helps and how to start
What GitOps actually changes about Kubernetes delivery, how Argo CD and Flux differ, and a low-risk way to begin.
By KubeCrew · Published
What GitOps changes
GitOps means the desired state of your cluster lives in Git, and software running in the cluster continuously makes reality match it. Instead of a pipeline pushing changes into the cluster with kubectl, a controller inside the cluster pulls from the repository and reconciles.
That small reversal has practical effects. Every change is a commit with an author, a review, and a timestamp. Rolling back is a revert. And because the controller keeps comparing the cluster to Git, manual changes made outside the process are detected, and optionally undone.
Why teams adopt it
- An audit trail for free: the history of the cluster is the history of the repository.
- Simple rollback, because the previous known-good state is already in Git.
- Drift detection and self-healing, so hand-edited resources do not silently diverge.
- Fewer credentials in CI. The pipeline needs to update a repository, not hold administrator access to every cluster.
Argo CD and Flux in brief
Argo CD and Flux are the two widely used GitOps controllers, and both are graduated projects in the Cloud Native Computing Foundation. They solve the same core problem with different shapes.
- Argo CD centers on an Application resource and ships with a web UI that shows sync status and the resource tree. It handles multiple clusters well and has ApplicationSets for generating many applications from a template.
- Flux is a set of focused controllers (source, Kustomize, Helm, notifications, image automation) configured with Kubernetes resources and driven mostly from the command line and Git.
Choosing between them
There is rarely a wrong answer. Teams that want a visual overview for developers and operators often prefer Argo CD. Teams that prefer a lighter, composable, CLI-first toolkit often prefer Flux. Pick one, standardize on it, and put effort into repository structure instead, which matters more than the controller.
Structure the repository on purpose
Keep application source code and environment configuration in separate repositories, or at least separate paths, so that a config change does not require a build and a code change does not accidentally change production. A common layout uses a shared base and per-environment overlays with Kustomize, and promotes a change from staging to production through a pull request.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/platform-config.git
targetRevision: main
path: apps/web/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: web
syncPolicy:
automated:
prune: true
selfHeal: trueHandle secrets without committing them
Git is not a place for plain-text secrets. Use an approach that keeps the repository safe to read: encrypt secrets in the repository with a tool such as Sealed Secrets or SOPS, or store them in an external secrets manager and let an operator sync them into the cluster.
Common pitfalls
- Automated pruning deletes resources that are removed from Git. Enable it deliberately, and start with it off for critical namespaces.
- Fields managed by other controllers, such as replica counts controlled by an autoscaler, can fight the reconciler unless you configure them to be ignored.
- Resource ordering matters. Custom resource definitions must exist before the resources that use them, so use the controller's ordering features.
- Helm values that change outside Git create exactly the drift GitOps is meant to remove. Keep values in the repository.
How to start with low risk
Pick one non-critical application in one namespace. Install the controller, point it at a repository, and begin with manual sync so you can see what it would change. Once the diff is boring, turn on automated sync, then add an alert for applications that stay out of sync. Expand one workload at a time, and leave anything fragile for later.