Helm is the package manager for Kubernetes. Think of it as the "apt" or "yum" for Kubernetes applications. It helps you define, install, and upgrade complex Kubernetes applications.
Key Concepts
Chart: A Helm package containing all resource definitions needed to run an application
Release: An instance of a chart running in a Kubernetes cluster
Repository: A place where charts are stored and shared
Why Use Helm?
Simplicity: Deploy complex applications with a single command
Reusability: Package once, deploy anywhere
Versioning: Track and rollback releases easily
Configuration: Customize deployments without modifying templates
Fun Fact: Helm was originally created by Deis (now part of Microsoft) and is now a CNCF graduated project.
Basic Helm Commands
# Search for charts
helm search repo nginx
# Install a chart
helm install my-release bitnami/nginx
# List releases
helm list
# Upgrade a release
helm upgrade my-release bitnami/nginx
# Uninstall a release
helm uninstall my-release
Test Your Knowledge - Lesson 1
1. What is a Helm Chart?
2. What command would you use to install a Helm chart?
3. What is a Helm Release?
Lesson 2: Chart Structure
Creating Your First Chart
Let's create a basic Helm chart from scratch. A chart is organized as a collection of files inside a directory.
apiVersion: v2
name: mychart
description:A Helm chart for my applicationtype: application
version: 0.1.0 # Chart versionappVersion:"1.0"# Version of the appkeywords:
- web
- application
maintainers:
- name: Your Name
email: your.email@example.com
Important: The version field is the chart version (semantic versioning), while appVersion is the version of the application being deployed.
values.yaml - Default Configuration
# Default values for mychartreplicaCount: 1
image:repository: nginx
tag:"1.21"pullPolicy: IfNotPresent
service:type: ClusterIP
port: 80
resources:limits:cpu: 100m
memory: 128Mi
requests:cpu: 100m
memory: 128Mi
Pro Tip: The values.yaml file provides default values that users can override during installation using --set or custom values files.
Test Your Knowledge - Lesson 2
1. Which file contains the chart's metadata?
2. Where are Kubernetes resource templates stored?
3. What is the purpose of values.yaml?
Lesson 3: Templates and Values
Template Basics
Helm uses the Go templating engine to render Kubernetes manifests. Templates allow you to inject values dynamically.
.Release.Namespace: Namespace the release is deployed to
.Chart.Name: Name from Chart.yaml
.Chart.Version: Chart version from Chart.yaml
.Values: Values from values.yaml or user-provided values
Template Functions
# Convert to uppercase
{{ .Values.environment | upper }}
# Default value if not set
{{ .Values.replicas | default 3 }}
# Quote a string
{{ .Values.image.tag | quote }}
# Conditional rendering
{{ if .Values.ingress.enabled }}
enabled: true
{{ else }}
enabled: false
{{ end }}
# Range over a list
{{ range .Values.environments }}
- {{ . }}
{{ end }}
# Download dependencies
helm dependency update ./mychart
# List dependencies
helm dependency list ./mychart
# This creates Chart.lock and downloads charts to charts/ directory
Hooks allow you to intervene at specific points in a release lifecycle.
# Hook example: pre-install jobapiVersion: batch/v1
kind: Job
metadata:name:"{{ .Release.Name }}-db-init"annotations:"helm.sh/hook": pre-install
"helm.sh/hook-weight": "-5""helm.sh/hook-delete-policy": hook-succeeded
spec:template:spec:containers:
- name: db-init
image: mysql:8.0
command: ["/bin/sh", "-c"]
args:
- |
mysql -h mysql -u root -p$MYSQL_ROOT_PASSWORD << EOF
CREATE DATABASE IF NOT EXISTS myapp;
EOF
restartPolicy: Never
Available Hook Points
pre-install: Executes after templates are rendered, but before resources are created
post-install: Executes after all resources are loaded into Kubernetes
pre-upgrade: Executes before upgrade
post-upgrade: Executes after upgrade
pre-delete: Executes before deletion
post-delete: Executes after all resources are deleted
pre-rollback: Executes before rollback
post-rollback: Executes after rollback
Hook Weight: Use hook-weight to order hook execution. Lower weights execute first (can be negative).
Test Your Knowledge - Lesson 5
1. Where are chart dependencies defined?
2. What command downloads chart dependencies?
3. Which hook executes after all resources are created?
Lesson 6: Production Best Practices
Chart Testing and Validation
# Lint your chart for issues
helm lint ./mychart
# Dry-run to see what would be deployed
helm install myapp ./mychart --dry-run --debug
# Template validation
helm template myapp ./mychart
# Install with test
helm test myrelease
Creating Chart Tests
# templates/tests/test-connection.yamlapiVersion: v1
kind: Pod
metadata:name:"{{ include "mychart.fullname" . }}-test"annotations:"helm.sh/hook": test
spec:containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "mychart.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
Security Best Practices
RBAC: Always include proper RBAC resources (ServiceAccount, Role, RoleBinding)
Security Context: Set appropriate security contexts
# Package your chart
helm package ./mychart
# Generate index for chart repository
helm repo index . --url https://charts.example.com
# Sign your chart (security)
helm package --sign --key 'mykey' --keyring ~/.gnupg/secring.gpg ./mychart
# Push to OCI registry
helm push mychart-0.1.0.tgz oci://registry.example.com/charts
Version Management
# Upgrade with rollback on failure
helm upgrade myapp ./mychart --atomic --timeout 5m
# Rollback to previous version
helm rollback myapp
# Rollback to specific revision
helm rollback myapp 3
# View release history
helm history myapp
Production Tip: Always use --atomic flag in production. It automatically rolls back if the upgrade fails.
Documentation
Create comprehensive README.md
Document all values with comments in values.yaml
Include examples for common use cases
Add NOTES.txt for post-installation instructions
# templates/NOTES.txt
Thank you for installing {{ .Chart.Name }}.
Your release is named {{ .Release.Name }}.
To learn more about the release, try:
$ helm status {{ .Release.Name }}
$ helm get all {{ .Release.Name }}
{{ if .Values.ingress.enabled }}
Visit your application at:
{{- range .Values.ingress.hosts }}
http://{{ .host }}
{{- end }}
{{ else }}
Get the application URL by running:
export POD_NAME=$(kubectl get pods -l "app={{ .Chart.Name }}" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 8080:80
{{ end }}
Final Test - Lesson 6
1. Which command checks your chart for potential issues?
2. What flag automatically rolls back on upgrade failure?
3. Why should you avoid using 'latest' as an image tag?