Helm cheatsheet.
Install
brew install helm
Repo
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo list
helm repo update
helm search repo nginx
helm search hub redis
Install
helm install my-redis bitnami/redis
helm install my-redis bitnami/redis --version 19.5.0
helm install my-redis bitnami/redis -f values.yaml
helm install my-redis bitnami/redis --set auth.password=x --set replica.replicaCount=3
helm install my-redis bitnami/redis -n redis --create-namespace
helm install my-redis . --dry-run --debug # local chart
Upgrade
helm upgrade my-redis bitnami/redis -f values.yaml
helm upgrade --install my-redis bitnami/redis # upsert
helm upgrade my-redis bitnami/redis --atomic --timeout 5m
helm upgrade my-redis bitnami/redis --reuse-values --set replica.count=5
--atomic: rollback on failure.
List / inspect
helm list
helm list -A # all namespaces
helm status my-redis
helm get values my-redis
helm get values my-redis --all
helm get manifest my-redis # rendered YAML
helm history my-redis
Rollback
helm rollback my-redis 2
helm rollback my-redis 2 --wait
Uninstall
helm uninstall my-redis
helm uninstall my-redis --keep-history
Create chart
helm create mychart
Creates:
mychart/
├── Chart.yaml
├── values.yaml
├── charts/
└── templates/
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── _helpers.tpl
└── NOTES.txt
Chart.yaml
apiVersion: v2
name: mychart
version: 0.1.0
appVersion: "1.0.0"
description: My app
dependencies:
- name: postgresql
version: 14.x.x
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
values.yaml
replicaCount: 2
image:
repository: nginx
tag: "1.27"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
hosts:
- host: chart-example.local
paths: ["/"]
resources:
limits: { cpu: 500m, memory: 256Mi }
requests: { cpu: 100m, memory: 128Mi }
Templates
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mychart.fullname" . }}
labels: {{- include "mychart.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels: {{- include "mychart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels: {{- include "mychart.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
resources: {{- toYaml .Values.resources | nindent 12 }}
Built-in objects
{{ .Release.Name }} # release name
{{ .Release.Namespace }}
{{ .Chart.Name }}
{{ .Chart.Version }}
{{ .Chart.AppVersion }}
{{ .Values.image.tag }}
{{ .Files.Get "config.yaml" }} # file contents
{{ .Capabilities.KubeVersion.Major }}
Templating functions
{{ .Values.name | default "default" }}
{{ .Values.name | upper }}
{{ .Values.name | quote }}
{{ .Values.tag | toString }}
{{ .Values | toYaml | indent 4 }}
{{ range .Values.hosts }}
- host: {{ . }}
{{ end }}
{{ if .Values.enabled }}...{{ end }}
{{ with .Values.image }}{{ .repository }}:{{ .tag }}{{ end }}
Conditionals
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}
Lookup
{{ $secret := lookup "v1" "Secret" .Release.Namespace "my-secret" }}
{{- if $secret }}
existing: true
{{- end }}
Helpers (_helpers.tpl)
{{- define "mychart.labels" -}}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
Dependencies
helm dependency update
helm dependency build
In Chart.yaml:
dependencies:
- name: postgresql
version: 14.x.x
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
alias: db
import-values:
- child: master.service
parent: dbService
Subchart values in values.yaml:
postgresql:
auth:
password: secret
Test
helm lint .
helm template . | less # render to stdout
helm install --dry-run --debug myrelease .
Package + publish
helm package . # creates mychart-0.1.0.tgz
helm push mychart-0.1.0.tgz oci://ghcr.io/me/charts
OCI registry support (no need for chartmuseum).
helmfile (multi-release)
brew install helmfile
# helmfile.yaml
releases:
- name: ingress-nginx
namespace: ingress-nginx
chart: ingress-nginx/ingress-nginx
values: [values/ingress-nginx.yaml]
- name: my-app
namespace: myapp
chart: ./charts/myapp
values: [values/myapp/${ENV:-dev}.yaml]
helmfile sync # apply all
helmfile diff
helmfile destroy
Common mistakes
- Forgetting
--namespace— wrong env. - Indent issues in templates — careful with
nindent. - Hardcoded values in templates instead of values.yaml.
- Not pinning chart version → broken upgrades.
- Mixing helm + kubectl edits → drift.
Read this next
If you want my Helm chart template + helmfile setup, it’s at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .