Chapter 10.2 - Helm Charts
Learning Objectives
By the end of this chapter, you will be able to:
- Understand the structure of a Helm Chart
- Create a Chart from scratch
- Use Go templates
- Customize with values.yaml
- Manage dependencies
- Publish a Chart
Introduction
A Helm Chart is a package containing all the files needed to deploy an application in Kubernetes. It uses templates to make YAML files dynamic.
Chart Structure
Complete Structure
my-chart/
├── Chart.yaml # Chart metadata
├── Chart.lock # Dependency lock file
├── values.yaml # Default values
├── values.schema.json # Validation schema (optional)
├── templates/ # Kubernetes templates
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl # Reusable helpers
│ └── NOTES.txt # Notes displayed after installation
├── charts/ # Dependent Charts (optional)
└── README.md # Documentation
Creating a Chart
Creating a Basic Chart
# Create a new Chart
helm create my-chart
# Created structure
my-chart/
├── Chart.yaml
├── values.yaml
└── templates/
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── _helpers.tpl
└── NOTES.txt
Chart.yaml
apiVersion: v2
name: my-chart
description: A Helm chart for my application
type: application
version: 0.1.0
appVersion: "1.0.0"
keywords:
- web
- application
maintainers:
- name: John Doe
email: john@example.com
Go Templates
Basic Syntax
Templates use the Go templates syntax:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-deployment
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
Available Variables
.Release.Name: Release name.Release.Namespace: Namespace.Chart.Name: Chart name.Values.*: Values from values.yaml.Capabilities.*: Cluster information
values.yaml
Example values.yaml
# Number of replicas
replicaCount: 3
# Image
image:
repository: nginx
tag: "1.20"
pullPolicy: IfNotPresent
# Service
service:
type: ClusterIP
port: 80
# Ingress
ingress:
enabled: true
className: nginx
hosts:
- host: example.com
paths:
- path: /
pathType: Prefix
tls: []
# Resources
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
Complete Example: Web App Chart
Chart.yaml
apiVersion: v2
name: web-app
description: A simple web application
type: application
version: 0.1.0
appVersion: "1.0.0"
values.yaml
replicaCount: 2
image:
repository: myapp
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8080
ingress:
enabled: true
className: nginx
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "web-app.fullname" . }}
labels:
{{- include "web-app.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "web-app.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "web-app.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 8080
name: http
resources:
{{- toYaml .Values.resources | nindent 10 }}
templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "web-app.fullname" . }}
labels:
{{- include "web-app.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "web-app.selectorLabels" . | nindent 4 }}
templates/_helpers.tpl
{{/*
Common labels
*/}}
{{- define "web-app.labels" -}}
app.kubernetes.io/name: {{ include "web-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "web-app.selectorLabels" -}}
app.kubernetes.io/name: {{ include "web-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Full name
*/}}
{{- define "web-app.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name }}
{{- end }}
Installing a Local Chart
Install
# From a local directory
helm install my-release ./my-chart
# With custom values
helm install my-release ./my-chart -f custom-values.yaml
# With inline values
helm install my-release ./my-chart \
--set replicaCount=5 \
--set image.tag=1.1.0
Update
# Update
helm upgrade my-release ./my-chart
# With new values
helm upgrade my-release ./my-chart -f new-values.yaml
Dependencies
Chart.yaml with Dependencies
apiVersion: v2
name: my-app
dependencies:
- name: postgresql
version: "12.0.0"
repository: "https://charts.bitnami.com/bitnami"
- name: redis
version: "17.0.0"
repository: "https://charts.bitnami.com/bitnami"
Installing Dependencies
# Download dependencies
helm dependency update
# View dependencies
helm dependency list
Packaging and Distribution
Creating a Package
# Create a .tgz package
helm package ./my-chart
# Result: my-chart-0.1.0.tgz
Publishing to a Repository
# Add to repository
helm repo index . --url https://charts.example.com
# Upload the package
# (depending on your storage method)
Useful Commands
Validation
# Linter
helm lint ./my-chart
# Template with dry-run
helm install my-release ./my-chart --dry-run --debug
# View computed values
helm template my-release ./my-chart
Testing
# Install in test mode
helm install my-release ./my-chart --dry-run
# View generated manifest
helm get manifest my-release
Best Practices
1. Clear Structure
Organize templates logically.
2. Helpers
Use _helpers.tpl for reusable code.
3. Documentation
Document all values in values.yaml.
4. Validation
Use values.schema.json to validate values.
5. Versioning
Follow semantic versioning for Charts.
Summary
In this chapter, you learned:
Structure: Chart.yaml, values.yaml, templates/, charts/
Go Templates: Syntax with double curly braces, available variables
values.yaml: Customizable default values
Helpers: _helpers.tpl for reusable code
Dependencies: Management via Chart.yaml
Packaging: helm package to create .tgz
Installation: helm install from local or repository
Best practices: Structure, helpers, documentation, versioning
Next Steps
Chapter 10.3: Advanced Templates and Hooks
Lab 10.2: Customization with values.yaml
Lab 10.3: Creating a Custom Chart
Chapter created on: December 2024