Command Palette

Search for a command to run...

Hectal
PHASE 7Intermediate ~14 min· topic 4 of 4

Topic 7.4

Helm Hooks & Chart Dependencies

In one line

Hooks let a chart run something at a specific point in its own lifecycle (like a database migration before the app starts); dependencies let one chart pull in and manage other charts it genuinely relies on.

0/4 · 0%

Key ideas

  1. 01

    A HELM HOOK is a Kubernetes resource (almost always a Job, Phase 1.4) annotated to run at a SPECIFIC POINT in a release's lifecycle — pre-install/pre-upgrade (before the main resources are created/updated), post-install/post-upgrade (after), and several others — genuinely useful for exactly the kind of 'run this once, at this specific moment' task a plain chart install/upgrade doesn't otherwise have a clean way to express.

  2. 02

    The classic real use case: a pre-upgrade hook running a DATABASE MIGRATION Job before the application's own Deployment is updated to a new version that expects the new schema to already exist — ensuring the migration genuinely completes successfully BEFORE any new application code that depends on it actually starts running.

  3. 03

    A hook is just a normal Kubernetes Job with a special annotation ("helm.sh/hook": pre-upgrade) — Helm specifically watches for this annotation and orchestrates running it at the correct point, waiting for it to complete successfully before proceeding with the rest of the release's normal resources.

  4. 04

    CHART DEPENDENCIES let one chart declare that it relies on OTHER charts — a genuinely common real example: your own application's chart declaring a dependency on the official, community-maintained PostgreSQL or Redis chart, rather than writing and maintaining your own Deployment/StatefulSet/Service manifests for a database you didn't build yourself.

  5. 05

    Dependencies are declared in a Chart.yaml's dependencies section (name, version, and a repository URL) — helm dependency update downloads the declared dependency charts into a charts/ subfolder, and installing your OWN chart then automatically installs its dependencies too, as part of the same single release.

  6. 06

    This mirrors Docker Compose's own depends_on (Docker's own course) at a conceptually similar level — 'this thing needs that thing to also exist' — though Helm dependencies specifically handle bundling and versioning OTHER PEOPLE'S charts cleanly, rather than just sequencing your own already-known services.

Code & diagrams

HookOrderingdiagram

A pre-upgrade hook completes fully before the main upgrade proceeds — never running concurrently with it.

Rendering diagram…
migration-hook.yamlmarkdown

A real pre-upgrade migration hook — just a Job with one special annotation.

apiVersion: batch/v1
kind: Job
metadata:
  name: {{ .Release.Name }}-db-migration
  annotations:
    "helm.sh/hook": pre-upgrade,pre-install
    "helm.sh/hook-weight": "0"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: migrate
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          command: ["./run-migrations.sh"]
chart-dependency.yamlmarkdown

Declaring a real dependency on the official, community-maintained PostgreSQL chart.

# Chart.yaml
apiVersion: v2
name: my-app-chart
version: 1.0.0
dependencies:
  - name: postgresql
    version: "13.2.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled   # can be toggled off via values.yaml
hooks-and-deps.shmarkdown

Watch a hook run in order, and pull in a real dependency chart.

# Download the declared dependency chart(s) into charts/
helm dependency update ./my-app-chart

# Install — the migration hook runs FIRST, automatically, before the main app
helm install my-release ./my-app-chart
kubectl get jobs
# my-release-db-migration — Completed, before the Deployment's pods even started

# Confirm the dependency (e.g. PostgreSQL) was installed as part of the SAME release
kubectl get statefulsets
# my-release-postgresql — installed automatically alongside your own app

Explain it without notes

01

Why is a pre-upgrade hook genuinely necessary for a database migration, rather than just adding the migration step inside the application container's own startup script?

02

Why would a team declare a dependency on the official community PostgreSQL chart rather than writing their own StatefulSet/Service manifests for it directly?

Practice

01

Add a pre-install hook Job to a test chart (even a trivial one that just echoes a message) and confirm with kubectl get jobs that it runs and completes before the chart's main Deployment appears.

02

Add a dependency on a public community chart (like the official Bitnami PostgreSQL or Redis chart) to a test chart's Chart.yaml, run helm dependency update, and confirm the dependency's resources are installed alongside your own.

Trade-offs

  • ↔

    Hooks and dependencies add real power and reduce duplicated effort, but they also mean a chart's true behavior isn't always fully visible just by reading its main templates — a migration silently running via a hook, or an entire database being installed as a side effect of a dependency declaration, can genuinely surprise someone unfamiliar with the chart's full structure; documenting a chart's hooks and dependencies clearly (in its own README) matters as much as writing them correctly in the first place.

Done when you can

  • I can write a Helm hook that runs a Job at a specific point in a release's lifecycle.

  • I understand why a pre-upgrade hook is a safer place for a database migration than an application's own startup script.

  • I can declare a chart dependency on another chart and confirm it installs alongside my own.