Helm — The Kubernetes Package Manager
Deploying a real application to Kubernetes often requires dozens of YAML files — Deployments, Services, ConfigMaps, Secrets, Ingress, RBAC rules, and more. Helm is the package manager for Kubernetes that bundles all these resources into reusable, configurable packages called charts.
What is Helm?
Helm is to Kubernetes what apt is to Ubuntu or brew is to macOS. It:
- Packages multiple Kubernetes manifests into a single unit (a chart)
- Templates YAML files with configurable values
- Manages releases — install, upgrade, rollback, uninstall
- Shares charts through repositories (like Docker Hub for K8s apps)
Installing Helm
macOS
brew install helm
Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Windows
choco install kubernetes-helm
Verify
helm version
Key Concepts
| Concept | Description |
|---|---|
| Chart | A package of pre-configured Kubernetes resources |
| Repository | A collection of charts (like a package registry) |
| Release | A specific instance of a chart deployed to a cluster |
| Values | Configuration parameters that customize a chart |
Chart (template) + Values (config) = Release (deployed instance)
Working with Helm Repositories
# Add a popular repository
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stable https://charts.helm.sh/stable
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# Update repository index
helm repo update
# Search for charts
helm search repo nginx
helm search repo postgresql
# Search Artifact Hub (public registry)
helm search hub wordpress
Installing Charts
Basic Install
# Install nginx from bitnami
helm install my-nginx bitnami/nginx
# Install with a specific version
helm install my-nginx bitnami/nginx --version 15.0.0
# Install in a specific namespace
helm install my-nginx bitnami/nginx --namespace web --create-namespace
Install with Custom Values
# Override values inline
helm install my-nginx bitnami/nginx \
--set replicaCount=3 \
--set service.type=NodePort
# Override using a values file
helm install my-nginx bitnami/nginx -f my-values.yaml
Create my-values.yaml:
replicaCount: 3
service:
type: NodePort
port: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
View Default Values
# See all configurable values for a chart
helm show values bitnami/nginx
# See chart information
helm show chart bitnami/nginx
# See everything
helm show all bitnami/nginx
Managing Releases
# List installed releases
helm list
helm list --all-namespaces
# Check release status
helm status my-nginx
# Get the manifest (rendered YAML)
helm get manifest my-nginx
# Get the values used
helm get values my-nginx
Upgrading Releases
# Upgrade with new values
helm upgrade my-nginx bitnami/nginx --set replicaCount=5
# Upgrade with a values file
helm upgrade my-nginx bitnami/nginx -f production-values.yaml
# Install or upgrade (create if doesn't exist)
helm upgrade --install my-nginx bitnami/nginx -f values.yaml
Rollback
# View release history
helm history my-nginx
# Rollback to previous revision
helm rollback my-nginx
# Rollback to a specific revision
helm rollback my-nginx 2
Output of helm history:
REVISION STATUS DESCRIPTION
1 superseded Install complete
2 superseded Upgrade complete
3 deployed Rollback to 2
Uninstalling Releases
# Uninstall a release
helm uninstall my-nginx
# Keep the history (allows rollback even after uninstall)
helm uninstall my-nginx --keep-history
Creating Your Own Chart
Scaffold a Chart
helm create my-app
This creates the chart structure:
my-app/
├── Chart.yaml # Chart metadata
├── values.yaml # Default configuration
├── charts/ # Dependencies
├── templates/ # Kubernetes manifest templates
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── serviceaccount.yaml
│ ├── hpa.yaml
│ ├── _helpers.tpl # Template helpers
│ ├── NOTES.txt # Post-install message
│ └── tests/
│ └── test-connection.yaml
└── .helmignore
Chart.yaml
apiVersion: v2
name: my-app
description: A Helm chart for my web application
type: application
version: 0.1.0 # Chart version
appVersion: "1.0.0" # Application version
values.yaml
replicaCount: 2
image:
repository: my-app
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
hosts:
- host: my-app.example.com
paths:
- path: /
pathType: Prefix
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
Templates with Go Templating
Templates use Go template syntax with Helm-specific functions:
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "my-app.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-app.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 80
resources:
{{- toYaml .Values.resources | nindent 12 }}
Common Template Functions
| Function | Description | Example |
|---|---|---|
{{ .Values.key }} |
Access values | {{ .Values.replicaCount }} |
{{ .Release.Name }} |
Release name | {{ .Release.Name }} |
{{ .Chart.Name }} |
Chart name | {{ .Chart.Name }} |
default |
Default value | {{ default "nginx" .Values.image.repository }} |
quote |
Quote a string | {{ .Values.name \| quote }} |
toYaml |
Convert to YAML | {{ toYaml .Values.resources }} |
nindent |
New line + indent | {{ toYaml .Values.labels \| nindent 4 }} |
if/else |
Conditionals | {{ if .Values.ingress.enabled }}...{{ end }} |
range |
Loops | {{ range .Values.hosts }}...{{ end }} |
Testing and Debugging Charts
# Render templates locally (without installing)
helm template my-release ./my-app
# Render with custom values
helm template my-release ./my-app -f staging-values.yaml
# Dry run — validate against cluster
helm install my-release ./my-app --dry-run --debug
# Lint the chart for issues
helm lint ./my-app
Chart Dependencies
Add dependencies in Chart.yaml:
dependencies:
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
- name: redis
version: "17.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
# Download dependencies
helm dependency update ./my-app
# Dependencies are stored in charts/
ls ./my-app/charts/
Hands-On: Deploy WordPress with Helm
# Add Bitnami repo
helm repo add bitnami https://charts.bitnami.com/bitnami
# Install WordPress
helm install my-blog bitnami/wordpress \
--set wordpressUsername=admin \
--set wordpressPassword=MyP@ssword \
--set service.type=NodePort \
--set mariadb.primary.persistence.size=1Gi \
--set persistence.size=1Gi
# Watch the deployment
kubectl get pods -w
# Get the access URL (Minikube)
minikube service my-blog-wordpress --url
# Check the status
helm status my-blog
helm get values my-blog
Helm Commands Cheat Sheet
| Command | Description |
|---|---|
helm repo add NAME URL |
Add a repository |
helm repo update |
Update repo index |
helm search repo KEYWORD |
Search charts |
helm install RELEASE CHART |
Install a chart |
helm upgrade RELEASE CHART |
Upgrade a release |
helm rollback RELEASE [REV] |
Rollback a release |
helm uninstall RELEASE |
Uninstall a release |
helm list |
List releases |
helm status RELEASE |
Release status |
helm history RELEASE |
Release history |
helm show values CHART |
Show chart values |
helm template RELEASE CHART |
Render templates locally |
helm create NAME |
Create a new chart |
helm lint CHART |
Check chart for issues |
helm package CHART |
Package chart for distribution |
Summary
- Helm is the package manager for Kubernetes
- Charts package multiple K8s resources into reusable units
- Values customize charts for different environments
- Releases track deployed instances with version history
- Use
helm upgrade --installfor idempotent deployments - Rollback to any previous revision with
helm rollback - Create custom charts for your own applications
What’s Next?
Now let’s learn about Monitoring and Logging — setting up observability for your Kubernetes cluster with Prometheus, Grafana, and centralized logging using the EFK stack.