Cyber Intelligence
Zero Trust14 min read

GitOps with ArgoCD: Managing Kubernetes the Right Way

GitOps makes Kubernetes deployments predictable and auditable, but it also concentrates deploy authority in your Git repo. Learn how to set up ArgoCD, plus the RBAC, secrets, and supply-chain controls a GitOps pipeline needs to stay secure.

I
Microsoft Cloud Solution Architect
GitOps with ArgoCD: Managing Kubernetes the Right Way infographic showing key Zero Trust concepts and controls
GitOps with ArgoCD: Managing Kubernetes the Right Way infographic showing key Zero Trust concepts and controls
GitOpsArgoCDKubernetesDevOpsCD

Why GitOps changed how I think about deployments

Before GitOps, my Kubernetes deployments were a mess. Kubectl commands run from laptops, different versions in different clusters, no clear audit trail.

GitOps flips this around: Git becomes the single source of truth. What's in Git is what's running. No exceptions.

GitOps is a deployment methodology where Git is the single source of truth for both infrastructure and application configuration, and a software agent, ArgoCD in this case, continuously reconciles the live cluster state to match what's declared in Git. Nothing gets applied to the cluster that didn't first go through Git.

GitOps principles

  1. Declarative: Describe what you want, not how to get there
  2. Versioned: All changes go through Git
  3. Automated: Changes in Git automatically apply to clusters
  4. Auditable: Git history shows who changed what and when

These four principles, declarative, versioned, pulled automatically, and continuously reconciled, come from OpenGitOps, the CNCF working group that formalized the vendor-neutral definition of GitOps.

Setting up ArgoCD

Installation

Create the argocd namespace and apply the installation manifest. Wait for pods to be ready, then get the initial admin password from the secret.

CLI installation

Install the ArgoCD CLI using brew on macOS or download the binary for Linux.

Repository structure

gitops-repo/
├── apps/                    # Application definitions
│   ├── production/
│   ├── staging/
│   └── dev/
├── base/                    # Base Kubernetes manifests
├── overlays/                # Environment-specific patches
└── projects/                # ArgoCD project definitions

Creating your first application

Create an Application resource that points to your Git repo, specifies the path to your manifests, and defines where to deploy.

Enable automated sync with prune (delete resources not in Git) and selfHeal (fix drift automatically).

Deployment workflows

Standard workflow

  1. Developer creates PR with manifest changes
  2. CI validates YAML and runs security scans (if using Azure DevOps for CI, see our Azure DevOps Pipelines setup guide)
  3. PR review and approval
  4. Merge to main
  5. ArgoCD detects change and syncs

Image updates

Use ArgoCD Image Updater to automatically update image tags in your Git repo when new images are pushed.

Multi-cluster management

App of Apps pattern

Manage multiple applications with one parent Application.

ApplicationSet for multi-cluster

Deploy the same app to multiple clusters using ApplicationSet with cluster generators.

Security implications of GitOps

GitOps concentrates deploy authority in one place: the Git repository and the agent that watches it. That's the whole point, and it's also the risk. Compromise the repo, or compromise ArgoCD's own permissions, and you compromise every cluster ArgoCD can reach. This is the part of GitOps adoption that gets the least attention relative to how much blast radius it controls. For broader Kubernetes cluster hardening, RBAC, Pod Security Standards, network policies, and cluster-side secrets encryption, see our Kubernetes security best practices guide; this section stays focused on what's specific to the GitOps deployment pipeline itself.

RBAC for ArgoCD itself

ArgoCD ships with one built-in superuser, the local admin account, and everything else is governed by a policy.csv file inside the argocd-rbac-cm ConfigMap. Policies map users or SSO groups to roles, and roles grant or deny specific actions, get, sync, override, delete, on specific resources. Get this wrong and every developer with ArgoCD access can sync any application to any cluster.

The real control boundary, though, is the AppProject. An AppProject restricts which Git repositories an application can source from, which cluster and namespace combinations it can deploy to, and which Kubernetes resource kinds it's allowed to create. Every ArgoCD installation ships with a default AppProject, and by default it's wide open: any repo, any destination, any resource kind. Teams that never create their own AppProjects are running every application under that default, unrestricted project without realizing it.

Scope it properly instead: one AppProject per team or environment, sourceRepos limited to the repos that team owns, destinations limited to the clusters and namespaces that team is responsible for, and project-scoped roles instead of the global admin role for anyone who doesn't need it.

Secrets management in a GitOps repository

A plain Kubernetes Secret manifest is base64, not encryption. Commit one to Git and it's readable by anyone with repo access, and it stays readable in Git history even after you delete the file, because the commit that added it is still there. This is the single most common way GitOps repositories leak credentials.

Three patterns avoid it. Sealed Secrets encrypts a Secret client-side with the target cluster's public key using the kubeseal CLI; the result is safe to commit because only the in-cluster controller holding the matching private key can decrypt it, even in a public repository. External Secrets Operator takes the opposite approach: it never stores secret material in Git at all, just a reference to where the real value lives in Vault, AWS Secrets Manager, Azure Key Vault, or similar, and it's synced into a native Kubernetes Secret at runtime. SOPS encrypts specific values inside a YAML or JSON file using KMS, PGP, or age keys, and integrates natively with Flux; on ArgoCD it typically needs a config management plugin or a Kustomize generator like ksops.

Pick based on what you already run: Sealed Secrets if you want something self-contained with no external dependency, External Secrets Operator if you already have Vault or a cloud secrets manager and want Git to hold zero secret material, SOPS if you're on Flux or already standardized on a KMS. Whichever you choose, add a secret scanner, gitleaks or equivalent, as a CI check on every pull request, not just a one-time repo audit, so a plaintext secret never reaches a mergeable state.

Sync policy risk: auto-sync from an unprotected branch

Automated sync with prune and selfHeal enabled is the GitOps ideal: Git changes apply automatically, deleted manifests get cleaned up, and drift gets corrected without anyone running kubectl. It's also where GitOps quietly removes a review step that Kubernetes access via RBAC used to provide. If the branch ArgoCD tracks has no branch protection, whoever can push to it, intentionally or through a compromised account, can reach production the moment ArgoCD's next reconciliation loop runs, typically within seconds of the commit landing.

selfHeal has a second, less obvious cost: it reverts manual changes, including ones an on-call engineer applies with kubectl during an active incident to stop harm, because ArgoCD treats anything not in Git as drift to correct. Scope automated sync deliberately: enable it on branches with required PR review and status checks, use AppProject sync windows to block automated sync outside change windows for production, and know that ArgoCD disables its own CLI rollback command while automated sync is active, so a Git revert, not a manual rollback, is the supported path back.

Supply chain integrity: signed commits and protected branches

Because merging to the tracked branch is functionally equivalent to running kubectl apply against production, the same controls that protect a codebase's release branch should protect a GitOps repository's production path. Require pull request review before merge, require signed commits so GitHub can mark each one Verified against a known key rather than an unauthenticated name and email, and add a CODEOWNERS entry for production manifest paths so changes route to the platform or security team automatically instead of merging on any approving review.

GitHub's branch protection settings enforce required reviews, required signed commits, and restricted push access at the platform level, backed by the SLSA framework's broader model for what tamper-resistant software delivery should look like end to end. See our GitHub Advanced Security setup guide for the full configuration, including secret scanning that can catch a plaintext credential before it ever reaches a protected branch.

Push versus pull deployment models: the security tradeoff

Traditional push-based CI/CD needs cluster credentials somewhere outside the cluster: a kubeconfig or service account token sitting in the CI system's secrets store, often with broad, long-lived permissions so any pipeline can deploy. Compromise the CI runner and an attacker has direct cluster write access, no Git commit required.

GitOps flips who holds the keys. ArgoCD runs inside the cluster and holds the cluster credentials itself; nothing external needs standing cluster access, CI only needs write access to Git or a container registry. That's a real reduction in what a compromised CI system can do. It doesn't reduce risk to zero, it moves it: the Git repository and ArgoCD's own RBAC become the new highest-value targets, which is exactly why the controls above matter as much as the deployment mechanics.

ArgoCD isn't the only pull-based option. Flux, also a CNCF-hosted GitOps project, takes a more composable approach: separate source, kustomize, and helm controllers instead of one UI-driven application, with native SOPS decryption built in rather than bolted on through a plugin. Teams that want a dashboard and AppProject-style multi-tenancy out of the box tend to reach for ArgoCD; teams standardized on GitHub-native workflows with no separate UI to secure often prefer Flux. Both inherit the same repo-as-target security model described here.

Common GitOps failure modes

  • Secrets get committed in plaintext, then "removed" in a later commit, while the original values remain readable in Git history and in every clone already made before the fix.
  • Every application stays on the default AppProject, which ships unrestricted by default, so anyone who can push to any repo ArgoCD watches can deploy to any cluster ArgoCD can reach.
  • Automated sync with selfHeal runs against a branch with no protection rules, so a bad merge, or a compromised contributor account, reaches production the moment it lands, with no review step catching it first.
  • The built-in ArgoCD admin account stays active with no SSO, no MFA, and the initial password never rotated, turning one credential into a skeleton key for every cluster ArgoCD manages.
  • selfHeal silently reverts a manual kubectl fix applied during an active incident, because ArgoCD reads any change not in Git as drift to correct, undoing exactly the mitigation an on-call engineer just applied.
  • No signed-commit requirement and no CODEOWNERS entry on production manifest paths, so any contributor with merge rights, not necessarily anyone on the platform or security team, can change what actually runs in production.

GitOps security checklist

  1. Require pull request review and passing CI checks before merge to any branch ArgoCD tracks for production. No direct pushes to that branch, for anyone.
  2. Turn on required signed commits on protected branches and verify the Verified badge in CI, not just in GitHub's UI.
  3. Add a CODEOWNERS entry for production manifest paths so changes route automatically to the platform or security team.
  4. Replace the default AppProject with per-team or per-environment AppProjects, scoping sourceRepos, destinations, and resource kinds to exactly what each team owns.
  5. Store secrets as Sealed Secrets, External Secrets Operator references, or SOPS-encrypted values, never as plain Secret manifests, and run a secret scanner in CI on every pull request.
  6. Use sync-wave annotations to sequence dependent resources, namespaces and CRDs before the workloads that need them, instead of relying on apply order to work out by luck.
  7. Treat git revert as the default rollback path. With automated sync active, ArgoCD's own rollback command is disabled, so reverting the offending commit and letting reconciliation catch up is the supported, auditable way back.

Getting started checklist

  1. Install ArgoCD in your cluster
  2. Set up a GitOps repository
  3. Create your first Application resource
  4. Enable auto-sync on a non-production app
  5. Set up sealed secrets
  6. Configure RBAC
  7. Add monitoring and alerting
  8. Document your deployment process

GitOps takes some setup, but the payoff is huge: predictable deployments, easy rollbacks, and a complete audit trail.

Frequently asked questions

What is GitOps and how does it differ from traditional CI/CD?

GitOps is a deployment model where Git is the single source of truth for infrastructure and application state. A GitOps agent (such as ArgoCD) continuously reconciles the live cluster state with the desired state declared in Git, automatically applying changes when Git is updated. Traditional CI/CD pipelines push changes to the cluster imperatively; GitOps uses a pull model where the cluster agent pulls and applies changes, providing automatic drift correction and a complete audit trail of every change.

What is ArgoCD and what does it do?

ArgoCD is a declarative GitOps continuous delivery tool for Kubernetes. It watches Git repositories containing Kubernetes manifests and automatically syncs the live cluster state to match the desired state in Git. ArgoCD provides a visual dashboard showing application sync status, detects and alerts on drift, supports multi-cluster deployments, and enables one-click rollbacks to any previous Git commit.

How do I secure secrets in a GitOps repository?

Never store plaintext secrets in a GitOps repository. The two most common approaches are Sealed Secrets (encrypts secrets with a cluster-specific public key so only that cluster can decrypt them, making it safe to commit encrypted secrets to Git) and External Secrets Operator (fetches secrets from an external secrets manager like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault at runtime and injects them as Kubernetes secrets). Sealed Secrets is simpler; External Secrets Operator is better for organizations with existing secrets management infrastructure.

What is the ArgoCD App of Apps pattern?

The App of Apps pattern is a way to manage multiple ArgoCD applications using a single parent ArgoCD Application. The parent application points to a directory containing Application resource definitions for each child application. When you add a new application definition to that directory, ArgoCD automatically creates and manages the new application. This pattern enables GitOps management of ArgoCD itself: all application definitions live in Git and changes are applied through the same GitOps workflow.

Can ArgoCD manage multiple Kubernetes clusters?

Yes. ArgoCD can manage applications across multiple Kubernetes clusters from a single ArgoCD installation. You register target clusters in ArgoCD and specify the destination cluster in each Application resource. The ApplicationSet resource extends this further, enabling you to generate Application resources automatically for all clusters matching a selector, making it straightforward to deploy the same application to dozens of clusters with a single configuration.

Is ArgoCD's pull-based model more secure than a traditional push-based CI/CD deployment?

It shifts risk rather than removing it. In a push model, the CI system holds cluster credentials, so a compromised CI runner can apply changes directly to the cluster. In ArgoCD's pull model, only the in-cluster controller holds those credentials, and CI only needs write access to Git, which narrows what a compromised CI system can do. That risk doesn't disappear, it concentrates into the Git repository and ArgoCD's own RBAC: whoever can merge to the tracked branch, or whoever holds ArgoCD sync permissions, effectively controls the cluster.

How does ArgoCD compare to Flux for GitOps security?

Both are pull-based GitOps tools hosted at the CNCF, and both reconcile cluster state from Git, so the same repo-as-target and RBAC concerns apply to either one. ArgoCD ships its own UI, API, and AppProject-based multi-tenancy model, which is useful for visibility but adds ArgoCD's RBAC configuration as its own control plane to secure. Flux is a more composable set of controllers, source, kustomize, helm, with native SOPS secret decryption, and tends to appeal to teams who want tighter GitHub-native workflows without a separate UI to lock down.

References

Free download

Zero Trust Implementation Guide

Step-by-step framework for deploying zero trust in enterprise environments.

No spam. Unsubscribe anytime.

Continue Learning

Zero Trust Architect Roadmap

Design and implement Zero Trust architectures that assume breach and verify every request.

Start the Intermediate Path11h · 4 topics · 10 quiz questions
I

Microsoft Cloud Solution Architect

Cloud Solution Architect with deep expertise in Microsoft Azure and a strong background in systems and IT infrastructure. Passionate about cloud technologies, security best practices, and helping organizations modernize their infrastructure.

Share this article

Questions & Answers

Ask a Question

0/2000 characters

Your email is used for moderation only and will not be displayed.

Related Articles

Need Help with Your Security?

Our team of security experts can help you implement the strategies discussed in this article.

Contact Us