Chapter 10.3 - Advanced Templates and Hooks
Learning Objectives
By the end of this chapter, you will be able to:
- Use advanced Go template functions
- Implement conditions and loops
- Use Helm Hooks
- Manage dependencies between resources
- Create reusable templates
- Optimize Charts
Introduction
Helm templates allow you to create dynamic and reusable Kubernetes configurations. Hooks allow you to execute actions at specific points in the lifecycle.
Advanced Template Functions
Conditions
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}-ingress
spec:
...
{{- end }}
Loops
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value }}
{{- end }}
Default Values
replicas: {{ .Values.replicaCount | default 3 }}
image: {{ .Values.image.repository | default "nginx" }}
Concatenation
name: {{ printf "%s-%s" .Release.Name .Chart.Name }}
Include
{{- include "my-chart.labels" . | nindent 4 }}
Helm Hooks
Hooks allow you to execute Jobs or Pods at specific points.
Hook Types
pre-install: Before installationpost-install: After installationpre-upgrade: Before upgradepost-upgrade: After upgradepre-delete: Before deletionpost-delete: After deletionpre-rollback: Before rollbackpost-rollback: After rollback
Example: Pre-install Hook
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-pre-install
annotations:
"helm.sh/hook": pre-install
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
containers:
- name: pre-install
image: busybox:1.35
command: ["/bin/sh", "-c", "echo 'Pre-install hook'"]
restartPolicy: Never
Example: Post-install Hook
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-post-install
annotations:
"helm.sh/hook": post-install
"helm.sh/hook-weight": "5"
spec:
template:
spec:
containers:
- name: post-install
image: busybox:1.35
command: ["/bin/sh", "-c", "echo 'Post-install hook'"]
restartPolicy: Never
Hook Annotations
hook-weight
Controls execution order:
"helm.sh/hook-weight": "-5" # Executed first
"helm.sh/hook-weight": "5" # Executed last
hook-delete-policy
When to delete the Hook:
before-hook-creation: Before creating a new hookhook-succeeded: If the hook succeedshook-failed: If the hook fails
"helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
Complete Example: Database Migration
Pre-upgrade Hook: Backup
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-pre-upgrade-backup
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "-10"
spec:
template:
spec:
containers:
- name: backup
image: postgres:14
command:
- /bin/bash
- -c
- |
pg_dump -h {{ .Release.Name }}-postgres mydb > /backup/backup-$(date +%Y%m%d).sql
aws s3 cp /backup/backup-$(date +%Y%m%d).sql s3://backups/
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: {{ .Release.Name }}-postgres-secret
key: password
volumeMounts:
- name: backup
mountPath: /backup
volumes:
- name: backup
emptyDir: {}
restartPolicy: Never
Post-upgrade Hook: Migration
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-post-upgrade-migrate
annotations:
"helm.sh/hook": post-upgrade
"helm.sh/hook-weight": "10"
spec:
template:
spec:
containers:
- name: migrate
image: my-app:{{ .Values.appVersion }}
command: ["/app/migrate.sh"]
env:
- name: DATABASE_URL
value: postgresql://postgres:5432/mydb
restartPolicy: OnFailure
Reusable Templates
Advanced _helpers.tpl
{{/*
Common labels
*/}}
{{- define "my-chart.labels" -}}
app.kubernetes.io/name: {{ include "my-chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "my-chart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "my-chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Chart name
*/}}
{{- define "my-chart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Full name
*/}}
{{- define "my-chart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
Best Practices
1. Use Helpers
Create reusable helpers in _helpers.tpl.
2. Appropriate Conditions
Use conditions to make templates flexible.
3. Judicious Hooks
Use hooks only when necessary (migrations, backups).
4. Documentation
Document hooks and their purpose.
5. Testing
Test hooks with --dry-run.
Summary
In this chapter, you learned:
Advanced functions: Conditions, loops, default values, concatenation
Hooks: Pre/post install/upgrade/delete/rollback
Annotations: hook-weight, hook-delete-policy
Use cases: Migrations, backups, initialization
Reusable templates: Helpers in _helpers.tpl
Best practices: Helpers, conditions, judicious hooks, testing
Next Steps
Module 11: Monitoring and Observability
Lab 10.4: Helmfile and Multi-environments
Chapter created on: December 2024