helm-argocd-gitops
Helm ArgoCD GitOps Integration
Purpose
Guide the configuration of ArgoCD Applications and ApplicationSets for GitOps-based Helm chart deployments with proper sync policies, multi-environment support, and progressive delivery patterns.
Basic ArgoCD Application Setup
Step 1: Create Basic Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/myorg/charts
targetRevision: main
path: charts/myapp
helm:
releaseName: myapp
valueFiles:
- values.yaml
- values-prod.yaml
parameters:
- name: image.tag
value: v1.0.0
destination:
server: https://kubernetes.default.svc
namespace: myapp
syncPolicy:
automated:
prune: false # Manual approval for deletions
selfHeal: false # Manual approval for drift correction
syncOptions:
- CreateNamespace=true
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
Key configuration points:
- ✅ Add finalizer to ensure clean deletion
- ✅ Use multiple value files for environment overrides
- ✅ Set
PruneLast=trueto delete resources in correct order - ✅ Configure retry with exponential backoff
- ✅ Be cautious with
automated.prunein production
Step 2: Deploy Application
# Create application
kubectl apply -f application.yaml
# Or use argocd CLI
argocd app create myapp \
--repo https://github.com/myorg/charts \
--path charts/myapp \
--dest-server https://kubernetes.default.svc \
--dest-namespace myapp \
--values values.yaml \
--values values-prod.yaml
# Sync application
argocd app sync myapp
# Get application status
argocd app get myapp
# View application diff
argocd app diff myapp
Multi-Environment with ApplicationSet
ApplicationSet for Multiple Environments
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-environments
namespace: argocd
spec:
generators:
- list:
elements:
- env: dev
cluster: https://dev.k8s.local
namespace: myapp-dev
autoPrune: "true"
autoHeal: "true"
imageTag: latest
- env: staging
cluster: https://staging.k8s.local
namespace: myapp-staging
autoPrune: "true"
autoHeal: "true"
imageTag: staging
- env: prod
cluster: https://prod.k8s.local
namespace: myapp-prod
autoPrune: "false" # Manual approval for prod
autoHeal: "false"
imageTag: v1.0.0
template:
metadata:
name: "myapp-{{env}}"
labels:
environment: "{{env}}"
spec:
project: default
source:
repoURL: https://github.com/myorg/charts
targetRevision: main
path: charts/myapp
helm:
valueFiles:
- values.yaml
- environments/{{env}}/values.yaml
parameters:
- name: image.tag
value: "{{imageTag}}"
destination:
server: "{{cluster}}"
namespace: "{{namespace}}"
syncPolicy:
automated:
prune: "{{autoPrune}}"
selfHeal: "{{autoHeal}}"
syncOptions:
- CreateNamespace=true
- PruneLast=true
ApplicationSet benefits:
- ✅ Single source of truth for all environments
- ✅ DRY principle - no duplicated manifests
- ✅ Easy to add new environments
- ✅ Consistent configuration with environment-specific overrides
Git-Based ApplicationSet (Auto-Discovery)
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-apps
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/myorg/cluster-config
revision: HEAD
directories:
- path: apps/*
template:
metadata:
name: "{{path.basename}}"
spec:
project: default
source:
repoURL: https://github.com/myorg/cluster-config
targetRevision: HEAD
path: "{{path}}"
helm:
valueFiles:
- values.yaml
- ../common-values.yaml
destination:
server: https://kubernetes.default.svc
namespace: "{{path.basename}}"
syncPolicy:
automated:
prune: true
selfHeal: true
Sync Policies for Different Environments
Conservative (Production)
syncPolicy:
automated:
prune: false # Manual approval for deletions
selfHeal: false # Manual approval for drift correction
syncOptions:
- CreateNamespace=true
- PruneLast=true
- ApplyOutOfSyncOnly=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
Progressive (Staging)
syncPolicy:
automated:
prune: true # Auto-delete removed resources
selfHeal: true # Auto-correct drift
syncOptions:
- CreateNamespace=true
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
Aggressive (Development)
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PruneLast=true
- Replace=true # Use replace instead of apply
retry:
limit: 2
backoff:
duration: 5s
factor: 2
maxDuration: 30s
Sync Waves for Ordered Deployment
Control deployment order with sync waves:
# Wave -1: Prerequisites (namespaces, CRDs)
apiVersion: v1
kind: Namespace
metadata:
name: myapp
annotations:
argocd.argoproj.io/sync-wave: "-1"
---
# Wave 0: Configuration (ConfigMaps, Secrets)
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
annotations:
argocd.argoproj.io/sync-wave: "0"
---
# Wave 1: Core services (Databases)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
annotations:
argocd.argoproj.io/sync-wave: "1"
---
# Wave 2: Application deployments
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
annotations:
argocd.argoproj.io/sync-wave: "2"
---
# Wave 3: Ingress and routing
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp
annotations:
argocd.argoproj.io/sync-wave: "3"
Resource Hooks for Lifecycle Management
Pre-Sync: Database Migration
apiVersion: batch/v1
kind: Job
metadata:
name: myapp-migration
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: myapp:v1.0.0
command: ["./migrate"]
restartPolicy: Never
Post-Sync: Smoke Test
apiVersion: batch/v1
kind: Job
metadata:
name: myapp-smoke-test
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: test
image: curlimages/curl:latest
command:
- sh
- -c
- |
curl -f http://myapp:80/healthz || exit 1
restartPolicy: Never
Helm Value File Structure for GitOps
Organize values for multi-environment:
charts/myapp/
├── values.yaml # Base defaults
├── environments/
│ ├── dev/
│ │ ├── values.yaml # Dev overrides
│ │ └── secrets.enc.yaml # Encrypted secrets
│ ├── staging/
│ │ ├── values.yaml
│ │ └── secrets.enc.yaml
│ └── prod/
│ ├── values.yaml
│ └── secrets.enc.yaml
└── clusters/
├── cluster-1-values.yaml
└── cluster-2-values.yaml
ArgoCD Application references:
helm:
valueFiles:
- values.yaml # Base
- environments/{{env}}/values.yaml # Environment
- clusters/{{cluster}}-values.yaml # Cluster-specific
App of Apps Pattern
Root application that manages other applications:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/cluster-config
targetRevision: HEAD
path: apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
Monitoring ArgoCD Deployments
Check Application Status
# Get application details
argocd app get myapp
# List all applications
argocd app list
# View sync history
argocd app history myapp
# View application events
argocd app events myapp
Prometheus Metrics
# Application sync status
argocd_app_sync_status{name="myapp",namespace="argocd"}
# Application health
argocd_app_health_status{name="myapp",namespace="argocd"}
# Sync operation duration
argocd_app_sync_duration_seconds{name="myapp"}
Alerting Rules
groups:
- name: argocd
rules:
- alert: ApplicationOutOfSync
expr: argocd_app_sync_status{sync_status="OutOfSync"} == 1
for: 15m
annotations:
summary: "Application {{ $labels.name }} is out of sync"
- alert: ApplicationUnhealthy
expr: argocd_app_health_status{health_status="Degraded"} == 1
for: 5m
annotations:
summary: "Application {{ $labels.name }} is unhealthy"
Troubleshooting Common Issues
Issue: Application stuck in "OutOfSync"
Diagnosis:
# Check app details
argocd app get myapp
# View diff
argocd app diff myapp
# Check sync status
argocd app sync myapp --dry-run
Common causes:
- Resource field managed by controller (add to
ignoreDifferences) - Invalid Helm template syntax
- Missing CRD
- Namespace doesn't exist
Issue: Sync fails with "resource already exists"
Solution:
# Add annotation to take ownership
metadata:
annotations:
argocd.argoproj.io/sync-options: Replace=true
Issue: Helm values not being applied
Diagnosis:
# Check rendered values
argocd app manifests myapp
# Verify value file exists in repo
# Check Application spec for correct valueFiles path
Common ArgoCD Commands
# Create application
argocd app create myapp \
--repo https://github.com/myorg/charts \
--path charts/myapp \
--dest-server https://kubernetes.default.svc \
--dest-namespace myapp
# Sync application
argocd app sync myapp
# Sync with prune
argocd app sync myapp --prune
# Delete application
argocd app delete myapp
# Rollback to previous version
argocd app rollback myapp
# View application logs
argocd app logs myapp
# Set application parameters
argocd app set myapp --parameter image.tag=v2.0.0
Resources
Related Agent
For comprehensive Helm/Kubernetes guidance that coordinates this and other Helm skills, use the helm-kubernetes-expert agent.
More from meriley/claude-code-skills
obs-cpp-qt-patterns
C++ and Qt integration patterns for OBS Studio plugins. Covers Qt6 Widgets for settings dialogs, CMAKE_AUTOMOC, OBS frontend API, optional Qt builds with C fallbacks, and modal dialog patterns. Use when adding UI components or C++ features to OBS plugins.
55vendure-developing
Develop Vendure e-commerce plugins, extend GraphQL APIs, create Admin UI components, and define database entities. Use vendure-expert agent for comprehensive guidance across all Vendure development domains.
36vendure-admin-ui-writing
Create Vendure Admin UI extensions with React components, route registration, navigation menus, and GraphQL integration. Handles useQuery, useMutation, useInjector patterns. Use when building Admin UI features for Vendure plugins.
33vendure-entity-writing
Define Vendure database entities extending VendureEntity, with TypeORM decorators, relations, custom fields, and channel-awareness. Use when creating database models in Vendure.
31vendure-graphql-writing
Extend Vendure GraphQL schema with custom types, queries, mutations, and resolvers. Handles RequestContext threading, permissions, and dual Shop/Admin API separation. Use when adding GraphQL endpoints to Vendure.
31vendure-plugin-writing
Create production-ready Vendure plugins with @VendurePlugin decorator, NestJS dependency injection, lifecycle hooks, and configuration patterns. Use when developing new Vendure plugins or extending existing ones.
29