~Engineers solve problems, I solve engineer's problems 🤘
A practical comparison of the two leading GitOps tools for Kubernetes deployments, focusing on reconciliation models, drift detection, multi-cluster strategies, and secrets handling.
GitOps is a methodology where Git serves as the single source of truth for declarative infrastructure and applications. Changes are made through Git commits, and an automated process ensures the actual state matches the desired state.
Feature | Argo CD | Flux |
---|---|---|
Architecture | Pull-based, agent in cluster | Pull-based, operator in cluster |
UI | Rich web interface | CLI-focused, basic UI |
Multi-cluster | Native support | Native support |
Helm Support | Excellent | Excellent |
Kustomize | Native | Native |
Learning Curve | Moderate | Steep |
Resource Usage | Higher | Lower |
# Argo CD Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp
targetRevision: HEAD
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
# Flux GitRepository
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: my-app
namespace: flux-system
spec:
interval: 1m
url: https://github.com/myorg/myapp
ref:
branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: my-app
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: my-app
path: "./k8s"
prune: true
validation: client
# Argo CD ApplicationSet for multi-cluster
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app-multicluster
spec:
generators:
- clusters:
selector:
matchLabels:
environment: production
template:
metadata:
name: '-my-app'
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp
targetRevision: HEAD
path: k8s
destination:
server: ''
namespace: production
# Argo CD with Sealed Secrets
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-with-secrets
spec:
source:
repoURL: https://github.com/myorg/myapp
path: k8s
syncPolicy:
syncOptions:
- CreateNamespace=true
sources:
- repoURL: https://github.com/myorg/secrets
path: sealed-secrets
targetRevision: main
# Flux with External Secrets
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend
namespace: flux-system
spec:
provider:
vault:
server: "https://vault.example.com"
path: "secret"
version: "v2"
auth:
kubernetes:
mountPath: "kubernetes"
role: "flux"
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-app-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: my-app-secrets
creationPolicy: Owner
data:
- secretKey: database-password
remoteRef:
key: my-app
property: db-password
my-gitops-repo/
├── clusters/
│ ├── production/
│ │ ├── apps/
│ │ └── infrastructure/
│ └── staging/
│ ├── apps/
│ └── infrastructure/
├── apps/
│ ├── my-app/
│ │ ├── base/
│ │ └── overlays/
│ └── another-app/
└── infrastructure/
├── monitoring/
└── networking/