Helm with ArgoCD
A comprehensive guide to Helm with ArgoCD covering GitOps, ArgoCD integration, automated sync, and best practices for managing Helm releases with GitOps.
GitOps is a paradigm for managing Kubernetes and infrastructure using Git as the single source of truth. In GitOps, Git repositories contain the entire desired state of the system, including Helm chart configurations. An operator (like ArgoCD) continuously reconciles the actual cluster state with the desired state stored in Git.
GitOps brings several benefits:
- Improved Auditability: All changes are tracked in Git
- Faster Recovery: Rollback is just reverting a commit
- Simplified Operations: Everything is declarative
- Consistency: Same process for all environments
- Security: No direct cluster access needed
helm install manually. Instead, you commit Helm chart configurations to Git, and ArgoCD automatically syncs them to your cluster.
ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes. It follows a pull-based model where the controller continuously monitors Git repositories and synchronizes cluster state.
ArgoCD API Server
Application Controller
Redis Cache
Repo Server
# Install ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Install ArgoCD CLI
curl -sSL -o argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x argocd
sudo mv argocd /usr/local/bin/
# Access ArgoCD UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
# Login via CLI
argocd login localhost:8080 --username admin --password --insecure
# Change password
argocd account update-password
ArgoCD supports Helm charts natively. You can use Helm charts as sources for ArgoCD applications, and ArgoCD will render and deploy them.
# ArgoCD Application with Helm chart
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/helm-charts
targetRevision: HEAD
path: charts/my-app
helm:
# Helm values files
valueFiles:
- values.yaml
- values-production.yaml
# Helm parameters
parameters:
- name: replicaCount
value: "5"
- name: image.tag
value: "v1.2.3"
# Release name
releaseName: my-release
# Helm version
version: v3
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
# ArgoCD Application with Helm repository
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.bitnami.com/bitnami
chart: nginx
targetRevision: 15.0.0
helm:
values: |
replicaCount: 3
service:
type: ClusterIP
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
- Use Helm charts from Git or Helm repositories
- Override values with Helm parameters
- Automatic sync with Git changes
- Rollback to any Git commit
- Multi-environment deployments
- Web UI for visualization
ApplicationSets are a powerful feature that generates ArgoCD Applications using templates and generators. They enable dynamic, scalable management of Helm charts across clusters and environments.
# ApplicationSet for Helm charts
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: helm-apps
namespace: argocd
spec:
generators:
- clusters:
selector:
matchLabels:
environment: production
template:
metadata:
name: '{{name}}-my-app'
spec:
project: default
source:
repoURL: https://github.com/myorg/helm-charts
targetRevision: HEAD
path: charts/my-app
helm:
valueFiles:
- values-{{metadata.labels.environment}}.yaml
parameters:
- name: cluster.name
value: '{{name}}'
- name: environment
value: '{{metadata.labels.environment}}'
destination:
server: '{{server}}'
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
# Git Generator for directory-based ApplicationSets
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: directory-apps
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/myorg/helm-charts
revision: HEAD
directories:
- path: charts/*
template:
metadata:
name: '{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/helm-charts
targetRevision: HEAD
path: '{{path}}'
helm:
valueFiles:
- values.yaml
destination:
server: https://kubernetes.default.svc
namespace: default
# List Generator for specific environments
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: env-apps
namespace: argocd
spec:
generators:
- list:
elements:
- env: dev
namespace: dev
replicas: "1"
- env: staging
namespace: staging
replicas: "2"
- env: prod
namespace: production
replicas: "5"
template:
metadata:
name: 'my-app-{{env}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/helm-charts
targetRevision: HEAD
path: charts/my-app
helm:
parameters:
- name: replicaCount
value: '{{replicas}}'
- name: environment
value: '{{env}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{namespace}}'
- Manage many applications with one resource
- Dynamic generation based on clusters or Git
- Consistent configuration across environments
- Easy to scale to hundreds of applications
- GitOps-friendly with declarative configuration
# Sync Policy options
syncPolicy:
# Automated sync
automated:
prune: true # Delete resources not in Git
selfHeal: true # Correct drift automatically
allowEmpty: false # Don't allow empty applications
# Sync options
syncOptions:
- CreateNamespace=true
- PruneLast=true
- ApplyOutOfSyncOnly=true
- Validate=true
- PrunePropagationPolicy=foreground
# Retry policy
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
# Manual sync (no automated)
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
spec:
syncPolicy:
syncOptions:
- CreateNamespace=true
# Sync Waves for ordered deployment
apiVersion: v1
kind: ConfigMap
metadata:
name: config
annotations:
argocd.argoproj.io/sync-wave: "1" # Deploy first
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
annotations:
argocd.argoproj.io/sync-wave: "5" # Deploy later
---
apiVersion: v1
kind: Service
metadata:
name: app
annotations:
argocd.argoproj.io/sync-wave: "3" # Deploy after config, before deployment
# Sync Hooks for pre/post sync actions
apiVersion: batch/v1
kind: Job
metadata:
name: pre-sync-job
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migration
image: myapp:migration
command: ["python", "migrate.py"]
restartPolicy: Never
# Post-sync hook
apiVersion: batch/v1
kind: Job
metadata:
name: post-sync-job
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: test
image: myapp:test
command: ["python", "smoke-test.py"]
restartPolicy: Never
- Use
prune: trueto remove orphaned resources - Use
selfHeal: trueto correct drift - Use sync waves for ordered deployment
- Use hooks for pre/post sync actions
- Set appropriate retry policies
- Test sync policies in staging first
- Never store plaintext secrets in Git
- Use Sealed Secrets for GitOps-safe encryption
- Use External Secrets Operator for dynamic secrets
- Use helm-secrets plugin for encrypted values
- Configure ArgoCD to decrypt secrets during sync
| Feature | Traditional Helm | Helm with ArgoCD |
|---|---|---|
| Deployment Method | Manual helm install/upgrade | Automated sync from Git |
| Source of Truth | Local values files | Git repository |
| Audit Trail | Limited (shell history) | Complete (Git history) |
| Rollback | helm rollback | Git revert |
| Multi-Cluster | Manual per cluster | ApplicationSets |
| Drift Detection | Manual | Automatic |
| Self-Healing | No | Yes (with selfHeal) |
| UI | No | Yes (ArgoCD UI) |
| Complexity | Low | Medium |
helm.valueFiles field to specify values files, or use helm.parameters to set individual values. You can also use helm.values for inline values.argocd.argoproj.io/sync-wave annotation to specify the wave.GitOps with ArgoCD transforms Helm deployments by making Git the source of truth. Embrace declarative deployments, automated sync, and auditability for modern, reliable infrastructure management.