Skip to main content

Helm and Helm Chart

A package manager for Kubernetes that bundles all required Kubernetes manifests into a reusable unit called a chart. Helm templates variables at deploy time, enabling the same chart to deploy consistently across dev, staging, and production environments with different configurations.

Helm — Comprehensive Production Guide

Helm eliminates the chaos of managing 5-6 separate Kubernetes YAML files per service. Instead of manually editing Deployment, Service, Ingress, and ServiceAccount manifests for every deploy, Helm packages them into one versioned chart and applies them with a single command.

Remember

Helm is to Kubernetes what npm is to Node.js — a package manager that handles versioning, upgrades, and rollbacks.


Helm Chart

A chart is the core Helm unit — a folder containing all Kubernetes manifest templates and configuration defaults for one application.

Chart structure

Bash
my-chart/
├── Chart.yaml # chart name, version, description
├── values.yaml # default config values
└── templates/
├── deployment.yaml # pod spec template
├── service.yaml # networking template
├── ingress.yaml # external access template
└── serviceaccount.yaml

Chart.yaml

YAML
apiVersion: v2
name: devops-network
description: Helm chart for DevOps Network Next.js app
type: application
version: 0.1.2
appVersion: "1.0.0"
Remember

version is the chart version — bump it every time you change templates. appVersion is the version of the application itself.

Templates use Go template variables that Helm fills at deploy time:

YAML
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: {{ .Values.service.port }}
{{- if .Values.extraEnvs }}
env:
{{- toYaml .Values.extraEnvs | nindent 12 }}
{{- end }}
{{- if .Values.extraVolumeMounts }}
volumeMounts:
{{- toYaml .Values.extraVolumeMounts | nindent 12 }}
{{- end }}
{{- if .Values.extraVolumes }}
volumes:
{{- toYaml .Values.extraVolumes | nindent 8 }}
{{- end }}
Tip

Always add extraVolumes and extraVolumeMounts support to your deployment template from the start. Adding them later requires a chart version bump and redeployment.


values.yaml

The default configuration file for a chart. All tunable parameters live here — image tag, replica count, resource limits, env vars. Environment-specific files like dev.values.yaml override these defaults at deploy time.

Base values.yaml

YAML
replicaCount: 1
image:
repository: 905418385260.dkr.ecr.ap-south-1.amazonaws.com/my-app
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 3000
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
extraEnvs: []
extraVolumes: []
extraVolumeMounts: []

Environment override — dev.values.yaml

Only include keys you want to override. Everything else falls back to values.yaml:

YAML
ingress:
enabled: true
className: nginx
hosts:
- host: app.devopsnetwork.in
paths:
- path: /
pathType: ImplementationSpecific
serviceAccount:
create: true
name: devops-network-sa
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::905418385260:role/my-irsa-role
extraEnvs:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: aws-secrets-manager-secret
key: database-url
Common Mistake

Putting secrets as plain text in values.yaml committed to your repo. Always use secretKeyRef pointing to a Kubernetes Secret, and store actual values in AWS Secrets Manager or Vault.


Helm Release

A running instance of a Helm chart deployed to a Kubernetes cluster. The same chart can be installed multiple times as different releases — each with its own name, namespace, and values. Helm tracks each release's revision history, enabling instant upgrades and rollbacks.

Core release commands

Bash
# Install a new release
helm install devops-network ./chart -f dev.values.yaml -n devops-network
# Upgrade an existing release
helm upgrade devops-network ./chart -f dev.values.yaml -n devops-network
# Install or upgrade (useful in CI pipelines)
helm upgrade --install devops-network ./chart -f dev.values.yaml -n devops-network
# Atomic upgrade — auto rollback on failure
helm upgrade --atomic devops-network ./chart -f prod.values.yaml -n production
# View all releases
helm list -n devops-network
# View revision history
helm history devops-network -n devops-network
# Roll back to a specific revision
helm rollback devops-network 2 -n devops-network
# Remove a release
helm uninstall devops-network -n devops-network

Revision history example

TEXT
REVISION STATUS CHART DESCRIPTION
1 deployed devops-network-0.1.0 Install complete
2 deployed devops-network-0.1.1 Upgrade complete
3 failed devops-network-0.1.2 Upgrade failed
Security

Rollback restores Kubernetes resource config only — Deployment spec, env vars, image tag. It does NOT revert database migrations or external state. Always test rollback in staging before a production incident.

Tip

Always use --atomic in production pipelines. If new pods fail health checks, Helm automatically rolls back to the previous revision without manual intervention.


Helmfile

A declarative wrapper on top of Helm. Instead of running separate helm upgrade commands for each environment, Helmfile lets you define all releases, charts, and environment-specific values in one helmfile.yaml — deploying everything with a single helmfile apply command.

helmfile.yaml

YAML
releases:
- name: devops-network
chart: oci://905418385260.dkr.ecr.eu-north-1.amazonaws.com/devops-network-helm/devops-network-testing
version: {{ .StateValues.CHART_VERSION | quote }}
namespace: devops-network-testing
installed: true
values:
- values.yaml
- "{{ .Environment.Name }}.values.yaml"
set:
- name: image.tag
value: {{ .StateValues.BUILD_ID | quote }}

Deploy commands

Bash
# Deploy dev environment
helmfile -e dev apply
# Deploy prod environment
helmfile -e prod apply
# Pass dynamic values at runtime (e.g. from CI pipeline)
helmfile -e dev \
--state-values-set CHART_VERSION="0.1.2" \
--state-values-set BUILD_ID="1.0.5" \
apply
# Preview diff before applying (uses helm-diff plugin)
helmfile -e dev diff

How value merging works

Helmfile layers values files in order — later files override earlier ones:

◈ DIAGRAM
values.yaml ← base defaults (replicas, resources, image repo)
+
dev.values.yaml ← environment overrides (ingress host, secrets, env vars)
=
Final merged config ← sent to Helm for templating
Remember

Helmfile only upgrades releases that have actual changes — it runs helm diff internally and skips unchanged releases. This makes helmfile apply safe to run on every pipeline push.


OCI Chart Registry

Helm charts can be stored in any OCI-compatible container registry alongside Docker images. AWS ECR, GitHub Container Registry, and Docker Hub all support OCI chart storage — no separate chart server needed.

Push chart to ECR

Bash
# Authenticate
aws ecr get-login-password --region ap-south-1 \
| helm registry login 905418385260.dkr.ecr.ap-south-1.amazonaws.com \
--username AWS --password-stdin
# Package and push
helm package ./devops-network-chart
helm push devops-network-chart-0.1.2.tgz \
oci://905418385260.dkr.ecr.ap-south-1.amazonaws.com/devops-network-helm

Reference OCI chart in helmfile.yaml

YAML
chart: oci://905418385260.dkr.ecr.ap-south-1.amazonaws.com/devops-network-helm/devops-network-chart
version: "0.1.2"
Common Mistake

Using a flat ECR repo name like devops-network-helm. ECR OCI push requires the full nested path — devops-network-helm/devops-network-chart as the repository name. Creating the repo with just the parent name will cause a push failure.


Quick Reference

Command What it does
helm install <name> <chart> Install a new release
helm upgrade --install <name> <chart> Install or upgrade
helm upgrade --atomic <name> <chart> Upgrade with auto rollback on failure
helm rollback <name> <revision> Restore a previous revision
helm history <name> View revision history
helm list -n <namespace> List all releases in namespace
helm template <name> <chart> Preview rendered YAML without deploying
helm diff upgrade <name> <chart> Show diff before upgrading
helmfile -e <env> apply Deploy all releases for an environment
helmfile -e <env> diff Preview all changes before applying

Frequently Asked Questions

What's actually inside a Helm chart, and how does templating work at deploy time?

A chart is a directory with a Chart.yaml (metadata), a templates/ folder of Kubernetes manifests written with Go template syntax, and a values.yaml supplying default variables. At install time, Helm's templating engine substitutes values into the templates and renders final YAML, which it then applies via the Kubernetes API — similar to how Jinja renders a config file, but purpose-built for Kubernetes object structure.

When should you use a Helm chart versus plain Kustomize overlays?

Helm suits packaging reusable, distributable applications — especially third-party software you install as-is with a few overridden values (databases, ingress controllers, monitoring stacks). Kustomize suits patching your own manifests across environments without a templating layer, since it works with plain YAML and overlay patches rather than a templating language. Many teams use both: Helm for vendored charts, Kustomize for their own app overlays.