Helm
Helm is the package manager for Kubernetes that bundles manifests into reusable parameterised charts. In CI/CD pipelines, Helm deploys applications with environment-specific values — enabling the same chart to deploy to dev, staging, and production with different configurations.
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 |
TipUse
helm upgrade --atomicin CI pipelines. The--atomicflag 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
helm upgrade --installis 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.
SecurityNever 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 MistakeUsing
helm installinstead ofhelm upgrade --installin CI.helm installfails if the release already exists — which it does on the second pipeline run. Always usehelm upgrade --installin automated pipelines.
Frequently Asked Questions
How does Helm fit into a CI/CD pipeline differently from applying raw Kubernetes manifests?
Raw manifests require separate YAML files (or fragile templating scripts) per environment; Helm consolidates them into one chart parameterized by values files, so a pipeline runs `helm upgrade --install -f values-prod.yaml` instead of maintaining duplicated YAML trees. Helm also tracks release history, so `helm rollback` can revert a bad deploy to the prior revision without the pipeline needing to reconstruct the previous manifest state itself.
What's a common Helm mistake that causes CI/CD deployments to silently fail or hang?
Not passing `--wait` and `--atomic` — without them, `helm upgrade` reports success the instant the API server accepts the manifests, even if the new pods then crash-loop, leaving a broken release marked as deployed. `--atomic` rolls back automatically on failure. Another frequent issue: hardcoding image tags inside the chart templates instead of injecting them via `--set image.tag=$CI_COMMIT_SHA`, which breaks reproducible, pipeline-driven deploys.