Helm Fundamentals: Kubernetes Package Manager
Quick answer
Helm turns multi-file Kubernetes manifests into versioned, parameterisable packages called charts. Learn to install charts from registries, override values, upgrade and roll back releases, and create your own chart.
- Installing Helm
- Charts, Releases, and Repositories
- Adding Repositories
- Installing a Chart
- Overriding Values
beginner · 60 min
Before you begin
- Kubernetes basics — Deployments, Services, Namespaces
- kubectl configured and pointing at a cluster
- No prior Helm experience needed
Helm Fundamentals: Kubernetes Package Manager
Deploying a real application to Kubernetes means writing a Deployment, a Service, a ConfigMap, maybe an Ingress and a HorizontalPodAutoscaler — all as separate YAML files. When you need to deploy the same application to dev, staging, and prod with different image tags and replica counts, you're copying files and manually editing values.
Helm solves this. A chart packages all those manifests together, replaces environment-specific values with template variables, and tracks what's deployed as a named release. Install, upgrade, and roll back with a single command.
Installing Helm
1# macOS
2brew install helm
3
4# Linux (official installer)
5curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
6
7# Verify
8helm version
9# version.BuildInfo{Version:"v3.x.x", ...}Helm 3 has no server-side component (Tiller was removed). It talks directly to the Kubernetes API using your ~/.kube/config.
Charts, Releases, and Repositories
Three concepts to internalize:
| Term | Meaning |
|---|---|
| Chart | A package — templates + default values + metadata |
| Release | A named installation of a chart in a cluster (one chart can be installed multiple times as different releases) |
| Repository | A registry of charts (like npm or apt for Kubernetes apps) |
Adding Repositories
Artifact Hub is the public chart registry. Most major projects publish their charts there.
1# Add the Bitnami repository (one of the most widely used)
2helm repo add bitnami https://charts.bitnami.com/bitnami
3
4# Add the ingress-nginx repository
5helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
6
7# Update the local cache (like apt update)
8helm repo update
9
10# List configured repositories
11helm repo listSearching for charts
1# Search your configured repos
2helm search repo nginx
3
4# Search Artifact Hub (requires internet)
5helm search hub nginx
6
7# See all versions of a chart
8helm search repo bitnami/nginx --versionsInstalling a Chart
1# Install nginx from Bitnami as a release named "my-nginx"
2helm install my-nginx bitnami/nginx
3
4# Install into a specific namespace (create it if needed)
5helm install my-nginx bitnami/nginx --namespace web --create-namespace
6
7# Install a specific chart version
8helm install my-nginx bitnami/nginx --version 18.1.0
9
10# See what would be installed without doing it
11helm install my-nginx bitnami/nginx --dry-runAfter install, Helm shows a NOTES section with the chart's own instructions — usually how to get the service URL.
Listing releases
helm list
helm list -n web # In a specific namespace
helm list --all-namespacesChecking release status
helm status my-nginx
helm status my-nginx -n webOverriding Values
Every chart has a values.yaml that defines defaults. Override them at install time.
See what's configurable
# Show all default values
helm show values bitnami/nginx
# Show chart description and README
helm show readme bitnami/nginx
helm show chart bitnami/nginxOverride on the command line
1# Single value
2helm install my-nginx bitnami/nginx --set replicaCount=3
3
4# Multiple values
5helm install my-nginx bitnami/nginx \
6 --set replicaCount=3 \
7 --set service.type=ClusterIP
8
9# Nested values (dot notation)
10helm install my-nginx bitnami/nginx \
11 --set resources.requests.cpu=100m \
12 --set resources.requests.memory=128MiOverride with a values file
For more than a few values, use a file:
1# my-values.yaml
2replicaCount: 3
3
4service:
5 type: ClusterIP
6 port: 80
7
8resources:
9 requests:
10 cpu: 100m
11 memory: 128Mi
12 limits:
13 cpu: 500m
14 memory: 256Mihelm install my-nginx bitnami/nginx -f my-values.yamlLayer multiple files (later files win):
helm install my-nginx bitnami/nginx \
-f base-values.yaml \
-f prod-values.yamlUpgrading a Release
1# Upgrade with a new value
2helm upgrade my-nginx bitnami/nginx --set replicaCount=5
3
4# Upgrade to a specific chart version
5helm upgrade my-nginx bitnami/nginx --version 18.2.0
6
7# Upgrade, or install if not present (idempotent — use in CI)
8helm upgrade --install my-nginx bitnami/nginx -f my-values.yamlhelm upgrade --install is the standard CI/CD pattern — it works whether the release exists or not.
View upgrade history
helm history my-nginx
# REVISION STATUS DESCRIPTION
# 1 superseded Install complete
# 2 deployed Upgrade completeRolling Back
1# Roll back to the previous revision
2helm rollback my-nginx
3
4# Roll back to a specific revision
5helm rollback my-nginx 1
6
7# Dry run
8helm rollback my-nginx 1 --dry-runRollback is just another upgrade — it creates a new revision pointing at the old configuration.
Uninstalling
helm uninstall my-nginx
helm uninstall my-nginx -n web
# Keep release history after uninstall (useful for auditing)
helm uninstall my-nginx --keep-historyRendering Templates Without Installing
# Render all templates to stdout (debugging)
helm template my-nginx bitnami/nginx -f my-values.yaml
# Render a specific template
helm template my-nginx bitnami/nginx -f my-values.yaml -s templates/deployment.yamlhelm template never connects to the cluster. Use it to inspect what would actually be applied.
Linting a chart
helm lint ./my-chartCreating Your Own Chart
helm create my-appThis scaffolds:
my-app/
├── Chart.yaml # Chart name, version, description, appVersion
├── values.yaml # Default values
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── hpa.yaml
│ ├── serviceaccount.yaml
│ ├── NOTES.txt # Post-install message
│ └── _helpers.tpl # Named templates (reusable snippets)
└── charts/ # Bundled chart dependencies
Helm templating basics
Templates use Go's text/template package with Sprig helper functions.
1# templates/deployment.yaml
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: {{ .Release.Name }}-{{ .Chart.Name }}
6 labels:
7 app: {{ .Chart.Name }}
8 release: {{ .Release.Name }}
9 version: {{ .Chart.AppVersion | quote }}
10spec:
11 replicas: {{ .Values.replicaCount }}
12 selector:
13 matchLabels:
14 app: {{ .Chart.Name }}
15 template:
16 metadata:
17 labels:
18 app: {{ .Chart.Name }}
19 spec:
20 containers:
21 - name: {{ .Chart.Name }}
22 image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
23 ports:
24 - containerPort: {{ .Values.service.port }}
25 resources:
26 {{- toYaml .Values.resources | nindent 12 }}Key built-in objects:
| Object | Example | Meaning |
|---|---|---|
.Release.Name | my-app | The release name given at install |
.Release.Namespace | production | The namespace |
.Release.IsInstall | true | First install (vs upgrade) |
.Chart.Name | my-app | Chart name from Chart.yaml |
.Chart.Version | 0.1.0 | Chart version |
.Chart.AppVersion | 1.5.2 | Application version |
.Values.xxx | .Values.replicaCount | Value from values.yaml |
Named templates in _helpers.tpl
Files starting with _ are not rendered as Kubernetes objects — they hold reusable template definitions.
# templates/_helpers.tpl
{{- define "my-app.labels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}Use in a template:
metadata:
labels:
{{- include "my-app.labels" . | nindent 4 }}Chart dependencies
Declare dependencies in Chart.yaml:
dependencies:
- name: postgresql
version: "13.x.x"
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled # Only include if values.postgresql.enabled is truehelm dependency update ./my-app # Download dependencies into charts/Install Your Chart
1# From local directory
2helm install my-app ./my-app -f my-values.yaml
3
4# Package it
5helm package ./my-app
6# Produces: my-app-0.1.0.tgz
7
8# Install from package
9helm install my-app ./my-app-0.1.0.tgzFrequently Asked Questions
Where does Helm store release state?
As Secrets in the release's namespace, not on your machine. That is why anyone with access can roll back a release from anywhere, and why an interrupted upgrade can leave a release stuck — the record exists but the operation never completed.
Why is my values override being ignored?
Almost always a path mismatch: the key does not exist at that location in the chart, so Helm accepts it and nothing consumes it. It does not warn about unknown keys. Ask Helm for the release's computed values and compare against what you intended.
How do I see what a chart will do before applying it?
Render it locally with helm template, or run the upgrade as a dry run to see what would be applied. Neither shows a diff against the live release — that needs the helm-diff plugin. Rendering first turns most template errors into a local problem rather than a partially applied release.
Why does upgrading a chart not upgrade its CRDs?
Because Helm deliberately installs CRDs on first install and never upgrades or deletes them — deleting a CRD deletes every object of that kind. Upgrade CRDs as an explicit step and read the chart's upgrade notes, which is where charts most often expect manual action.
What's Next
- Kubernetes Core Concepts — Deployments, Services, and Namespaces that Helm manages
- Helmfile: Managing Multiple Helm Releases — deploy many charts together as a unit
- Helm Best Practices for Production — pinned chart versions, values structure, and CI patterns
Official References
- Helm chart template guide — templates, values and the sprig function set
- Helm charts — chart structure, dependencies and hooks
Next in Helm: Kubernetes Package Management
Helmfile: Managing Multiple Helm Releases
We built Podscape to simplify Kubernetes workflows like this — logs, events, and cluster state in one interface, without switching tools.
Struggling with this in production?
We help teams fix these exact issues. Our engineers have deployed these patterns across production environments at scale.