本文目录导读:

在 Helm 中,钩子(Hooks)是用于在 Release 生命周期的特定时刻执行操作的机制,它们定义在 Chart 模板中,通过特殊的注释和资源文件来实现。
Helm 钩子的基本用法
定义钩子资源
在 templates/ 目录下创建普通资源文件,添加 helm.sh/hook 注释:
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-pre-install
annotations:
"helm.sh/hook": pre-install
"helm.sh/hook-weight": "0"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
spec:
containers:
- name: setup
image: alpine
command: ["echo", "This runs before install"]
restartPolicy: Never
可用的钩子类型
| 钩子类型 | 触发时机 | 应用场景 |
|---|---|---|
pre-install |
模板渲染后,资源创建前 | 初始化数据库、创建密钥、运行检查脚本 |
post-install |
所有资源创建后 | 数据迁移、发送通知、注册服务 |
pre-delete |
删除请求后,任何资源删除前 | 清理外部资源、备份数据 |
post-delete |
所有资源删除后 | 清理验证、发送通知 |
pre-upgrade |
升级时,模板渲染后,资源更新前 | 数据备份、版本检查 |
post-upgrade |
升级后,所有资源更新后 | 数据迁移、缓存重建 |
pre-rollback |
回滚时,模板渲染后,资源回滚前 | 备份当前状态 |
post-rollback |
回滚后,所有资源回滚后 | 恢复验证、数据同步 |
test |
helm test 命令执行时 |
集成测试、健康检查 |
钩子权重控制
通过 helm.sh/hook-weight 控制执行顺序:
# 低权重先执行 annotations: "helm.sh/hook": pre-install "helm.sh/hook-weight": "-5" # 高权重后执行 annotations: "helm.sh/hook": pre-install "helm.sh/hook-weight": "10"
删除策略
annotations: "helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"
删除策略选项:
hook-succeeded:成功后删除(默认)hook-failed:失败后保留日志排查before-hook-creation:新钩子创建前删除旧钩子
实际应用示例
数据库迁移 Job
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-migration
labels:
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
spec:
containers:
- name: migration
image: {{ .Values.migration.image }}
env:
- name: DB_HOST
value: {{ .Values.database.host }}
- name: DB_USER
value: {{ .Values.database.user }}
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Release.Name }}-db-secret
key: password
command: ["./migrate.sh"]
restartPolicy: Never
{{- if .Values.migration.serviceAccount }}
serviceAccountName: {{ .Values.migration.serviceAccount }}
{{- end }}
复杂的钩子脚本示例
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-init-script
annotations:
"helm.sh/hook": pre-install
"helm.sh/hook-weight": "-10"
data:
init.sh: |
#!/bin/sh
echo "Checking prerequisites..."
kubectl get namespace {{ .Values.namespace }} || kubectl create namespace {{ .Values.namespace }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-init
annotations:
"helm.sh/hook": pre-install
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
containers:
- name: init
image: bitnami/kubectl:latest
command: ["/scripts/init.sh"]
volumeMounts:
- name: scripts
mountPath: /scripts
volumes:
- name: scripts
configMap:
name: {{ .Release.Name }}-init-script
restartPolicy: Never
serviceAccountName: {{ .Release.Name }}-init-sa
高级技巧
条件执行钩子
{{- if .Values.migration.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-migration
annotations:
"helm.sh/hook": post-upgrade
spec:
template:
spec:
containers:
- name: migration
image: {{ .Values.migration.image }}
{{- with .Values.migration.command }}
command: {{ . }}
{{- end }}
restartPolicy: Never
{{- end }}
钩子与 ConfigMap/Secret 配合
# templates/hooks/_helpers.tpl
{{- define "hooks.wait-for-service" -}}
{{- printf "until curl -f http://%s/health; do sleep 5; done" .Values.service.name }}
{{- end }}
# templates/hooks/post-install.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-wait
annotations:
"helm.sh/hook": post-install
"helm.sh/hook-weight": "0"
spec:
template:
spec:
containers:
- name: health-check
image: curlimages/curl
command: ["/bin/sh", "-c"]
args:
- |
{{ include "hooks.wait-for-service" . }}
restartPolicy: Never
钩子超时控制
在 values.yaml 或安装时设置:
helm install myapp . --timeout 600s # 或 helm upgrade myapp . --timeout 10m --atomic
最佳实践
- 幂等性设计:确保钩子脚本可以安全重复执行
- 错误处理:使用
set -e和适当的错误处理 - 资源清理:合理设置
hook-delete-policy避免资源泄漏 - 权限最小化:为钩子使用专用的 ServiceAccount
- 日志记录:确保输出有意义的日志
- 测试验证:通过
helm test验证钩子功能
常见问题
钩子不执行?
- 检查注释语法(
helm.sh/hook:与"helm.sh/hook":) - 确认钩子资源类型支持(通常用 Job)
- 查看
helm install --debug输出
钩子执行失败?
# 查看当前 Release 状态 helm status myapp --show-resources # 查看失败的 Job Pod 日志 kubectl logs -l job-name=myapp-hook-job-name
钩子资源没清理?
# 手动清理 kubectl delete job <job-name>
使用 Helm 钩子可以优雅地处理复杂的部署流程,但要确保脚本健壮且可重入。