| name | helm-charts |
| description | Helm package manager for Kubernetes. Use when creating, managing, or debugging Helm charts, writing Chart.yaml or values.yaml files, templating K8s manifests with Go templates, managing Helm releases (install, upgrade, rollback), working with Helm repositories, creating chart libraries, or troubleshooting Helm deployment issues. Covers chart structure, values overrides, hooks, tests, dependencies, and OCI registry usage. |
Helm Package Manager
Comprehensive guidance for managing Kubernetes applications with Helm charts, from chart creation to production deployment patterns.
Quick Start
Basic operations
helm install my-release ./chart -n namespace
helm upgrade my-release ./chart -n namespace -f values.yaml
helm rollback my-release 1 -n namespace
helm uninstall my-release -n namespace
helm list -n namespace
helm list -A
Repository management
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm search repo nginx
helm search hub prometheus
Chart Structure
Standard layout
mychart/
├── Chart.yaml # Chart metadata (name, version, dependencies)
├── Chart.lock # Locked dependency versions
├── values.yaml # Default configuration values
├── values.schema.json # Optional JSON schema for values validation
├── templates/
│ ├── _helpers.tpl # Template helpers (named templates)
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── hpa.yaml
│ ├── serviceaccount.yaml
│ ├── NOTES.txt # Post-install usage instructions
│ └── tests/
│ └── test-connection.yaml
├── charts/ # Dependency charts (vendored)
└── .helmignore # Files to exclude from packaging
Chart.yaml
apiVersion: v2
name: my-app
description: A Helm chart for my application
type: application
version: 1.2.0
appVersion: "3.1.0"
keywords:
- app
- backend
home: https://github.com/org/my-app
sources:
- https://github.com/org/my-app
maintainers:
- name: Team Name
email: team@example.com
dependencies:
- name: postgresql
version: "~13.0"
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
- name: redis
version: "~18.0"
repository: https://charts.bitnami.com/bitnami
values.yaml
replicaCount: 2
image:
repository: gcr.io/my-project/my-app
tag: ""
pullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
annotations: {}
name: ""
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: false
className: traefik
annotations: {}
hosts:
- host: app.example.com
paths:
- path: /
pathType: Prefix
tls: []
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory:
[]
[]
{}
{}
{}
[]
{}
Go Templating
Template helpers (_helpers.tpl)
{{/*
Expand the name of the chart.
*/}}
{{- define "mychart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "mychart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{
}}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{
}}
{{ }}
{{ }}
{{ }}
{{ }}
{{
}}
{{ }}
{{ }}
{{ }}
{{
}}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
Common template patterns
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
{{- end }}
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
{{- include "mychart.labels" . | nindent 4 }}
resources:
{{- toYaml .Values.resources }}
{{ }}
{{ }}
Deployment template
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "mychart.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
labels:
{{- include "mychart.labels" . | nindent 8 }}
spec:
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
{{ }}
Values Management
Override strategies
helm install my-release ./chart -f values.yaml
helm install my-release ./chart \
-f values.yaml \
-f values-prod.yaml
helm install my-release ./chart \
-f values.yaml \
--set image.tag=v1.2.3 \
--set replicaCount=3
helm install my-release ./chart --set-string annotations."key"="value"
helm install my-release ./chart --set-file config=./app-config.json
Environment-specific values pattern
chart/
├── values.yaml # Defaults
├── values-dev.yaml # Dev overrides
├── values-staging.yaml # Staging overrides
└── values-prod.yaml # Production overrides
helm upgrade --install my-release ./chart \
-f values.yaml \
-f values-prod.yaml \
-n production
values.schema.json (validation)
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["image", "service"],
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1
},
"image": {
"type": "object",
"required": ["repository"],
"properties": {
"repository": { "type": "string" },
"tag":
Hooks
Pre/post install and upgrade hooks
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "mychart.fullname" . }}-db-migrate
annotations:
"helm.sh/hook": pre-upgrade,pre-install
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
command: ["python", "manage.py", "migrate"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
backoffLimit: 1
Hook types
| Hook | Description |
|---|
pre-install | Before any resources are installed |
post-install | After all resources are installed |
pre-upgrade | Before any resources are upgraded |
post-upgrade | After all resources are upgraded |
pre-delete | Before any resources are deleted |
post-delete | After all resources are deleted |
pre-rollback | Before rollback |
post-rollback | After rollback |
test | When helm test is invoked |
Delete policies
before-hook-creation — delete previous hook resource before new one is created
hook-succeeded — delete after hook succeeds
hook-failed — delete after hook fails
Chart Tests
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "mychart.fullname" . }}-test-connection"
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "mychart.fullname" . }}:{{ .Values.service.port }}/healthz']
helm test my-release -n namespace
helm test my-release -n namespace --logs
Dependencies
Managing chart dependencies
helm dependency update ./chart
helm dependency list ./chart
helm dependency build ./chart
Conditional dependencies
dependencies:
- name: postgresql
version: "~13.0"
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
tags:
- database
Overriding dependency values
postgresql:
enabled: true
auth:
postgresPassword: secret
database: myapp
primary:
persistence:
size: 10Gi
OCI Registry
Push and pull charts via OCI
helm registry login gcr.io -u _json_key --password-stdin < key.json
helm package ./chart
helm push my-app-1.2.0.tgz oci://gcr.io/my-project/charts
helm pull oci://gcr.io/my-project/charts/my-app --version 1.2.0
helm install my-release oci://gcr.io/my-project/charts/my-app --version 1.2.0
Library Charts
Creating a library chart
apiVersion: v2
name: common-lib
type: library
version: 1.0.0
{{- define "common-lib.deployment" -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "common-lib.fullname" . }}
labels:
{{- include "common-lib.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "common-lib.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "common-lib.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
resources:
{{ }}
{{ }}
Using a library chart
dependencies:
- name: common-lib
version: "1.0.0"
repository: "file://../common-lib"
{{- include "common-lib.deployment" . }}
Release Management
Inspect releases
helm history my-release -n namespace
helm get values my-release -n namespace
helm get values my-release -n namespace -a
helm get manifest my-release -n namespace
helm get notes my-release -n namespace
helm get all my-release -n namespace
Upgrade patterns
helm upgrade my-release ./chart -n namespace \
-f values.yaml \
--atomic \
--timeout 5m
helm upgrade --install my-release ./chart -n namespace -f values.yaml
helm upgrade my-release ./chart -n namespace -f values.yaml --dry-run
helm diff upgrade my-release ./chart -n namespace -f values.yaml
Rollback
helm rollback my-release -n namespace
helm rollback my-release 3 -n namespace
helm rollback my-release 3 -n namespace --wait --timeout 5m
Debugging
helm template my-release ./chart -f values.yaml
helm template my-release ./chart -f values.yaml --debug
helm install my-release ./chart -f values.yaml --dry-run --debug
helm lint ./chart
helm lint ./chart -f values.yaml
helm show values ./chart
helm show chart ./chart
helm show readme ./chart
Common issues
Template rendering errors:
helm template my-release ./chart -s templates/deployment.yaml
helm template my-release ./chart | kubectl apply --dry-run=client -f -
Release stuck in pending/failed:
helm status my-release -n namespace
helm uninstall my-release -n namespace --no-hooks
kubectl delete secret -l owner=helm,name=my-release -n namespace
Best Practices
- Use
helm upgrade --install for idempotent deployments
- Use
--atomic in CI/CD to auto-rollback failed upgrades
- Pin chart versions in dependencies — avoid floating versions
- Use
values.schema.json to validate values before rendering
- Include NOTES.txt with post-install instructions
- Use named templates in
_helpers.tpl — avoid duplication across templates
- Add checksum annotations for ConfigMaps/Secrets to trigger pod restart on config changes
- Test charts with
helm lint, helm template, and helm test
- Separate chart version from app version — bump chart version for chart changes, appVersion for application changes
- Use
.helmignore to exclude CI files, tests, and docs from packaged chart
Package Requirements
This skill requires:
helm >= 3.0 — Kubernetes package manager
kubectl — for cluster access and validation
- Optional:
helm-diff plugin — for previewing upgrade changes