Helm Package Manager for Kubernetes
Helm is the package manager for Kubernetes. It bundles all the Kubernetes resources for an application into a single versioned package called a chart, and provides commands to install, upgrade, roll back, and remove that package as a unit. This page covers how charts work, how to use Helm with AKS, and when to use it instead of plain kubectl.
Charts, releases, and repositories
Three concepts underpin everything in Helm:
A chart is a collection of files that describe a set of Kubernetes resources. It contains YAML templates with placeholder variables, a values.yaml file with defaults for those variables, a Chart.yaml file with metadata like name and version, and optionally a README and schema validation. Charts can be packaged as .tgz archives and shared via a repository.
A release is an instance of a chart installed in a Kubernetes cluster. If you install the same chart twice — once as staging-nginx and once as prod-nginx — you have two releases, each independent with its own configuration and upgrade history.
A repository is an HTTP server hosting packaged charts and an index file. The original stable repository was https://charts.helm.sh/stable but has been deprecated. Modern charts are hosted on Artifact Hub or on dedicated repositories maintained by each project.
Installing Helm and adding repositories
Helm is a single binary. On macOS install it with Homebrew; on Linux download it from the official release page or use the install script; on Windows use Chocolatey or the binary directly.
# macOS
brew install helm
# Linux (install script)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Verify
helm versionAdd repositories before you can search for or install charts from them:
# Add the ingress-nginx chart repo
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# Add Jetstack (for cert-manager)
helm repo add jetstack https://charts.jetstack.io
# Update your local repo cache
helm repo update
# Search for charts
helm search repo ingress-nginx
helm search hub cert-manager # searches Artifact HubInstalling and upgrading releases
Install a chart into your AKS cluster with helm install. The first argument is the release name; the second is the chart reference (repo/chartname or a local path).
# Create the namespace first
kubectl create namespace ingress-nginx
# Install ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.replicaCount=2 \
--set controller.nodeSelector."kubernetes\.io/os"=linux
# Check release status
helm status ingress-nginx -n ingress-nginx
# List all installed releases across all namespaces
helm list --all-namespacesTo install cert-manager, which requires CRDs (Custom Resource Definitions) to be installed first:
# Install CRDs separately
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.crds.yaml
# Install cert-manager chart
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.14.4When a new chart version is available or you want to change configuration, use helm upgrade:
# Upgrade to a new chart version
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--version 4.10.0 \
--reuse-values
# Upgrade and change a value
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.replicaCount=3 \
--reuse-values—reuse-values carries forward all previously set values, so you only need to specify what changes. Without it, Helm resets to chart defaults for any value you do not explicitly provide.
Configuring charts with values.yaml
Every chart has a values.yaml file that defines the configurable parameters and their defaults. You override these by providing your own values file or using —set flags.
For production, create an environment-specific values file and commit it to source control. This makes your exact configuration reproducible and reviewable:
# prod-values.yaml
controller:
replicaCount: 3
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
service:
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
config:
proxy-body-size: "50m"
use-forwarded-headers: "true"# Install using a values file
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
-f prod-values.yaml
# Combine a file with individual overrides
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
-f prod-values.yaml \
--set controller.replicaCount=4To see what values a chart accepts before installing it:
# Show the full default values.yaml for a chart
helm show values ingress-nginx/ingress-nginx
# Show only the chart metadata
helm show chart ingress-nginx/ingress-nginxRollbacks and release history
Helm stores the history of every upgrade for each release. If an upgrade breaks something, you can roll back to any previous revision.
# Show the history of a release
helm history ingress-nginx -n ingress-nginx
# Output looks like:
# REVISION STATUS CHART DESCRIPTION
# 1 superseded ingress-nginx-4.9.0 Install complete
# 2 superseded ingress-nginx-4.9.0 Upgrade complete
# 3 deployed ingress-nginx-4.10.0 Upgrade complete
# Roll back to the previous revision
helm rollback ingress-nginx -n ingress-nginx
# Roll back to a specific revision
helm rollback ingress-nginx 1 -n ingress-nginx
# Verify after rollback
helm status ingress-nginx -n ingress-nginxRolling back a Helm release does not automatically roll back PersistentVolumeClaims or other stateful resources that were created by the chart. Data resources require separate handling.
Helm history is kept as Kubernetes Secrets. By default, Helm retains the last 10 revisions. You can change this with the —history-max flag during install or by setting HELM_MAX_HISTORY in your environment.
Helm vs plain kubectl apply
For simple single-service applications, managing a handful of YAML files with kubectl is entirely reasonable. Helm adds value when the complexity grows.
| Scenario | kubectl apply | Helm |
|---|---|---|
| Single Deployment + Service | Simple, no extra tooling | Overhead not justified |
| App with 10+ resources across Deployments, RBAC, Ingress | Tedious to manage atomically | Single install/upgrade command |
| Deploy to multiple environments with different config | Duplicate YAML files with edits | One chart, multiple values files |
| Rolling back a broken deployment | Manual — re-apply old YAML | helm rollback |
| Installing open-source software (nginx, cert-manager) | Find and apply upstream YAML | helm install from repo |
| Atomic install (all resources succeed or none do) | No built-in atomicity | Atomic with —atomic flag |
Use kubectl for your own simple workloads. Use Helm when you are installing third-party software, managing applications that span many resource types, or deploying to multiple environments where configuration differs.
Uninstalling a release
helm uninstall removes all Kubernetes resources that were created by the release and deletes the release history:
# Uninstall a release
helm uninstall ingress-nginx -n ingress-nginx
# Keep history for auditing (resources still deleted)
helm uninstall ingress-nginx -n ingress-nginx --keep-history
# Dry run — show what would be deleted
helm uninstall ingress-nginx -n ingress-nginx --dry-runResources not created by Helm — such as PersistentVolumeClaims that were created dynamically by StatefulSets — are not deleted by helm uninstall. You must delete those manually.
Common mistakes
- Using —set for all configuration instead of a values file. Flags like
—set controller.replicaCount=3are not tracked anywhere. The next person who runs helm upgrade without the same flags will reset that value to the chart default. Always put environment-specific configuration in a committed values file. - Installing CRD-heavy charts without reading the install notes. Some charts like cert-manager and Prometheus Operator create Custom Resource Definitions that the chart itself then tries to use. If the CRDs are not registered before the resources that depend on them, the install fails. Check the chart documentation before running helm install.
- Not pinning chart versions in production. Running
helm upgrade myapp myrepo/myappwithout a—versionflag installs the latest chart version, which may include breaking changes. Always specify—versionin production pipelines and test new versions in staging before rolling to production.
Summary
- Helm packages Kubernetes resources into charts — versioned, configurable bundles that can be installed as releases with a single command.
- Use values files rather than —set flags to configure releases per environment; commit those files to source control alongside your application code.
- helm upgrade —reuse-values updates a release incrementally; helm rollback returns to any previous revision stored in the release history.
- Helm is most valuable for complex multi-resource applications and for installing third-party software from public chart repositories.
Frequently asked questions
What is the difference between a Helm chart and a release?
A chart is the package — a directory of templates, a values file, and metadata. A release is a specific installation of a chart in a cluster with a given set of values. You can install the same chart multiple times in different namespaces, and each installation is a separate release with its own name and history.
Does Helm store release state in the cluster?
Yes. Helm 3 stores release metadata as Kubernetes Secrets in the same namespace as the release. This means release history is available to anyone with read access to Secrets in that namespace. It also means no separate Helm server (Tiller) is needed — Helm 3 is entirely client-side.
How do I override chart values without editing values.yaml?
Use the --set flag for individual values: helm install myapp ./chart --set image.tag=2.1.0. For multiple overrides, create a separate override file and use -f: helm install myapp ./chart -f prod-values.yaml. The -f approach is better for production because the overrides are tracked in a file you can commit to source control.