Helm Hooks

A comprehensive guide to Helm hooks covering pre-install, post-install, pre-upgrade, post-upgrade hooks, and best practices for lifecycle management in Helm charts.

Pre-Install Post-Install Pre-Upgrade Post-Upgrade
What are Helm Hooks?

Helm hooks are special resources that run at specific points during the lifecycle of a Helm release. They allow you to perform tasks like database migrations, initialization, cleanup, and validation during installation, upgrade, or deletion.

Hooks are defined as annotations on Kubernetes resources and are managed by Helm during the release lifecycle.

Pre-Install Install Post-Install Pre-Upgrade Upgrade Post-Upgrade
Key Concept: Hooks are executed in a specific order and can be used to ensure that dependencies are ready, data is migrated, or cleanup is performed before or after the main resources are deployed.
Hook Types

pre-install

Before installation
Executed before the installation of the chart. Used for pre-installation setup, validation, or resource creation.

post-install

After installation
Executed after all resources are installed. Used for post-installation tasks like database migrations or seeding data.

pre-upgrade

Before upgrade
Executed before the upgrade of the chart. Used for pre-upgrade validation, backup, or cleanup.

post-upgrade

After upgrade
Executed after the upgrade is complete. Used for post-upgrade tasks like database migrations or service restarts.

pre-delete

Before deletion
Executed before the chart is deleted. Used for cleanup, data backup, or validation before removal.

post-delete

After deletion
Executed after the chart is deleted. Used for cleanup tasks that require the release to be removed.

test

Test hooks
Used with helm test to validate the installation. These are not run during normal installation/upgrade.

pre-rollback

Before rollback
Executed before a rollback operation. Used for validation or preparation before reverting.

post-rollback

After rollback
Executed after a rollback operation. Used for cleanup or verification after reverting.
Defining Hooks

Hooks are defined using the helm.sh/hook annotation on Kubernetes resources.

# Pre-install hook example (database migration) apiVersion: batch/v1 kind: Job metadata: name: {{ include "my-app.fullname" . }}-db-migration annotations: helm.sh/hook: pre-install helm.sh/hook-weight: "5" helm.sh/hook-delete-policy: hook-succeeded spec: template: spec: containers: - name: migration image: myapp-migration:latest env: - name: DB_URL value: {{ .Values.database.url }} command: ["/bin/sh", "-c", "python migrate.py"] restartPolicy: Never # Post-install hook example (seeding data) apiVersion: batch/v1 kind: Job metadata: name: {{ include "my-app.fullname" . }}-seed-data annotations: helm.sh/hook: post-install helm.sh/hook-weight: "10" helm.sh/hook-delete-policy: hook-succeeded spec: template: spec: containers: - name: seed image: myapp-seed:latest env: - name: DB_URL value: {{ .Values.database.url }} command: ["/bin/sh", "-c", "python seed.py"] restartPolicy: Never # Pre-upgrade hook (backup before upgrade) apiVersion: batch/v1 kind: Job metadata: name: {{ include "my-app.fullname" . }}-backup annotations: helm.sh/hook: pre-upgrade helm.sh/hook-weight: "1" helm.sh/hook-delete-policy: before-hook-creation spec: template: spec: containers: - name: backup image: myapp-backup:latest env: - name: DB_URL value: {{ .Values.database.url }} command: ["/bin/sh", "-c", "pg_dump > /backups/pre-upgrade.sql"] restartPolicy: Never # Post-upgrade hook (validate after upgrade) apiVersion: batch/v1 kind: Job metadata: name: {{ include "my-app.fullname" . }}-validate annotations: helm.sh/hook: post-upgrade helm.sh/hook-weight: "20" helm.sh/hook-delete-policy: hook-succeeded,hook-failed spec: template: spec: containers: - name: validate image: myapp-validator:latest command: ["/bin/sh", "-c", "python validate.py"] restartPolicy: Never
Hook Best Practices:
  • Use meaningful hook names
  • Set appropriate hook weights to control execution order
  • Use hook-delete-policy to manage hook cleanup
  • Make hooks idempotent (can be run multiple times safely)
  • Test hooks thoroughly in different scenarios
Hook Annotations

helm.sh/hook

Specifies the hook type (e.g., pre-install, post-install). Multiple hooks can be specified with commas.

helm.sh/hook-weight

Controls the execution order of hooks (lower weights execute first). Default is 0.

helm.sh/hook-delete-policy

Controls when hooks are deleted. Options: hook-succeeded, hook-failed, before-hook-creation.

helm.sh/hook-skip-install

Skips the hook during installation (useful for upgrade-only hooks).
# Hook with multiple annotations apiVersion: batch/v1 kind: Job metadata: name: migration-job annotations: # Hook type (multiple allowed) helm.sh/hook: pre-install,pre-upgrade # Weight for ordering (lower = earlier) helm.sh/hook-weight: "5" # Delete policy helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded # Skip during install (only run on upgrade) helm.sh/hook-skip-install: "true" spec: template: spec: containers: - name: migration image: myapp-migration:latest command: ["python", "migrate.py"] restartPolicy: Never
Hook Weight Ordering: Hooks with lower weights execute first. If multiple hooks have the same weight, the order is not guaranteed. Use weights to control dependencies between hooks.
Hook Delete Policies

hook-succeeded

Delete the hook after it successfully completes. Default behavior for most hooks.

hook-failed

Delete the hook if it fails. Useful for debugging failed hooks.

before-hook-creation

Delete the hook before creating a new one. Ensures clean state for each run.

hook-succeeded,hook-failed

Delete the hook regardless of outcome. Clean up after completion.
# Examples of delete policies # Delete on success only metadata: annotations: helm.sh/hook-delete-policy: hook-succeeded # Delete on failure only (for debugging) metadata: annotations: helm.sh/hook-delete-policy: hook-failed # Delete before each run (clean state) metadata: annotations: helm.sh/hook-delete-policy: before-hook-creation # Delete regardless of outcome metadata: annotations: helm.sh/hook-delete-policy: hook-succeeded,hook-failed # Multiple policies metadata: annotations: helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
Delete Policy Considerations:
  • Use before-hook-creation to ensure clean state
  • Use hook-succeeded to clean up successful hooks
  • Consider hook-failed for debugging failed hooks
  • Multiple policies can be combined with commas
  • Test delete policies to avoid orphaned resources
Common Hook Patterns

Database Migration

Run database migrations before the application starts. Use pre-install or pre-upgrade hooks.

Data Seeding

Seed initial data after installation. Use post-install hooks with appropriate weights.

Backup Before Upgrade

Take backups before upgrading. Use pre-upgrade hooks with high priority.

Validation After Upgrade

Validate the application after upgrade. Use post-upgrade hooks to verify functionality.

Cleanup

Clean up resources before deletion. Use pre-delete hooks for safe removal.

Health Check

Run health checks after installation or upgrade. Use test hooks with helm test.
# Database Migration Hook apiVersion: batch/v1 kind: Job metadata: name: {{ include "my-app.fullname" . }}-migration annotations: helm.sh/hook: pre-install,pre-upgrade helm.sh/hook-weight: "1" helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded spec: template: spec: containers: - name: migration image: {{ .Values.image.repository }}:{{ .Values.image.tag }} command: - /bin/sh - -c - | python manage.py migrate echo "Migration completed successfully" env: - name: DATABASE_URL value: {{ .Values.database.url }} restartPolicy: Never # Health Check Hook apiVersion: v1 kind: Pod metadata: name: {{ include "my-app.fullname" . }}-health-check annotations: helm.sh/hook: test helm.sh/hook-delete-policy: hook-succeeded spec: containers: - name: health-check image: curlimages/curl:latest command: - /bin/sh - -c - | curl -f http://{{ include "my-app.fullname" . }}:{{ .Values.service.port }}/health echo "Health check passed" restartPolicy: Never
Hook Pattern Best Practices:
  • Make hooks idempotent (safe to run multiple times)
  • Use appropriate weights for ordering
  • Test hooks in isolation
  • Handle failures gracefully
  • Use appropriate delete policies to avoid resource accumulation
Debugging Hooks
# Dry-run to see hooks helm install my-release ./my-chart --dry-run --debug # See hook execution order helm install my-release ./my-chart --dry-run --debug | grep -A 10 hooks # Check hook status kubectl get jobs --all-namespaces | grep -E "pre|post|hook" # View hook logs kubectl logs <hook-job-pod> # Test hooks in isolation # Use --set to enable/disable hooks # Force hook execution helm install my-release ./my-chart --set hooks.enabled=true # Skip hooks helm install my-release ./my-chart --set hooks.enabled=false # Debug hook failures kubectl describe job <hook-job> kubectl logs <hook-pod> # Check hook annotations kubectl get job <hook-job> -o yaml | grep -A 5 annotations
Common Hook Issues:
  • Hooks not executing: Check annotations and hook type
  • Hook failures: Check logs and resources
  • Orphaned hooks: Check delete policies
  • Order issues: Check hook weights
  • Resource conflicts: Check for name collisions
Frequently Asked Questions
What are Helm hooks used for?
Helm hooks are used to perform tasks at specific points during the Helm release lifecycle, such as pre-installation setup, post-installation configuration, pre-upgrade backups, and post-upgrade validation.
How do I order hooks?
Use the helm.sh/hook-weight annotation. Hooks with lower weights execute first. If weights are equal, the order is not guaranteed.
What is the difference between pre-install and post-install hooks?
Pre-install hooks run before the chart is installed. Post-install hooks run after all resources are installed. Use pre-install for validation or setup, post-install for configuration or seeding.
How do I delete hooks after they run?
Use the helm.sh/hook-delete-policy annotation. Options include hook-succeeded, hook-failed, and before-hook-creation.
Can I have multiple hooks of the same type?
Yes, you can have multiple hooks of the same type. Use hook weights to control their execution order.
What is a test hook?
A test hook is a special hook that runs with helm test. It validates the installation and can be used for health checks and verification.
Can hooks use values from the chart?
Yes, hooks are rendered like regular templates and can access all chart values, including global values and subchart values.
What happens if a hook fails?
If a hook fails, the installation or upgrade will be aborted. The failed hook will remain for debugging. Use appropriate delete policies to manage failed hooks.
Previous: Chart Dependencies Next: Helm Templating

Helm hooks enable powerful lifecycle management in your charts. Use them to automate tasks like database migrations, backups, and validation, making your deployments more robust and reliable.