Helm hooks: executando ações durante install/upgrade
1. Introdução aos Helm Hooks
Helm hooks são mecanismos que permitem executar ações em pontos específicos do ciclo de vida de um release. Diferente dos templates regulares, que são processados e aplicados sempre durante uma operação, os hooks são executados apenas em momentos determinados, como antes ou depois de um install, upgrade, rollback ou delete.
A principal motivação para usar hooks é automatizar tarefas que precisam ocorrer em momentos específicos: migrações de banco de dados antes de um upgrade, notificações após uma instalação bem-sucedida, backups antes de uma alteração crítica, ou validações de saúde após um rollout.
O ciclo de vida de um release Helm segue esta sequência: pre-install → instalação → post-install → pre-upgrade → upgrade → post-upgrade → pre-rollback → rollback → post-rollback → pre-delete → delete → post-delete. Em cada um desses pontos, podemos injetar hooks.
A diferença fundamental entre hooks e templates regulares está no controle de execução: templates são sempre aplicados durante a operação principal, enquanto hooks são condicionais e seguem uma ordenação específica definida por pesos.
2. Tipos de Hooks e Seus Gatilhos
Helm oferece 8 tipos de hooks principais, cada um associado a um gatilho específico:
- pre-install: Executado antes da instalação dos recursos do chart.
- post-install: Executado após todos os recursos do chart serem instalados com sucesso.
- pre-upgrade: Executado antes do upgrade, útil para validações ou backup do estado atual.
- post-upgrade: Executado após o upgrade ser concluído, ideal para notificações ou limpeza.
- pre-delete: Executado antes da deleção dos recursos, permitindo cleanup ou backup final.
- post-delete: Executado após a deleção, para ações como remoção de DNS ou notificações.
- pre-rollback: Executado antes de reverter para uma versão anterior.
- post-rollback: Executado após o rollback ser concluído.
Além desses, existem dois hooks especiais:
- test: Usado com
helm testpara validar que um release está funcionando corretamente. - crds: Executado antes de qualquer outro hook para instalar Custom Resource Definitions (CRDs) primeiro.
3. Anatomia de um Recurso de Hook
Um hook é definido através de anotações no metadata do recurso Kubernetes. A anotação principal é helm.sh/hook, que especifica em qual fase o recurso deve ser executado:
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ .Release.Name }}-db-migration"
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migration
image: myapp/migration:1.0
command: ["/bin/sh", "-c", "echo 'Running migration...'"]
A anotação helm.sh/hook-weight controla a ordem de execução entre hooks do mesmo tipo. Hooks com pesos menores executam primeiro. O peso padrão é 0, e valores negativos são permitidos.
A anotação helm.sh/hook-delete-policy gerencia quando o recurso do hook deve ser removido. As políticas disponíveis são:
- before-hook-creation: Remove o recurso antes de criar um novo hook do mesmo tipo.
- hook-succeeded: Remove o recurso após execução bem-sucedida.
- hook-failed: Remove o recurso após falha na execução.
4. Exemplos Práticos: Hooks em Ação
Job de migração de banco de dados (hook pre-upgrade)
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ .Release.Name }}-db-migrate"
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "10"
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
template:
spec:
containers:
- name: migrate
image: myapp/migration:{{ .Values.image.tag }}
env:
- name: DB_URL
value: "{{ .Values.database.url }}"
- name: DB_USER
valueFrom:
secretKeyRef:
name: {{ .Values.database.secretName }}
key: username
command: ["/migration-tool", "upgrade"]
restartPolicy: Never
backoffLimit: 2
Notificação via webhook (hook post-install)
apiVersion: v1
kind: Pod
metadata:
name: "{{ .Release.Name }}-notify"
annotations:
"helm.sh/hook": post-install
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
containers:
- name: notify
image: curlimages/curl:latest
command:
- /bin/sh
- -c
- |
curl -X POST -H "Content-Type: application/json" \
-d '{"release":"{{ .Release.Name }}","status":"installed"}' \
https://hooks.example.com/helm-notify
restartPolicy: Never
Backup de estado antes de upgrade (hook pre-upgrade com ConfigMap + Job)
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Release.Name }}-backup-config"
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": before-hook-creation
data:
backup.sh: |
#!/bin/sh
kubectl get configmap {{ .Release.Name }}-config -o yaml > /tmp/backup.yaml
echo "Backup completed"
---
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ .Release.Name }}-backup"
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "2"
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
template:
spec:
containers:
- name: backup
image: bitnami/kubectl:latest
command: ["/bin/sh", "/backup/backup.sh"]
volumeMounts:
- name: script
mountPath: /backup
volumes:
- name: script
configMap:
name: "{{ .Release.Name }}-backup-config"
restartPolicy: Never
5. Boas Práticas e Armadilhas Comuns
Timeouts e bloqueios: Hooks podem causar timeouts se demorarem muito. Configure backoffLimit e activeDeadlineSeconds nos Jobs para evitar bloqueios eternos.
Recursos efêmeros: Use hook-delete-policy adequadamente para evitar acúmulo de recursos. A combinação before-hook-creation,hook-succeeded é geralmente segura.
Hooks vs. initContainers: Use hooks para ações que devem ocorrer apenas durante operações específicas (instalação, upgrade). Use initContainers para ações que devem ocorrer sempre que um pod for iniciado.
Labels para depuração: Adicione labels como app.kubernetes.io/component: hook nos recursos de hook para facilitar a identificação e limpeza manual.
6. Depuração e Logs de Hooks
Para inspecionar hooks executados em um release:
helm get hooks my-release
Para visualizar logs de jobs/pods de hook específicos:
kubectl logs -l app.kubernetes.io/component=hook --all-containers
Para simular a execução de hooks sem aplicá-los:
helm install my-release ./mychart --dry-run
O dry-run mostra todos os recursos que seriam criados, incluindo hooks, permitindo validar a sintaxe e a lógica antes da execução real.
7. Integração com CI/CD e Estratégias Avançadas
Em pipelines GitOps com ArgoCD ou Flux, hooks de longa duração podem causar problemas. Configure syncPolicy no ArgoCD para respeitar os hooks ou use skipCrds: true se necessário.
Ao combinar hooks com subcharts, lembre-se que cada subchart pode ter seus próprios hooks. A ordem de execução entre hooks de diferentes subcharts segue a mesma lógica de pesos, mas não há garantia de ordenação entre subcharts.
Hooks podem ser combinados com helm test para validação pós-upgrade:
apiVersion: v1
kind: Pod
metadata:
name: "{{ .Release.Name }}-health-check"
annotations:
"helm.sh/hook": test
spec:
containers:
- name: health
image: curlimages/curl:latest
command:
- /bin/sh
- -c
- |
curl -f http://{{ .Release.Name }}-service:8080/health
restartPolicy: Never
Este hook é executado apenas quando helm test my-release é chamado, permitindo validações automatizadas pós-instalação ou pós-upgrade.
Referências
- Helm Hooks Documentation (Official) — Documentação oficial da Helm sobre hooks, incluindo todos os tipos, pesos e políticas de deleção.
- Helm Hooks: A Complete Guide (Dev.to) — Guia prático com exemplos detalhados de implementação de hooks em cenários reais.
- Using Helm Hooks for Database Migrations (Medium) — Tutorial específico sobre como usar hooks pre-upgrade para executar migrações de banco de dados.
- Helm Hooks Best Practices (Artifact Hub) — Coleção de boas práticas e patterns para hooks, incluindo exemplos de políticas de deleção e gerenciamento de recursos.
- Debugging Helm Hooks (Kubernetes Blog) — Artigo do blog oficial do Kubernetes sobre técnicas de depuração e logs de hooks.
- Helm Hooks in GitOps Workflows (ArgoCD Blog) — Documentação do ArgoCD sobre como hooks Helm interagem com pipelines GitOps e estratégias de sincronização.