Skip to main content
← All Articles · · 11 min read

GitOps Workflow Guide: ArgoCD vs Flux in 2026

A deep dive into GitOps principles with a practical ArgoCD vs FluxCD comparison—setup examples, sync strategies, and production tips for Kubernetes deployments.

devopskubernetesgitopsargocdfluxcdplatform-engineering

GitOps has become the deployment standard for Kubernetes in production. The premise is simple and powerful: Git is the single source of truth for your system’s desired state. Deployments happen by merging a pull request, not by running kubectl apply on a developer’s laptop.

In 2026, two tools dominate this space: ArgoCD and FluxCD. Both implement GitOps well. Choosing between them comes down to your team’s workflow preferences, not which one is “better.”

GitOps Core Principles

Before comparing tools, nail down the four principles that define GitOps:

  1. Declarative: The entire system—infrastructure and applications—is described declaratively.
  2. Versioned and immutable: The desired state is stored in Git, which provides versioning, audit history, and rollback.
  3. Pulled automatically: Software agents automatically pull and apply the desired state from Git.
  4. Continuously reconciled: Software agents continuously observe the actual state and reconcile any divergence from the desired state.

The reconciliation loop is what separates GitOps from traditional CI/CD. Your cluster is constantly comparing “what Git says should exist” with “what actually exists” and correcting drift.


Why GitOps Matters for Operations

The operational benefits compound over time:

  • Audit trail: Every deployment is a Git commit with an author, timestamp, and reason. Compliance teams love this.
  • Rollback is just a revert: Bad deploy? git revert and push. The GitOps agent handles the rest.
  • Disaster recovery: Rebuild an entire environment from a Git repository. No manual state reconstruction.
  • Developer self-service: Developers deploy by opening a PR—no direct cluster access required.
  • Drift detection: If someone runs kubectl edit directly, the GitOps agent flags and reverts it.

ArgoCD: Overview

ArgoCD is a declarative GitOps controller with a polished UI that makes it particularly accessible to teams new to GitOps.

Key Features

  • Web UI for visualizing application state and sync status
  • ApplicationSet controller for managing many apps from a single template
  • Multiple sync strategies (auto-sync, manual, self-heal)
  • Multi-cluster management from a single control plane
  • SSO integration (OIDC, SAML, LDAP)
  • Notification controller for Slack/PagerDuty/webhook alerts

Installing ArgoCD

kubectl create namespace argocd
kubectl apply -n argocd -f \
  https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Wait for all pods to be ready
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=300s

# Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

# Port-forward to access UI
kubectl port-forward svc/argocd-server -n argocd 8080:443

Defining an Application

# app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-api
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/k8s-manifests
    targetRevision: main
    path: apps/my-api
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true        # Delete resources removed from Git
      selfHeal: true     # Revert manual kubectl changes
      allowEmpty: false  # Never sync an empty state
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - ApplyOutOfSyncOnly=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

ApplicationSets for Multi-Environment Deployments

ApplicationSets let you template applications across environments or clusters:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: my-api-environments
  namespace: argocd
spec:
  generators:
  - list:
      elements:
      - env: staging
        cluster: staging-cluster
        url: https://staging.k8s.example.com
      - env: production
        cluster: prod-cluster
        url: https://prod.k8s.example.com
  template:
    metadata:
      name: 'my-api-{{env}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/your-org/k8s-manifests
        targetRevision: main
        path: 'apps/my-api/{{env}}'
      destination:
        server: '{{url}}'
        namespace: my-api
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

FluxCD: Overview

FluxCD takes a more Kubernetes-native, CLI-first approach. Rather than a central UI, Flux is composed of controllers you interact with via kubectl and the flux CLI.

Key Features

  • Modular controller architecture (source, kustomize, helm, notification, image automation)
  • Image update automation: Flux can open PRs to bump image tags
  • First-class Helm and Kustomize support
  • Multi-tenancy with isolated namespaces per team
  • Mozilla SOPS integration for encrypted secrets in Git

Installing FluxCD

# Install Flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash

# Bootstrap into your cluster (creates flux-system namespace + Git repo)
flux bootstrap github \
  --owner=your-org \
  --repository=fleet-infra \
  --branch=main \
  --path=./clusters/production \
  --personal

Defining a Source and Kustomization

# Source: where Flux watches for changes
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: my-api
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/your-org/k8s-manifests
  ref:
    branch: main
  secretRef:
    name: flux-system  # SSH deploy key or GitHub token
---
# Kustomization: what to apply and how
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-api
  namespace: flux-system
spec:
  interval: 10m
  path: ./apps/my-api
  prune: true
  sourceRef:
    kind: GitRepository
    name: my-api
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: my-api
      namespace: production
  timeout: 5m

Helm Release with FluxCD

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
  name: podinfo
  namespace: flux-system
spec:
  interval: 5m
  url: https://stefanprodan.github.io/podinfo
---
apiVersion: helm.toolkit.fluxcd.io/v2beta2
kind: HelmRelease
metadata:
  name: podinfo
  namespace: default
spec:
  interval: 5m
  chart:
    spec:
      chart: podinfo
      version: '>=6.0.0'
      sourceRef:
        kind: HelmRepository
        name: podinfo
        namespace: flux-system
  values:
    replicaCount: 2
    resources:
      requests:
        cpu: 100m
        memory: 64Mi

ArgoCD vs FluxCD: Direct Comparison

DimensionArgoCDFluxCD
UIRich web UI, visual app treeCLI-first, no built-in UI
Installation complexitySingle manifestBootstrap CLI, modular
Helm supportNativeNative
Kustomize supportNativeNative
Multi-clusterStrong, single pane of glassSupported, requires config
Image update automationVia image-updater pluginBuilt-in, first-class
Secret encryptionExternal (Vault, ESO)Mozilla SOPS built-in
Multi-tenancyProjects + RBACNamespace isolation
NotificationNotification controllerNotification controller
CommunityVery largeLarge (CNCF graduated)
Learning curveLower (UI helps)Higher (kubectl-native)

Production Tips

Git Repository Structure

Mono-repo vs. multi-repo is a common debate. For most teams, start with a dedicated “fleet” repository:

fleet-infra/
├── clusters/
│   ├── staging/
│   │   ├── flux-system/     # Flux bootstrap configs
│   │   └── apps/            # App-level kustomizations
│   └── production/
│       ├── flux-system/
│       └── apps/
├── apps/
│   ├── base/                # Shared base configs
│   │   └── my-api/
│   │       ├── deployment.yaml
│   │       ├── service.yaml
│   │       └── kustomization.yaml
│   ├── staging/             # Staging overlays
│   │   └── my-api/
│   └── production/          # Production overlays
│       └── my-api/
└── infrastructure/
    ├── cert-manager/
    ├── ingress-nginx/
    └── monitoring/

Progressive Delivery with ArgoCD Rollouts

For canary and blue/green deployments, pair ArgoCD with Argo Rollouts:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-api
spec:
  replicas: 10
  strategy:
    canary:
      steps:
      - setWeight: 10      # Send 10% traffic to new version
      - pause: {duration: 5m}
      - setWeight: 25
      - pause: {duration: 5m}
      - setWeight: 50
      - pause: {}          # Manual approval gate
      - setWeight: 100
      analysis:
        templates:
        - templateName: success-rate
        startingStep: 2
  selector:
    matchLabels:
      app: my-api

Sync Wave Ordering

When deploying dependent resources, use sync waves to control ordering (ArgoCD):

metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "-1"  # Deploy CRDs first

Waves go from most negative to most positive. Use -2 for namespaces, -1 for CRDs, 0 for core infrastructure, 1+ for applications.

Handling Secrets

Never put plaintext secrets in Git. Options in 2026:

  • External Secrets Operator (ESO): Pull secrets from Vault, AWS Secrets Manager, or GCP Secret Manager at sync time. Works with both ArgoCD and Flux.
  • Mozilla SOPS (Flux native): Encrypt secrets with an age key or AWS KMS. Flux decrypts on apply.
  • Sealed Secrets: Encrypt with a cluster-specific key, commit the sealed secret object.
# External Secrets Operator example
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: my-api-credentials
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: my-api-credentials
    creationPolicy: Owner
  data:
  - secretKey: DATABASE_URL
    remoteRef:
      key: production/my-api
      property: database_url

Choosing Between ArgoCD and Flux

Choose ArgoCD if:

  • Your team is new to GitOps and will benefit from a visual interface
  • You manage many clusters and need a single pane of glass
  • You want progressive delivery (canary, blue/green) in the same ecosystem

Choose FluxCD if:

  • Your team prefers CLI and Kubernetes-native workflows
  • You need image update automation out of the box
  • You want SOPS encryption without additional tooling
  • You’re running Flux in a multi-tenant setup with strict namespace isolation

Conclusion

GitOps in 2026 is mature, well-documented, and battle-tested at scale. Both ArgoCD and FluxCD will serve you well. The most important choice isn’t which tool—it’s committing to the GitOps model itself.

Once your deployments are driven by Git, the benefits compound: faster onboarding, cleaner audits, simpler rollbacks, and a team that spends less time firefighting ad-hoc configuration drift. Start with one cluster, one app, and one team. The pattern scales naturally from there.

Free Download

50 CLI Commands That Save Hours Every Week

The exact Git shortcuts, file search tricks, Docker commands, and productivity hacks that senior developers use daily. Compiled from 5+ years of shipping production code.

  • Git mastery (10 cmds)
  • File & search wizardry
  • Docker & DevOps tricks
  • Process & network tools
  • Productivity boosters
  • macOS & Linux install guide

No spam. 1 email/week max. Unsubscribe anytime.

Found this guide useful? Check out our free developer tools.