Skip to content

10 - Helm

What this session is

About 45 minutes. Helm - Kubernetes' package manager. Lets you install complex applications (Postgres, Prometheus, cert-manager, ingress controllers, dozens of services) with one command, parameterized via values.

The problem

Some OSS applications are 20+ Kubernetes resources: a Deployment, a StatefulSet, several Services, ConfigMaps, Secrets, an Ingress, NetworkPolicies, ServiceAccount, ClusterRole, ClusterRoleBinding. Maintaining that as a stack of YAML files is painful.

A Helm chart packages them with templates and a single values file. Install with helm install. Upgrade with helm upgrade. Rollback with helm rollback. One command.

Install Helm

brew install helm           # macOS
sudo snap install helm --classic     # Ubuntu
# or download from helm.sh

Verify:

helm version

Add a chart repository

Helm charts live in repositories (HTTP servers + index file). Add one:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

Bitnami publishes high-quality charts for most popular OSS (PostgreSQL, Redis, RabbitMQ, MongoDB, etc.).

Other popular repos: - https://prometheus-community.github.io/helm-charts - https://grafana.github.io/helm-charts - https://kubernetes.github.io/ingress-nginx - https://charts.jetstack.io (cert-manager)

Search and install

helm search repo postgresql
helm install mydb bitnami/postgresql --namespace db --create-namespace

helm install arguments: - mydb - your release name (the install's identity). - bitnami/postgresql - <repo>/<chart>. - --namespace db --create-namespace - install in the db namespace; create it if it doesn't exist.

Helm renders the chart's templates into Kubernetes manifests and kubectl applys them. Many resources are created - a Service, StatefulSet, Secret with the auto-generated password, ConfigMap, ServiceAccount, etc.

Inspect:

helm list -A                              # list releases across all namespaces
kubectl get all -n db                     # all the resources Helm created
helm get manifest mydb -n db              # the actual rendered YAML

Configure via values

Every chart has a values.yaml with configurable defaults. Override:

helm show values bitnami/postgresql | head -50

Create your own myvalues.yaml:

auth:
  postgresPassword: my-secret-password
  database: myapp
primary:
  persistence:
    size: 5Gi
resources:
  requests:
    memory: "256Mi"
    cpu: "100m"

Install with your values:

helm install mydb bitnami/postgresql -f myvalues.yaml -n db --create-namespace

Or override individual values:

helm install mydb bitnami/postgresql \
  --set auth.postgresPassword=secret \
  --set auth.database=myapp \
  -n db --create-namespace

-f file is cleaner for non-trivial config; --set for one-off tweaks.

Upgrade and rollback

After installation, update config:

helm upgrade mydb bitnami/postgresql -f myvalues.yaml -n db

Helm computes the diff and applies. Tracks revisions:

helm history mydb -n db

Rollback to a previous revision:

helm rollback mydb 1 -n db

Uninstall (removes everything Helm created):

helm uninstall mydb -n db

A chart's structure

A Helm chart on disk:

mychart/
├── Chart.yaml              (metadata: name, version, dependencies)
├── values.yaml             (default values)
├── README.md
├── templates/
│   ├── deployment.yaml     (with Go template placeholders)
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── _helpers.tpl        (reusable template snippets)
│   └── NOTES.txt           (printed after install)
└── charts/                 (vendored dependency charts)

Templates use Go's templating language:

# templates/deployment.yaml (excerpt)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    spec:
      containers:
      - name: app
        image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
        resources:
          {{- toYaml .Values.resources | nindent 10 }}

{{ .Values.X }} reads from values.yaml. {{ .Release.Name }} is the install's name. The chart author writes templates; users pass values.

Reading a chart

When you encounter a chart in an OSS project:

  1. Chart.yaml - name, version, dependencies.
  2. values.yaml - what's configurable (with defaults).
  3. templates/ - what resources get created.
  4. README.md - usage docs; often has tables of all values.

helm template renders the chart without installing - useful to see what it WOULD create:

helm template mydb bitnami/postgresql -f myvalues.yaml | head -100

Write your own chart (brief)

helm create myapp

Generates a starter chart with sensible defaults: Deployment, Service, Ingress, optional ServiceAccount, HPA. Edit the templates and values.yaml for your app.

Test render:

helm template ./myapp

Install locally:

helm install myapp ./myapp

For a real first chart, start by adapting helm create's output. Many OSS projects ship a chart in charts/ or helm/ for their own deployment.

Helmfile / values per environment

Real apps have dev / staging / prod with different values. Patterns:

  • Multiple values files: values-dev.yaml, values-prod.yaml. helm install -f values-base.yaml -f values-prod.yaml.
  • Helmfile - a tool that wraps Helm with a higher-level declarative spec.
  • Argo CD / Flux - GitOps tools that watch your git repo and apply Helm releases. Beyond beginner; widely used.

Exercise

  1. Install Helm.
  2. Add Bitnami repo:
    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm repo update
    
  3. Install Postgres with custom values:
    echo 'auth:
      postgresPassword: secret123' > myvals.yaml
    helm install mydb bitnami/postgresql -f myvals.yaml -n db --create-namespace
    helm list -A
    kubectl get all -n db
    
  4. Inspect rendered manifests:
    helm template mydb bitnami/postgresql -f myvals.yaml | head -50
    
  5. Upgrade: change myvals.yaml (e.g. raise memory), helm upgrade mydb ... -n db.
  6. Cleanup:
    helm uninstall mydb -n db
    kubectl delete namespace db
    

What you might wonder

"Helm vs Kustomize?" Two ways to manage K8s YAML. - Helm: templates + values. Better for distributing reusable apps. - Kustomize: patches over base YAML. Built into kubectl (kubectl apply -k .). Better for "I want to tweak existing YAML." Many teams use both: Helm for third-party charts; Kustomize for their own apps.

"Is Helm 'production-grade'?" Yes. Used everywhere. Helm 3 (current) is solid. Helm 2 (deprecated) had a Tiller server that was a known security issue; H3 is client-side only.

"What's helm install actually doing?" 1. Fetches the chart (from a repo or local). 2. Resolves values (defaults + your overrides). 3. Renders templates. 4. Calls kubectl apply for the rendered YAML. 5. Records the release in a Secret (or ConfigMap) in the target namespace.

That last step is how helm list works - it queries those Secrets to find releases.

Done

  • Install Helm.
  • Add chart repos.
  • Install / upgrade / rollback / uninstall charts.
  • Override values via files or --set.
  • Read a chart's structure.
  • Render templates without installing.

Next: kubectl power tools →

Comments