Understanding Helm in CI/CD
What Is Helm in Simple Terms
Helm is to Kubernetes what apt is to Ubuntu. Instead of managing dozens of separate YAML files for a Deployment, Service, Ingress, ConfigMap, and HPA, Helm packages them all into a single chart. You deploy the chart with helm install and configure it with a values file.
In CI/CD, Helm solves the configuration-per-environment problem: the same chart deploys to dev (2 replicas, small instance), staging (3 replicas, medium), and production (10 replicas, large) — just with different values files. One chart, one source of truth, multiple environments.
How It Works
+------------------------------------------+| Helm Chart: payment-api/ || Chart.yaml -- metadata, version || values.yaml -- default values || templates/ -- Kubernetes manifests || deployment.yaml || service.yaml || ingress.yaml |+------------------------------------------+ | +-- values-staging.yaml (override) | replicas: 3 | image.tag: abc123 | +-- values-production.yaml (override) | replicas: 10 | image.tag: abc123 | v+------------------------------------------+| helm upgrade --install payment-api ./ || --values values-production.yaml || --set image.tag=$IMAGE_TAG |+------------------------------------------+ | v+------------------------------------------+| Kubernetes manifests rendered and applied|+------------------------------------------+Helm in GitHub Actions pipeline:
steps: - uses: actions/checkout@v4 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789:role/github-deploy aws-region: ap-south-1 - name: Update kubeconfig run: aws eks update-kubeconfig --name mumbai-prod-cluster --region ap-south-1 - name: Deploy with Helm run: | helm upgrade --install payment-api ./charts/payment-api \ --namespace payment-api-production \ --values ./charts/payment-api/values-production.yaml \ --set image.repository=${{ env.ECR_REGISTRY }}/payment-api \ --set image.tag=${{ github.sha }} \ --set replicaCount=10 \ --atomic \ --timeout 5m \ --wait ## --atomic: rollback automatically if deployment fails ## --wait: wait for all pods to be ready ## --timeout: fail if not ready within 5 minutesChart values structure:
## values.yaml -- defaultsreplicaCount: 2 image: repository: payment-api tag: latest ## overridden in CI with git SHA pullPolicy: IfNotPresent resources: limits: cpu: 500m memory: 512Mi requests: cpu: 250m memory: 256Mi autoscaling: enabled: false minReplicas: 2 maxReplicas: 20 targetCPUUtilizationPercentage: 70Practical Commands
## Install or upgrade a releasehelm upgrade --install release-name ./chart-dir \ --namespace my-namespace --create-namespace ## Check what would change (dry run)helm upgrade --dry-run --debug release-name ./chart-dir ## List all releaseshelm list -A ## across all namespaces ## Check release historyhelm history payment-api -n production ## Rollback to previous versionhelm rollback payment-api 2 -n production## (2 = revision number from helm history) ## Uninstall a releasehelm uninstall payment-api -n production ## Add community chart repositoryhelm repo add bitnami https://charts.bitnami.com/bitnamihelm repo updatehelm search repo bitnami/postgresqlTroubleshooting
| Symptom | Check | What to Look For |
|---|---|---|
| Release stuck in pending-upgrade | helm history release |
Previous upgrade failed and left lock |
| Template rendering error | helm template ./chart |
Syntax error in template file |
| Values not applying | helm get values release |
Check currently applied values |
| Pods not starting after helm apply | kubectl describe pod |
Image pull error or resource limits |
PLACEMENT PRO TIP**Tip:** Use `helm upgrade --atomic` in CI pipelines. The `--atomic` flag makes the upgrade roll back automatically if any deployed resources fail to become ready within the timeout. Without it, a failed deployment leaves the release in a broken state that requires manual intervention.
REMEMBER THIS**Remember:** `helm upgrade --install` is the idempotent deployment command. It installs the chart if the release does not exist and upgrades it if it does. This means your CI pipeline runs the exact same command regardless of whether it is a first-time deploy or an update.
COMMON MISTAKE / WARNING**Security:** Never put secrets directly in values.yaml files committed to Git. Use Helm with an external secrets operator (External Secrets Operator, Sealed Secrets, or Vault) to inject secrets at deploy time. The values.yaml in your Git repository should contain only non-sensitive configuration.
COMMON MISTAKE / WARNING**Common Mistake:** Using `helm install` instead of `helm upgrade --install` in CI. `helm install` fails if the release already exists — which it does on the second pipeline run. Always use `helm upgrade --install` in automated pipelines.