ArgoCD and Flux: GitOps Basics for Kubernetes
What if your cluster could read a Git repository, compare it with reality, and quietly fix every difference on its own? This guide explains GitOps from the ground up, then walks through the two most popular tools, ArgoCD and Flux, so you can understand how they work and choose between them.
Picture a restaurant with a printed recipe book. Every dish has one official recipe, and every cook follows the book. If a cook adds extra salt on their own, a manager notices that the plate no longer matches the book and corrects it. If the owner wants to change a dish, they edit the book, and every kitchen follows the new version by the next day. Nobody walks around whispering changes from cook to cook, and anyone can open the book to see exactly how every dish is supposed to be made, and who changed it, and when.
GitOps brings this idea to Kubernetes. The recipe book is a Git repository. The cooks are the many objects running in your cluster, such as Deployments, Services, and ConfigMaps. The manager is a small program inside the cluster that keeps comparing the book with the kitchen and fixing differences. ArgoCD and Flux are the two best-known managers.
In this guide we move step by step. We begin with the ideas behind GitOps, then study ArgoCD, then Flux, then compare them. After that we cover the practical matters that decide success in real teams: how to organize repositories, how to handle secrets, how to promote changes between environments, how to secure the setup, and how to fix common problems. No earlier knowledge of either tool is assumed, and every new term is explained when it first appears.
1What Is GitOps?
GitOps is a way of running infrastructure and applications where a Git repository is the single source of truth for what should be running.
The Short Definition
Git is a tool for storing files together with their full history. Every change is recorded with who made it, when, and why, and any earlier version can be restored. GitOps means that you describe the desired state of your system in files stored in Git, and an automated agent makes the real system match those files. Instead of someone typing commands against the cluster, people propose changes to the files, the team reviews them, and the agent applies them.
The word “desired state” is important. It means a description of what you want, not a list of steps to get there. You do not say “start three copies of the payments service.” You write “the payments service should have three copies,” and the agent figures out what to do, whether that means starting new ones, stopping extra ones, or doing nothing because three are already running.
Think of a thermostat. You do not turn the heating on and off by hand. You set a target temperature, and the thermostat keeps checking the room and adjusting the heater to match. Git holds the target setting, and the GitOps agent is the thermostat for your cluster, constantly nudging reality toward what the repository says.
Why Teams Adopt It
Before GitOps, many teams deployed by running commands from laptops or from pipeline scripts. This works for a while, but problems appear as the system grows. Nobody can say for sure what is running in production. Two people change the same thing in different ways. A fix applied in an emergency is never written down and disappears the next time someone redeploys. New team members are afraid to touch anything because the real state lives only in the cluster and in a few people’s heads.
GitOps answers these problems directly. The repository always shows the intended state. Every change has an author and a reviewer. Rolling back means reverting a change in Git. Rebuilding a lost cluster means pointing a fresh cluster at the same repository. The result is a calmer, more predictable way of working.
GitOps is not a product you install. It is a working style. ArgoCD and Flux are tools that implement the style. You can follow the style with either, and the ideas you learn in this guide apply to both.
2Push Delivery vs Pull Delivery
The biggest practical difference between traditional pipelines and GitOps is who initiates the deployment: something outside the cluster, or something inside it.
The Traditional Push Model
In a classic continuous delivery pipeline, a build system compiles your code, runs tests, and then, as its final step, connects to the cluster and applies the new version. We call this push, because the pipeline pushes the change into the cluster. To do this, the pipeline needs credentials with the power to modify the cluster. Those credentials are stored in the build system, which usually has many users, many plugins, and a large attack surface.
Push also has a blind spot. After the pipeline finishes, it goes home. If someone later changes the cluster by hand, or a node crashes and loses an object, the pipeline knows nothing until the next run. The cluster can drift away from what was deployed, and nobody is told.
The GitOps Pull Model
In the pull model, an agent runs inside the cluster. It watches the Git repository and pulls changes when they appear. The pipeline’s job shrinks to building and testing the software and writing the new version number into the repository. It never needs cluster credentials. The agent, already inside the cluster, has the access it needs and nothing more.
flowchart LR
subgraph Push["Push model"]
P1["Code change"] --> P2["Build pipeline"]
P2 --> P3["Pipeline holds cluster credentials"]
P3 --> P4["Cluster"]
end
subgraph Pull["Pull model"]
L1["Code change"] --> L2["Build pipeline"]
L2 --> L3["Update Git repository"]
L4["Agent inside the cluster"] --> L3
L4 --> L5["Cluster"]
end
| Aspect | Push Delivery | Pull Delivery (GitOps) |
|---|---|---|
| Who applies changes | An external pipeline | An agent inside the cluster |
| Cluster credentials | Stored in the pipeline | Stay inside the cluster |
| Drift after deployment | Usually unnoticed | Detected and often corrected |
| Source of truth | Pipeline scripts and the live cluster | The Git repository |
| Rollback | Rerun an old pipeline | Revert a commit |
| Rebuilding a cluster | Replay many scripts | Point it at the repository |
Push is like a courier who has a key to every apartment and delivers packages inside. Pull is like each resident collecting their own parcels from a locker. The courier never needs a key, and a stolen courier uniform cannot open any doors.
GitOps does not replace your build pipeline. You still need automated builds and tests. GitOps changes only the last step: instead of pushing into the cluster, the pipeline updates the repository, and the in-cluster agent does the rest.
3The Four Principles of GitOps
The community behind GitOps has summarized the idea in four short principles. Both ArgoCD and Flux are built to follow them.
Declarative
The whole system is described as a statement of what should exist, not as a script of steps. Kubernetes already works this way, which is why GitOps fits it so naturally.
Versioned and Immutable
The desired state is stored in a way that keeps full history and cannot be quietly rewritten. Git provides exactly that, with every change recorded and reversible.
Pulled Automatically
Software agents automatically fetch the desired state from the source. Nobody has to remember to run a command for the change to take effect.
Continuously Reconciled
Agents keep checking the real state and try to bring it back to the desired state whenever the two differ, not only at the moment of a change.
Why Each Principle Matters
Each principle closes a different gap. Declarative descriptions mean the agent can work out the steps itself, so people do not have to write fragile scripts. Versioned storage means that disagreements are settled by looking at history, not memory. Automatic pulling removes human delay and human forgetfulness. Continuous reconciliation is the safety net: even if something outside the process changes the cluster, the agent notices and acts.
Whenever you are tempted to fix something directly in the cluster, ask yourself whether the fix would survive the next reconciliation. In a GitOps setup it usually will not, and that is the point. Make the change in Git instead.
4The Reconciliation Loop: How It Really Works
At the heart of every GitOps tool is a simple repeating cycle. Understanding it makes the behavior of both tools easy to predict.
Observe, Compare, Act
A reconciliation loop is a cycle that repeats forever. First the agent fetches the latest version of the repository. Second, it renders the files into the final Kubernetes objects, which may involve expanding templates. Third, it reads the real objects currently in the cluster. Fourth, it compares the two. Fifth, if they differ, it acts by creating, updating, or deleting objects until the cluster matches. Then it waits a short time and begins again.
flowchart TD
A["Fetch latest Git revision"] --> B["Render files into Kubernetes objects"]
B --> C["Read live objects from the cluster"]
C --> D{"Do they match?"}
D -- "Yes" --> E["Report healthy and in sync"]
D -- "No" --> F["Apply the difference"]
F --> G["Check health of the result"]
G --> E
E --> H["Wait, then repeat"]
H --> A
A Developer Proposes a Change
Someone edits the desired state, for example raising the number of copies of a service, and opens a request for review.
The Team Reviews and Merges
Colleagues read the exact difference, discuss it, and approve it. The merge creates a permanent record.
The Agent Notices the New Revision
Either by checking on a schedule or by receiving a notification from the Git host, the agent learns that the repository has changed.
The Agent Applies the Difference
It works out what must change and tells the cluster to make those changes, in a sensible order.
The Agent Reports Health
It watches the new objects until they are running properly and reports the outcome, so people can see whether the change worked.
Two Words to Remember: Sync and Drift
When the cluster matches the repository, we say it is in sync. When something differs, we say it has drifted. Drift can happen for innocent reasons, such as a person using a command to scale a service during an incident, or for worrying reasons, such as an attacker changing a setting. Both tools can show you the drift. They can also be told to fix it automatically, a feature often called self-healing.
Self-healing is powerful but surprising for people used to quick manual fixes. If you switch it on, tell your team first, otherwise their emergency edits will vanish within minutes and confusion will follow.
5ArgoCD at a Glance
ArgoCD is a GitOps tool for Kubernetes known for its rich web interface and its clear picture of what is running and whether it matches Git.
What It Is
ArgoCD is a continuous delivery tool that you install inside a Kubernetes cluster. It started within the Argo family of projects, which also includes tools for workflows, event handling, and progressive delivery, and it is now a graduated project of the Cloud Native Computing Foundation. You tell it which Git repository and which folder hold your desired state, and which cluster and namespace should receive it. It then keeps the two in step.
The feature most people notice first is its web interface. It shows every application as a graph of connected objects: the Deployment, the ReplicaSets it created, the Pods inside them, the Services in front of them. Each object has a color showing whether it is healthy, and a badge showing whether it matches Git. For a newcomer, seeing this picture explains Kubernetes better than many pages of documentation.
If GitOps is a recipe book system, ArgoCD is the manager with a big wall display in the kitchen. At a glance you see every dish, which ones follow the book, which ones have been altered, and which ones are burning. You can click a dish to see exactly what differs from the recipe.
What It Can Read
ArgoCD is not limited to plain files. It understands several ways of describing Kubernetes objects. It can read plain manifest files, Helm charts, which are packaged templates, Kustomize overlays, which let you customize a base description for different environments, and a few others. It converts them to final objects before comparing, so you can use whichever style your team prefers.
Visual Clarity
A live graph of resources with health and sync status makes the state of every application easy to understand, even for people new to Kubernetes.
Many Clusters, One Place
A single installation can deploy to many clusters, giving platform teams a central control point for the whole fleet.
Built-in Access Control
It has its own roles, projects, and single sign-on integration, so you can decide who may see or change which application.
Diff and Rollback
It shows the exact difference between Git and the cluster, and lets you return to an earlier recorded state with a few clicks.
6ArgoCD Architecture and Components
Behind the friendly screen, ArgoCD is a small team of cooperating programs, each with one clear job.
flowchart LR
U["Users and CLI"] --> API["API server"]
API --> CTRL["Application controller"]
CTRL --> REPO["Repo server"]
REPO --> GIT["Git repository"]
CTRL --> K8S["Target cluster"]
API --> CACHE["Redis cache"]
CTRL --> CACHE
API --> SSO["Single sign-on provider"]
API Server
The front door. It serves the web interface, the command-line tool, and the programmatic interface, and it enforces who may do what.
Repo Server
Fetches the repository and turns its files, including Helm charts and Kustomize overlays, into final Kubernetes objects. Keeping this separate isolates the risky work of running templates.
Application Controller
The brain of the reconciliation loop. It compares the rendered objects with the live cluster, computes the difference, and applies changes when allowed.
Cache
A Redis store that keeps recent results so the system does not need to recompute everything on each look.
Additional Controllers
Optional parts handle generating many applications from a pattern, and sending notifications to chat and email when something changes.
Identity Connector
Connects to your single sign-on provider so people use their normal company accounts instead of separate passwords.
How a Check Happens
By default, ArgoCD looks at the repository periodically, on the order of a few minutes, to see whether anything changed. You can make it react faster by configuring your Git host to send a notification the moment a commit lands. When a change is found, the repo server renders the files, the application controller compares the result with the cluster, and the application is marked either in sync or out of sync. If automatic syncing is enabled, the controller then applies the difference.
Because ArgoCD usually runs in one central cluster and reaches out to others, that central installation holds credentials for many clusters. Treat it like a critical piece of infrastructure: restrict access, keep it patched, and back up its configuration.
7Applications, Projects, Sync, and Health
ArgoCD has a handful of core ideas. Once you know these words, its screens and messages will make sense.
The Application
The central object in ArgoCD is the Application. It is a small record, itself stored as a Kubernetes object, that connects a source to a destination. The source says which repository, which revision, and which folder or chart to read. The destination says which cluster and which namespace to deploy into. One Application usually represents one deployable unit, such as a single service or a bundle of tightly related pieces.
The Project
An AppProject is a fence that groups applications and limits what they may do. A project can restrict which repositories its applications may read from, which clusters and namespaces they may deploy to, and which kinds of objects they may create. This is how a platform team lets many teams share one ArgoCD safely. A team can deploy freely inside its own fence and nowhere else.
Two Separate Statuses
ArgoCD reports two independent things, and mixing them up is a very common beginner mistake.
Sync Status: Does It Match Git?
- Synced means the live objects match the repository
- OutOfSync means something differs
- It says nothing about whether the application works
- Answers a question about configuration only
Health Status: Is It Working?
- Healthy means the objects are running properly
- Progressing means they are still starting
- Degraded means something is failing
- Answers a question about runtime behavior
An application can be perfectly synced and still degraded, for example when the configuration in Git is exactly what is deployed but the container keeps crashing. Likewise, an application can be healthy yet out of sync, for example when someone scaled it by hand. Always read both badges together.
Sync status is whether the dish was plated exactly as the recipe says. Health status is whether the dish tastes good and is hot. A dish can follow the recipe and still be burnt, or taste great and not follow the recipe.
Treating a green sync badge as proof that a release is fine. Sync only means the cluster follows Git. Always check health and your own monitoring before declaring success.
8Sync Policies, Waves, and Hooks in ArgoCD
Knowing that something is out of sync is only half the story. ArgoCD also lets you decide when and how the difference gets fixed.
Manual or Automatic Sync
By default an out-of-sync application waits for a person to press the sync button. This is manual sync, and it suits teams that want a human to confirm each change, especially in production. With automated sync, ArgoCD applies the difference by itself as soon as it detects one. Most teams use automatic sync in development and testing, and many choose either automatic or manual for production depending on their comfort level and change policy.
Two Switches That Change Behavior
Prune
When an object disappears from Git, prune also deletes it from the cluster. Without it, leftover objects stay behind forever, which can confuse everyone. With it, deletions in Git become real deletions, so use it with care.
Self-Heal
When someone changes a live object by hand, self-heal reverts it to match Git. This enforces the rule that Git is the truth, but it also removes quick manual fixes.
Ordering with Waves
Some applications need their pieces created in a particular order. A database schema must exist before the service that uses it. A namespace must exist before objects inside it. ArgoCD handles this with sync waves: you label objects with a wave number, and ArgoCD applies lower numbers first, waiting for each wave to become healthy before starting the next.
Hooks for Special Moments
Hooks are short tasks that run at particular moments of a sync. A pre-sync hook runs before anything else, perhaps to back up a database. A post-sync hook runs after everything is healthy, perhaps to run a smoke test or send a message. A failure hook runs when a sync goes wrong, perhaps to start a cleanup. Hooks let you add the small procedural steps that pure descriptions cannot express.
Pre-Sync Hooks
Preparation tasks, such as taking a backup or checking that a dependency is ready.
Sync Waves in Order
Objects are applied from the lowest wave to the highest, with health checks between waves.
Post-Sync Hooks
Verification tasks, such as a smoke test, that run once everything is healthy.
Failure Hooks if Needed
Cleanup or alert tasks that run only when the sync fails.
Start with automatic sync without prune in test environments, add prune once your team trusts the setup, and decide about self-heal in production based on how strict your change process is.
9Many Apps and Many Clusters: App of Apps and ApplicationSets
Real organizations have dozens of services and several clusters. Creating each Application by hand does not scale, so ArgoCD offers two patterns to automate it.
The App-of-Apps Pattern
Since an Application is just a Kubernetes object, it can be stored in Git and deployed like anything else. In the app-of-apps pattern, you create one parent Application whose source folder contains the definitions of many child Applications. When you sync the parent, ArgoCD creates all the children, and each child then deploys its own workload. Adding a new service becomes a matter of adding one small file to the folder.
It is like a table of contents that is also a set of instructions. The head chef’s master list names every station in the kitchen. When the master list changes, stations open and close accordingly, and each station follows its own recipes.
ApplicationSets
An ApplicationSet goes a step further. It is a template combined with a generator, a source of values that fills in the template to produce many Applications automatically. A generator might list clusters, so that the same service is deployed to every cluster. It might scan folders in a repository, so that every folder becomes an application. It might combine two lists, such as every service in every environment.
List
A fixed list of values written directly in the definition. Simple and good for a small number of targets.
Cluster
Produces one application for each cluster registered with ArgoCD, perhaps filtered by labels such as region or environment.
Git Directory or File
Looks inside a repository and creates one application per folder or per configuration file found there.
Matrix and Merge
Combines other generators, for example every service multiplied by every cluster, to cover large fleets with one definition.
Multi-Cluster Deployment
A single ArgoCD can manage other clusters once they are registered with it. The central installation then holds access to each target cluster. Some organizations prefer to run one ArgoCD per cluster instead, which avoids a central point of risk but gives up the single overview. Both approaches are valid, and the choice depends on how much you value central visibility versus isolation.
Use Case: A Regional Rollout
A company runs clusters in several regions. A cluster-based generator deploys a shared monitoring stack to every cluster labeled as production, and a new region receives the stack automatically the moment its cluster is registered and labeled.
10Flux at a Glance
Flux takes the same GitOps ideas and builds them as a set of small, focused controllers that live inside Kubernetes and speak its native language.
What It Is
Flux is a GitOps tool that is also a graduated project of the Cloud Native Computing Foundation. Its current generation is built as a collection of separate controllers, sometimes called the GitOps Toolkit. Each controller handles one concern, such as fetching sources, applying manifests, or releasing Helm charts. Together they form a complete delivery system, and you can install only the pieces you need.
Flux is designed to feel like part of Kubernetes itself. You configure it by creating ordinary Kubernetes objects, and you observe it using the same tools you use for everything else. There is no central server with its own database. The state lives in the cluster, in the objects the controllers manage.
If ArgoCD is a manager with a big wall display, Flux is a team of quiet specialists who each handle one job and leave notes on a shared board. One fetches the recipe book, one prepares the ingredients, one cooks, and one sends messages. There is no central screen unless you add one, but every specialist is dependable and works on its own.
Where It Shines
Kubernetes-Native
Everything is a Kubernetes object, so existing tools for access control, monitoring, and policy work on Flux resources too.
Composable
Because the controllers are separate, you can adopt only what you need and extend the system with your own parts.
Multi-Tenancy by Design
Teams can be given their own areas, and Flux can apply their changes using that team’s limited identity instead of a powerful shared one.
Image Automation
It can watch for new container images and write the new version back into Git, closing the loop automatically.
Flux does not ship with a built-in graphical interface. Most teams use its command-line tool and their normal monitoring and chat tools, and some add separate dashboards from the wider community. If a visual console matters a lot to you, factor that into your choice.
11The Flux Toolkit: Controllers and Their Jobs
Flux is easiest to learn when you meet its controllers one at a time and see how they pass work to each other.
flowchart LR
GIT["Git, OCI registry, or bucket"] --> SRC["Source controller"]
SRC --> KC["Kustomize controller"]
SRC --> HC["Helm controller"]
KC --> K8S["Cluster objects"]
HC --> K8S
IMG["Image reflector and automation controllers"] --> GIT
NC["Notification controller"] --> CHAT["Chat and alerts"]
KC --> NC
HC --> NC
Source Controller
Fetches content from Git repositories, container registries storing configuration, Helm repositories, and storage buckets, and makes it available to the others as a versioned package.
Kustomize Controller
Takes content from a source, builds it using Kustomize if needed, applies it to the cluster, and keeps it reconciled. It also checks the health of what it applied.
Helm Controller
Installs and upgrades Helm charts, treating each release as a declared object, and can roll back when an upgrade fails.
Notification Controller
Sends alerts about what Flux is doing to chat tools and other systems, and can also receive incoming notifications from Git hosts so changes are noticed immediately.
Image Reflector Controller
Scans container registries and records which image versions exist, so other parts can decide which one to use.
Image Automation Controller
Updates files in Git when a newer image matching your rules appears, so the repository stays the record of what runs.
Getting Started: Bootstrap
Flux comes with a command-line tool that performs a bootstrap. This one step installs the controllers into your cluster and also commits their own configuration into your repository. From that moment, Flux manages itself from Git: upgrading Flux means changing a file and letting Flux apply it. This self-managing property is one of the most elegant parts of the design.
Flux has an object called a Kustomization, and the Kustomize tool has a file with a similar name. They are different things. The Flux object tells a controller where to find content and how to apply it. The Kustomize file describes how to customize a base set of files. They are often used together, which makes confusion easy.
12Sources, Kustomizations, and HelmReleases
Flux’s everyday work revolves around a few object types. Learn these and you can read almost any Flux setup.
Sources: Where Things Come From
A source object tells Flux where to look and how often. A Git source names a repository and a branch. An OCI source points to configuration packaged in a container registry, which is increasingly popular because registries are fast and well protected. A Helm repository source points to a collection of charts. A bucket source points to object storage. Each source produces a verified, versioned snapshot that downstream objects can use.
Kustomizations: How Content Is Applied
A Flux Kustomization connects a source to the cluster. It names a source and a path inside it, says how often to reconcile, and can specify extras: whether to delete objects that disappear from Git, which health checks to wait for, which other Kustomizations must finish first, and even which identity to use when applying. That last option is how teams are kept inside their own boundaries.
HelmReleases: Charts as Declared Objects
A HelmRelease describes a Helm chart installation as an object: which chart, which version, which settings. The Helm controller watches it and makes the real release match, upgrading when the description changes and optionally rolling back on failure. This turns what is normally a manual command into a reviewed, repeatable, Git-managed record.
| Flux Object | Plain Meaning | Typical Question It Answers |
|---|---|---|
| Git Source | A repository and branch to watch | Where is the desired state? |
| OCI Source | Configuration stored in a registry | Can we deliver config like an image? |
| Helm Repository | A catalog of charts | Where do the charts live? |
| Kustomization | Apply this path from that source | What gets applied and how? |
| HelmRelease | Install this chart with these settings | Which chart version runs here? |
A Source Fetches
The source controller checks the repository on a schedule and records a new snapshot when something changes.
A Kustomization Notices
The controller watching that source sees the new snapshot and prepares to apply it.
Dependencies Are Respected
If this Kustomization depends on another, such as one that installs shared infrastructure, it waits until that one reports ready.
Objects Are Applied and Checked
The controller applies the difference and waits for configured health checks before declaring success.
Flux orders work through explicit dependencies between objects rather than numbered waves. If your infrastructure must exist before your applications, declare that dependency and Flux will respect it.
13Image Automation and Notifications in Flux
Flux can close the loop between a new container image and the repository, and it can keep people informed without anyone watching dashboards.
Updating Git Automatically
When your pipeline builds a new container image, someone must update the repository so the new version is deployed. Many teams do this with a small script in the pipeline. Flux offers a built-in alternative. One controller scans your registry for new image tags. You describe a rule for which versions are acceptable, for example “newest within the stable series.” Another controller then edits the files in Git, commits the change, and pushes it. The usual reconciliation loop deploys the result.
The key point is that the change still passes through Git. The automation writes a commit like any person would, so the history stays complete and a rollback remains a simple revert.
Imagine a supplier who delivers new ingredients. A diligent assistant checks the delivery against your rules, and if the new batch is acceptable, writes it into the recipe book with a signed note. The kitchen then follows the book as usual. The assistant never cooks, and the book remains the truth.
Staying Informed
The notification controller sends messages about important events, such as a failed reconciliation or a successful deployment, to chat tools and other systems. You choose which events matter and where they go. It can also work in the other direction: it can receive a signal from your Git host or registry when something changes, so Flux reacts immediately instead of waiting for the next scheduled check.
Failures
Notify the owning team the moment a reconciliation fails, with the reason, so problems are fixed before users notice.
Successful Deployments
Post a short message when a new version lands, giving the team confidence and a record of what changed.
Instant Triggers
Accept signals from the Git host so a merged change is applied within moments, not minutes.
Commit Status Updates
Report the outcome of a deployment back to the Git host, so the pull request shows whether the change actually worked.
Automatic image updates that commit to the same branch your team uses can create noisy history and surprise merges. Many teams give the automation a separate branch or a separate path, and review its changes like any others.
14ArgoCD vs Flux: Choosing Between Them
Both tools follow the same principles and both are mature, graduated projects. The better choice depends on what your team values most.
| Aspect | ArgoCD | Flux |
|---|---|---|
| Overall style | A central application with a rich interface | A set of small controllers working together |
| Graphical interface | Built in and a major strength | Not built in; add-ons exist |
| Main unit | Application | Source plus Kustomization or HelmRelease |
| Multi-cluster | Central instance can manage many clusters | Typically one instance per cluster, managed from Git |
| Ordering | Sync waves and hooks | Explicit dependencies between objects |
| Access control | Its own roles, projects, and single sign-on | Standard Kubernetes access control and impersonation |
| Helm handling | Renders charts and applies the result | Runs real Helm releases through a dedicated controller |
| Image automation | Via a companion add-on | Built into the toolkit |
| Learning curve | Gentle start thanks to the interface | Steeper at first, then very consistent |
Choose ArgoCD When
- You want a visual overview for developers and managers
- A central platform team serves many application teams
- You need project-level fences and single sign-on out of the box
- You manage many clusters from one place
- Teams are newer to Kubernetes and benefit from the graph view
Choose Flux When
- You prefer everything to be plain Kubernetes objects
- You want small parts you can adopt and combine
- You rely on native Kubernetes access control for tenants
- You want built-in image update automation
- Your team is comfortable without a built-in dashboard
Teams succeed with both. The skills transfer between them, because the ideas of desired state, reconciliation, and Git as the truth are identical. Pick one, learn it well, and invest in good repository structure, which matters far more than the tool.
15Structuring Your Git Repositories
The tools are the easy part. How you lay out your repositories decides whether GitOps feels pleasant or painful a year from now.
Application Code and Configuration: Keep Them Apart
The most widely recommended habit is to keep application source code in one repository and deployment configuration in another. The reason is practical. Code changes constantly, with many commits that have nothing to do with deployment. If configuration lives beside code, every code commit risks triggering the agent, and the history of deployments gets buried in noise. A separate configuration repository has a clean history in which every commit means “something about what runs has changed.”
There is a security reason too. The people who may edit code and the people who may approve production changes are not always the same. Separate repositories make it simple to give each group the right permissions.
Environments: Folders, Not Branches
A common beginner idea is to use one branch per environment, such as a development branch and a production branch. It looks tidy but tends to cause trouble: branches drift apart, merges become confusing, and it is hard to see at a glance how environments differ. Most experienced teams prefer one branch with a folder for each environment. A shared base holds what is common, and small overlays in each environment folder hold only the differences. Comparing environments becomes a simple comparison of folders.
flowchart TD
R["Configuration repository"] --> B["base: shared description"]
R --> E1["environments: development"]
R --> E2["environments: staging"]
R --> E3["environments: production"]
B --> E1
B --> E2
B --> E3
R --> I["infrastructure: shared services"]
R --> C["clusters: what each cluster should run"]
One Repository for Everything
Simple for small teams, with one place to look and one history. It gets crowded as teams multiply and permissions become harder to separate.
One Repository per Team
Each team owns its configuration and its permissions. A central repository defines which team repositories each cluster follows.
Platform and Application Split
A platform team owns shared services, such as ingress, monitoring, and policies, in one repository, while application teams own their own services elsewhere.
Cluster Definitions
A top-level folder lists exactly what each cluster should run, so rebuilding or adding a cluster means adding one entry.
Copying whole files between environment folders leads to slow, invisible divergence. Share a base and override only the differences, so a change to common settings happens in one place.
16Managing Secrets Safely
If Git holds everything, what about passwords and keys? The answer is never to put them there as plain text.
The Problem
Git history is permanent and widely copied. A password committed once, even if deleted in the next commit, remains in history and in every clone. It is also visible to everyone with read access to the repository. At the same time, GitOps wants the cluster to be fully described by the repository. These two facts seem to clash, but the community has found three reliable solutions.
Encrypt Before Committing
The secret is encrypted on a developer machine using a public key, and only the encrypted form is stored in Git. A controller in the cluster holds the private key and decrypts it into a real secret. Sealed Secrets is a well-known tool built on this idea.
Encrypt with a Key Service
Files are encrypted with keys held in a cloud key service or similar, and the GitOps tool decrypts them when applying. Flux supports this natively with the SOPS tool, and ArgoCD supports it through plugins.
Keep Secrets Outside Git
Git stores only a reference, such as “fetch the database password named payments-db.” An operator in the cluster, like External Secrets Operator, retrieves the real value from a dedicated secrets manager at runtime.
Choosing an Approach
| Approach | Secret Lives In | Best When | Watch Out For |
|---|---|---|---|
| Encrypt before committing | Git, encrypted | You want everything in one place and simple tooling | Losing the private key means losing the secrets |
| Key service encryption | Git, encrypted with managed keys | You already use a cloud key service | Access to the key service becomes critical |
| External secrets manager | A dedicated secrets system | Compliance needs central rotation and auditing | An extra system that must be highly available |
A recipe book can say “add the secret spice from the locked cabinet” without ever writing the spice blend on the page. Anyone can read the book, but only the cooks with the key can open the cabinet. Writing the blend in plain ink would let every visitor copy it.
Do not store secrets in plain text in Git, even in a private repository, and do not assume that a plain Kubernetes Secret is encrypted. Its contents are only encoded, which anyone can reverse. Treat it as readable by anyone with access.
17Helm and Kustomize in a GitOps World
Plain files become repetitive quickly. Helm and Kustomize are two popular ways to avoid repetition, and both tools support them well.
Kustomize: Layers of Customization
Kustomize starts with a plain base description and applies layers of changes on top, called overlays. A production overlay might raise the number of copies and set larger memory limits, while a development overlay keeps everything small. The base stays clean and readable, and each overlay is short. Because Kustomize works with ordinary Kubernetes descriptions and needs no special syntax, many teams find it the most natural fit for GitOps.
Helm: Packaged Templates
Helm packages an application as a chart, a bundle of templates and default settings. You supply a small set of values to customize it. Helm is very popular for installing third-party software, because most open-source projects publish a chart. It is also used for in-house applications where many similar services share one template.
Kustomize Strengths
- No templating language to learn
- Output is easy to predict and review
- Great for per-environment differences
- Built into the Kubernetes command-line tool
Helm Strengths
- Huge ecosystem of ready-made charts
- Powerful templating for complex logic
- Versioned packages with clear upgrades
- Good for sharing one design across many services
How the Two Tools Treat Them
ArgoCD renders Helm charts into plain objects and then applies and tracks those objects, rather than running a traditional Helm install. This means it sees and compares each individual object, which gives its interface a detailed view. Flux, by contrast, drives real Helm releases through its Helm controller, so the usual Helm history and rollback features remain available. Neither approach is wrong. They differ in which familiar feature set you keep.
Use Case: Third-Party Software with Local Tweaks
A team installs a popular monitoring stack from its public chart, pins the chart to an exact version in Git, and keeps their own small file of setting overrides beside it. Upgrading means changing the version number in a reviewed change, and the diff shows exactly what will differ.
Always pin charts and base images to exact versions in Git. A moving target such as “latest” defeats the purpose of GitOps, because the repository no longer fully determines what runs.
18Promotion and Progressive Delivery
Getting a change to production safely means moving it through environments and, ideally, releasing it gradually instead of all at once.
Promoting Between Environments
Promotion means moving a tested version from one environment to the next. In GitOps this is simply a change in Git: the version number in the staging folder is copied into the production folder through a reviewed change. Because both are just files, the pull request shows exactly what is being promoted, who approved it, and when. Some teams automate the first steps, such as development to staging, and keep production as a deliberate human approval.
Build and Test
The pipeline builds the application, runs tests, and publishes a new image with a unique version.
Update Development
The new version is written into the development folder automatically, and the agent deploys it.
Promote to Staging
After checks pass, the same version is written into the staging folder, often by automation.
Approve for Production
A person reviews the change that moves the version into the production folder. The review is the approval gate.
Observe and Decide
Monitoring confirms health. If something is wrong, reverting the production change restores the previous version.
Releasing Gradually
Even a well-tested change can surprise you in production. Progressive delivery reduces the risk by exposing the new version to a small share of users first, measuring how it behaves, and only then widening the rollout. Two common styles exist. In a canary release, a small percentage of traffic goes to the new version while the rest stays on the old one. In a blue-green release, the new version runs alongside the old one and traffic is switched over all at once after checks pass, with a quick way back.
Both GitOps tool families have companions for this. The Argo family offers Argo Rollouts, and the Flux family offers Flagger. They plug into the same Git-driven flow: you declare the rollout strategy in Git, and the companion controls the gradual traffic shift and automatic rollback on bad metrics.
A restaurant testing a new dish serves it to a few tables first and watches their reactions. If they love it, it goes on the full menu. If they send it back, the kitchen quietly returns to the old recipe, and most guests never notice.
19Security in a GitOps Setup
GitOps changes where the power sits. Securing the repository and the agent becomes as important as securing the cluster.
Git Is Now the Control Plane
If the repository decides what runs in production, then anyone who can merge to it can change production. Protect the repository accordingly. Require reviews, restrict who can approve production changes, use protected branches so nobody can push directly, and consider requiring signed commits so that changes can be tied to verified identities. The review process you already know from code becomes your change-approval process.
The Agent’s Power
The agent inside the cluster usually has broad permissions, since it must create all kinds of objects. Limit it where you can. Use projects in ArgoCD or impersonation in Flux so that each team’s changes are applied with that team’s limited identity instead of a cluster-wide one. Run the agent with the least privilege that works, and restrict who can reach its interface or its objects.
The Repository
Protected branches, mandatory reviews, signed commits, and limited approvers keep unauthorized changes out of production.
The Credentials
The agent needs read access to Git, preferably read-only and scoped to one repository, and credentials for any other clusters it manages. Store and rotate them carefully.
The Boundaries
Separate teams with projects or namespaces and limited identities, so one team’s mistake or compromise cannot spread.
The Supply Chain
Pin versions, verify the origin of images and charts where the tools support it, and scan what you deploy so that trusted sources feed the pipeline.
Because the agent pulls from inside the cluster, you no longer need to store cluster-admin credentials in your build system. That removes one of the most attractive targets from your delivery pipeline.
Admission rules and policy tools still matter. GitOps ensures that what is in Git gets applied, but it does not judge whether what is in Git is safe. Combine GitOps with policy checks so that bad changes are stopped even when they are correctly merged.
20Reliability, Scale, and Disaster Recovery
A tool that deploys everything must itself be dependable. Plan for its failure and for the failure of the clusters it manages.
What Happens If the Agent Is Down?
The good news is that your applications keep running. The agent only reconciles; it is not in the path of user traffic. If it stops, nothing breaks immediately. You simply lose automatic updates and drift correction until it returns. Once it comes back, it catches up with the repository. Still, you should monitor the agent and alert when it stops, because a silent agent means silent drift.
Rebuilding from Nothing
One of GitOps’s greatest gifts is simple disaster recovery. If a cluster is destroyed, you create a new one, install the agent, and point it at the same repository. The agent recreates everything that Git describes. The speed of recovery depends on how much of your state lives in Git. Data in databases and volumes is not in Git, so it needs its own backup plan, but your configuration comes back automatically.
Create a Fresh Cluster
Provision empty infrastructure, ideally also described in code so it can be repeated.
Install the Agent
Bootstrap ArgoCD or Flux and give it access to the repository and the keys needed to decrypt secrets.
Let It Reconcile
The agent rebuilds shared infrastructure first and then the applications, following the declared order.
Restore Data Separately
Bring back databases and volumes from backups, since Git holds configuration but not data.
Verify and Redirect Traffic
Confirm health and then switch users to the recovered cluster.
Scaling to Many Applications
As the number of applications grows into the hundreds, the agent must read repositories, render files, and compare many objects. Both tools can be scaled: ArgoCD by spreading its controller work across several instances, and Flux by running controllers with more resources or sharding. Keep individual repositories and applications reasonably small, because a huge application takes longer to render and compare and makes every change riskier.
Disaster recovery that has never been tried is a hope, not a plan. Periodically rebuild a test cluster from the repository and note what was missing, such as a forgotten secret or a manually created object. Each gap you find is a gap in your GitOps discipline.
21Monitoring, Logging, and Notifications
A GitOps system should tell you when it is unhappy, ideally before your users do.
What to Watch
Both tools publish metrics in a standard format that monitoring systems understand. These tell you how many applications are in sync, how many are failing, how long reconciliations take, and how often the agent encounters errors. Chart these and set alerts on the important ones. A sudden rise in failures or a flat line of no activity both deserve attention.
Sync State
How many applications are out of sync, and for how long. A few minutes during a rollout is normal. Hours is a warning.
Reconciliation Duration
How long each cycle takes. Growth over time suggests applications that are too large or an overloaded agent.
Failures and Errors
Failed syncs, rendering errors, and authentication problems with Git. These often explain why a change never arrived.
Agent Health
Whether the agent itself is running and recently active. A silent agent hides every other problem.
Telling People
Connect notifications to the chat tools your teams already use. Useful messages include a deployment started, a deployment succeeded, a sync failed with its reason, and an application degraded after a change. Send each message to the team that owns the application, not to a crowded shared channel, so that alerts are acted on instead of ignored.
flowchart LR
A["GitOps agent"] --> M["Metrics"]
A --> L["Logs"]
A --> N["Notifications"]
M --> D["Dashboards and alerts"]
L --> T["Troubleshooting searches"]
N --> C["Team chat channels"]
G["Git history"] --> H["Audit trail of who changed what"]
Git history is itself an audit log. To answer “who changed this and why,” you read the commit and its review. Make commit messages and pull request descriptions meaningful, and the log becomes genuinely useful during incidents.
22Anti-patterns and Best Practices
Teams that adopt GitOps tend to stumble in the same places. Knowing them in advance saves months.
Problem
Engineers keep fixing production directly with command-line edits, “just this once,” and never update the repository.
Why It’s Harmful
Git no longer describes reality. With self-healing on, the fix vanishes within minutes, and with it off, the cluster silently drifts. Either way, trust in the repository erodes, and the next deployment may undo the fix without warning.
Correct Approach
Treat Git as the only way to change production. For true emergencies, allow a documented break-glass procedure, and require that the same change be committed to Git as soon as the incident ends.
Problem
Secrets are committed as plain text because “the repository is private.”
Why It’s Harmful
Anyone with read access, any laptop that cloned the repository, and any backup of it now holds the secrets, and history keeps them forever even after deletion.
Correct Approach
Use one of the three safe approaches from Chapter 16, rotate any secret that was ever committed in plain text, and add automated scanning to catch mistakes early.
Problem
The same deployment is driven by both a pipeline that pushes into the cluster and a GitOps agent that pulls from Git.
Why It’s Harmful
The two fight over the same objects. The pipeline applies one version, the agent reverts it to another, and nobody knows which is the truth.
Correct Approach
Choose one path to the cluster. Let the pipeline build and test, and let it end by updating Git, with the agent as the only component that touches the cluster.
Problem
Automatic pruning and self-healing are switched on everywhere on day one, including production, without the team understanding them.
Why It’s Harmful
A mistaken deletion in Git becomes a real deletion in the cluster within minutes. A badly structured repository can remove more than anyone intended.
Correct Approach
Introduce automation gradually. Begin in test environments, learn how deletions and drift behave, add protective markers to critical objects, and then expand to production.
Best Practices at a Glance
Do
- Keep application code and configuration in separate repositories
- Use folders and overlays for environments, not long-lived branches
- Pin charts, base images, and tool versions to exact versions
- Require reviews and protect branches, especially for production
- Store secrets encrypted or outside Git, never in plain text
- Alert on failed syncs and on a silent agent
- Practice rebuilding a cluster from the repository
- Write meaningful commit messages and review descriptions
Do Not
- Edit live objects by hand and leave Git unchanged
- Use floating tags such as the latest image
- Copy whole folders between environments
- Mix push-style pipelines with a pulling agent on the same objects
- Create one giant application containing everything
- Grant the agent more access than it needs
- Ignore out-of-sync warnings until they pile up
23Troubleshooting Common Problems
Most GitOps problems fall into a handful of patterns. A calm checklist finds the cause faster than guesswork.
Problem: It Is Always Out of Sync
This is the most common puzzle. You merge a change, the agent applies it, and a moment later the application is out of sync again. Usually another system is changing the same field. An autoscaler may adjust the number of copies, an admission webhook may add default values, or a controller may write extra information into an object. Each time the agent compares, it sees a difference and tries to correct it, while the other system changes it back.
The cure is to tell the tool which fields to ignore, or better, to stop describing those fields in Git. If an autoscaler controls the number of copies, do not also hard-code that number in the repository. Both tools offer a way to ignore specific differences.
Problem: The Change Never Arrived
Work from the outside inward. Did the change actually reach the branch the agent watches? Can the agent still log into the repository, or has a token expired? Did it fetch the new revision? Did rendering the files fail because of a syntax mistake or a missing value? Both tools report these errors on the application or source object, so read the status message before anything else.
Check the Repository Side
Confirm the change is merged on the watched branch and that the agent’s credentials still work.
Check Fetching and Rendering
Look for errors fetching the revision or turning files into objects. A typo in a template is a frequent cause.
Check Dependencies and Ordering
See whether the application is waiting for another one that has not become healthy yet.
Check the Cluster’s Response
Sometimes the cluster rejects an object, for example because of a policy or a missing permission. The rejection message names the reason.
Check Whether Reconciliation Is Paused
Both tools allow reconciliation to be suspended on an object. A forgotten pause is a classic explanation for changes that are never applied.
Stuck in Progressing
The objects were applied but never became healthy. Look at the Pods: a crash loop, a missing image, or a failed readiness check is almost always the cause.
Authentication Failed
Credentials for the repository expired or were revoked. Renew them and check that the agent can read the right repository.
Resource Rejected
The cluster refused an object, often because of a policy, a missing custom type, or an ordering issue. Install shared types before the objects that use them.
Deleted Objects Come Back
Self-healing restored something a person removed. If deletion was intended, remove it from Git.
Both ArgoCD and Flux write a clear status and a message on every object they manage. Reading that message before touching anything else solves a large share of problems in under a minute.
24Real-World Adoption: A Practical Journey
GitOps is easier to adopt in steps than in one dramatic switch. Here is a path many teams have followed successfully.
A Little History
The term GitOps was popularized around 2017 by the team at Weaveworks, who also created the original Flux. ArgoCD grew out of the Argo project family and was shaped heavily by engineers at Intuit. Both projects are now community-driven and have reached the graduated level in the Cloud Native Computing Foundation, a sign of broad adoption and maturity. Companies in many industries, from finance to retail to telecommunications, run them in production.
The Adoption Path
Start Small and Safe
Pick one non-critical application in a development cluster. The goal is learning, not perfection.
Describe It Declaratively
Export or write the descriptions of that application and commit them to a new configuration repository, with sensible structure from the beginning.
Install the Agent and Observe
Connect it in a mode that only reports differences. Watching the reported drift teaches you how much hidden manual change existed.
Turn On Automatic Sync
Once the repository and cluster agree, enable automation for that application, and let the team get used to changing things only through Git.
Handle Secrets and Access
Adopt a secrets approach and set up proper boundaries, reviews, and notifications before expanding.
Expand Environment by Environment
Move staging and then production, with promotion by reviewed change, and bring in more applications and teams steadily.
Add Progressive Delivery and Policy
When the basics are stable, add gradual rollouts and policy checks to raise safety further.
Use Case: A Platform Team Serving Many Squads
A central team runs the clusters and shared services from one repository, while each squad owns a repository for its own services. A top-level definition tells each cluster which repositories to follow, and projects or limited identities keep every squad inside its own area. New squads onboard by adding one entry.
Use Case: A Fleet of Edge Clusters
A retailer runs a small cluster in each store. Each cluster follows the same repository and applies updates on its own schedule, so a store with a poor network connection simply catches up when it reconnects. Nobody needs to log in to a store to deploy.
Use Case: Regulated Environments
An organization that must show who approved each production change uses the pull request history as its evidence. Every deployment is tied to a reviewed, signed, timestamped commit, making audits far simpler than reconstructing events from scattered pipeline logs.
25A Simple Decision Guide
If you are still unsure where to start, this short path points toward a sensible first choice.
flowchart TD
S["Starting with GitOps"] --> Q1{"Do you want a built-in visual interface?"}
Q1 -- "Yes" --> A["Lean toward ArgoCD"]
Q1 -- "No or not important" --> Q2{"Do you prefer everything as native Kubernetes objects and small parts?"}
Q2 -- "Yes" --> F["Lean toward Flux"]
Q2 -- "No" --> Q3{"Do many teams share one central platform?"}
Q3 -- "Yes" --> A
Q3 -- "No" --> Q4{"Do you want built-in image update automation?"}
Q4 -- "Yes" --> F
Q4 -- "No" --> E["Try both in a test cluster for a week"]
Reading the Guide
The guide is only a nudge. If your developers and managers want to see the state of everything at a glance, ArgoCD’s interface is a strong reason to choose it. If you value a minimal, composable system that feels like a natural extension of Kubernetes, Flux is attractive. If a central platform team serves many squads, either works, with ArgoCD offering friendlier tools for central visibility and Flux offering strong tenant isolation through native access control. When honestly undecided, a week of hands-on trial in a throwaway cluster is worth more than any article.
Your repository structure, secret handling, review habits, and monitoring will matter far more to your success than the tool. A well-organized repository can be moved from one tool to the other with modest effort, because the ideas and many of the files are the same.
26Testing Changes Before They Merge
In GitOps, a merged change goes live quickly. That makes checking the change before the merge one of the most valuable habits you can build.
Catch Mistakes in the Review Stage
Because the agent applies whatever reaches the watched branch, an error in the repository becomes an error in the cluster. The cheapest place to catch it is before the merge, while the change is still only a proposal. Most teams add automatic checks to every proposed change. These checks confirm that the files are valid, that templates render without errors, that the final objects follow the expected structure, and that company policies are respected, such as having resource limits and approved image sources.
A particularly helpful check is a rendered difference. Since many repositories use templates and overlays, the files that a reviewer reads are not the final objects. A rendering step produces the final objects for both the old and new versions and shows the difference between them. The reviewer then sees exactly what will change in the cluster, not just which template lines were edited. This often reveals surprises, such as a small value change that affects twenty objects.
Syntax and Structure
Confirms that files are well formed and match the expected shape of Kubernetes objects, catching typos before the agent ever sees them.
Rendering
Builds the final objects from templates and overlays, proving that the change can actually be turned into something deployable.
Policy Rules
Applies company rules to the rendered objects, such as requiring limits, forbidding risky settings, or restricting image sources.
Rendered Difference
Shows reviewers the true effect of the change on the cluster so that approval is based on facts, not guesses.
Previews and Test Environments
Some teams go further and create a temporary environment for each proposed change. The agent deploys the proposal into a short-lived namespace, tests run against it, and the environment disappears when the proposal is merged or closed. This gives reviewers a real, running copy to try instead of only reading files. It costs more resources, so teams usually reserve it for changes that are risky or that touch many users.
A test kitchen is the place where a new recipe is tried before it is printed into the official book. Printing is fast and permanent, so you taste first. A preview environment is that test kitchen, and the review checks are the tasting notes.
Configure the Git host so that a change cannot be merged until the automatic checks pass and a reviewer approves. This turns good intentions into a rule that nobody can forget on a busy day.
27Handling Drift Thoughtfully
Drift is not always a villain. Understanding why it appears helps you decide whether to fix it, tolerate it, or redesign around it.
Where Drift Comes From
Drift appears for several different reasons, and each calls for a different response. Some drift comes from people: an engineer changes a live object during an incident. Some comes from other automation: an autoscaler changes the number of copies, or a certificate tool rewrites a secret. Some comes from the cluster itself: it fills in default values for fields that your files left empty, and these defaults then look like differences. And some comes from attackers, though this is the rarest cause. Treating all drift the same way leads either to constant noise or to missed warnings.
| Source of Drift | Example | Best Response |
|---|---|---|
| A person | Manual scaling during an incident | Allow it temporarily, then commit the decision to Git |
| Other automation | An autoscaler adjusting copies | Stop describing that field in Git, or ignore it |
| Cluster defaults | Empty fields filled with default values | Ignore the field or write the default explicitly |
| Malicious change | An unexpected privileged setting | Self-heal and alert the security team |
Ownership of Fields
A helpful mental model is that every field of every object has exactly one owner. If Git owns the number of copies, then nothing else should change it. If an autoscaler owns it, Git should not mention it. Problems arise when two owners claim the same field, and the agent and the other system fight. Clearing up ownership, rather than adding more exceptions, is the lasting cure for most never-ending sync problems.
Use Case: Autoscaling Without a Fight
A team sets the baseline number of copies in Git, then adds an autoscaler. The two start fighting. The team removes the copy count from the repository for that service and lets the autoscaler own it. The sync status becomes stable, and the repository still records every other setting.
Use Case: An Incident Override
During an outage, an engineer scales a service by hand to buy time. The agent reports drift but, by team agreement, does not revert it during the incident. Afterward the team makes the permanent decision in Git, and the drift disappears because Git and the cluster agree again.
Adding an ignore rule for every noisy difference hides real problems. Before ignoring a field, understand who changes it and why. Ignore it only when you are sure that another system rightfully owns it.
28What GitOps Asks of You: Costs and Trade-offs
GitOps brings real benefits, but it also asks for changes in habits and a small amount of extra machinery. An honest view helps teams plan well.
Advantages
- A complete, reviewable history of every change
- Fast and predictable rollback by reverting a commit
- Easier disaster recovery by pointing a new cluster at the repository
- Less need for powerful credentials in build systems
- Consistent environments with fewer hidden differences
- Better audit evidence for regulated industries
Disadvantages / Trade-offs
- A cultural shift: quick manual fixes are no longer welcome
- Extra components to run, secure, and monitor
- Secrets need a deliberate, separate solution
- Repository structure takes thought and can be hard to change later
- Merging a bad change reaches production quickly if checks are weak
- Debugging now means following a longer path from Git to cluster
The Human Side
The hardest part of adopting GitOps is usually not technical. People who are used to fixing things directly feel slowed down by the requirement to propose, review, and merge every change. The answer is to make the Git path fast and pleasant: quick reviews, helpful automatic checks, and a clear break-glass procedure for real emergencies. When the proper path is easy, people use it willingly, and the benefits become visible within weeks.
When It Might Not Be Worth It
For a tiny setup with a single small cluster and one or two engineers who deploy rarely, the extra moving parts may outweigh the gain. Even then, many people adopt a light version because the benefits of history and recoverability appear early. The decision should reflect how many people change the cluster, how often they do so, and how costly a mistake or an outage would be.
Track a few simple signals before and after adoption, such as how long a deployment takes, how long recovery from a bad release takes, and how many times people had to log in to production. Real numbers make it easier to justify the effort and to see where to improve next.
29Frequently Asked Questions
The ideas apply anywhere you can describe desired state and reconcile it, but the mature tools discussed here are built for Kubernetes, which is naturally declarative and so fits very well.
Yes. You still build, test, and scan your software. GitOps changes the final step: the pipeline updates the repository, and the agent inside the cluster does the deployment.
They keep running. The agent only reconciles configuration and is not in the path of user traffic. You lose automatic updates and drift correction until it returns, so monitor it and alert if it stops.
Revert the change in Git. The agent then applies the previous state. This is usually faster and safer than hand-crafted rollback commands, and the revert itself becomes part of the history.
Most experienced teams use a single main branch with a folder for each environment and share a common base. Long-lived environment branches tend to drift and make comparisons confusing.
Never in plain text in Git. Use encryption before committing, encryption with a key service, or an external secrets manager referenced from Git. Pick the one that fits your compliance and operating model.
It reverts manual changes to match Git. It is safe when your team understands it and follows the rule that all changes go through Git. Introduce it gradually and tell people before switching it on.
Another system is probably modifying the same fields, such as an autoscaler or an admission webhook. Stop describing those fields in Git or tell the tool to ignore those specific differences.
Technically yes, but not on the same objects, because they would fight each other. Some organizations use one for platform components and the other for applications, but running one tool is simpler for most teams.
Both poll on a configurable schedule, typically every few minutes by default. You can make them react almost instantly by having your Git host notify the agent when a commit lands.
With ArgoCD, one central instance can manage many clusters, and ApplicationSets generate applications per cluster. With Flux, you usually run an instance in each cluster that follows the same repository, with definitions that say what each cluster should run.
No. GitOps ensures that what is in Git is applied, but it does not judge whether it is safe. Keep admission rules, policy checks, scanning, and access control in place alongside it.
No. Git holds configuration, not the contents of databases or volumes. Those need their own backups and recovery plan, even though your configuration can be restored automatically.
Pick one low-risk application in a development cluster, put its configuration in a new repository, install either tool in report-only mode, and watch what it tells you. Expand only after you are comfortable.
30Summary and Key Takeaways
GitOps makes a Git repository the single source of truth for what runs in your cluster, and uses an agent inside the cluster to keep reality matching it. ArgoCD offers a rich interface and central control, while Flux offers a Kubernetes-native toolkit of small controllers. Both follow the same four principles, and both turn deployment, rollback, and recovery into ordinary Git operations. Success depends less on the tool and more on good habits: separate repositories for code and configuration, folders for environments, safe secret handling, reviewed promotion, careful security, and clear monitoring. Start small, learn how drift and reconciliation behave, and grow step by step.
Key Takeaways
- Git is the source of truth — the desired state lives in a repository with full history, review, and easy rollback.
- Pull beats push — an agent inside the cluster fetches changes, so build systems no longer hold powerful cluster credentials.
- Reconciliation never stops — the agent keeps comparing Git with the cluster and can correct drift automatically.
- ArgoCD and Flux share the same ideas — choose ArgoCD for its interface and central view, or Flux for its composable, Kubernetes-native design.
- Structure matters most — keep code and configuration apart, use folders and overlays for environments, and pin every version.
- Never store plain secrets in Git — encrypt them or reference an external secrets manager.
- Adopt in steps — start with one safe application, observe, then expand automation, promotion, and progressive delivery as trust grows.