Helm — The Kubernetes Package Manager

5 minute read

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 --install for 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.

Next: Monitoring and Logging →

Updated: