生命周期 Hook 与 Chart 测试
在安装或升级前后运行一次性工作,并编写一个验证 release 确实可用的测试。
chart 所做的大部分事情,都是声明会持续运行的资源。有时你需要某个东西在特定时刻运行一次,比如升级之前的数据库迁移、卸载之后的清理作业,或者在 release 启动后检查它确实可用。Helm 通过 hook 和 chart 测试来覆盖这两种情况。
什么是 hook
hook 是一个普通的 Kubernetes 资源,最常见的是 Job,通过注解告诉 Helm 它应当在一次 install、upgrade、rollback 或 uninstall 的哪个时间点运行:
# templates/hooks/pre-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Values.appName }}-pre-install
annotations:
"helm.sh/hook": pre-install
"helm.sh/hook-weight": "0"
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: myorg/webapp-migrate:1.0
command: ["./run-migrations.sh"]
helm.sh/hook 注解使它成为一个 hook,而不是 Helm 作为 release 一部分跟踪的普通资源。常见的 hook 点有 pre-install、post-install、pre-upgrade、post-upgrade、pre-rollback、post-rollback、pre-delete 和 post-delete;完整的列表(包括几个与测试相关的)见 Helm hooks 文档。
Helm 如何为 hook 排序
对于 pre-install hook:
- Helm 渲染 hook 资源并在集群中创建它,先于 chart 中的其他任何东西。
- Helm 等待它达到就绪或完成状态(运行到完成的
Job算数)。 - 只有那时,Helm 才渲染并应用 chart 的其余资源。
post-install 则颠倒第 1 步和第 3 步:chart 的常规资源先进入,然后 hook 运行。失败的 pre-upgrade hook 会中止升级,这正是把迁移放在这里运行、而不是指望它事后成功的意义所在。
Hook 权重与删除策略
helm.sh/hook-weight 在同一时间点对多个 hook 排序,数字越小越先运行,以普通字符串形式书写("0"、"5"),没有权重的 hook 默认为 0。helm.sh/hook-delete-policy 控制清理,因为已完成的 Job 否则会无限期地留在集群中:
before-hook-creation(默认):在创建新的 hook 资源之前删除先前的那个,这样重试不会与同名的遗留 Job 冲突。hook-succeeded:成功完成后删除该资源。hook-failed:失败时删除它,当你宁愿清理也不愿保留一个失败的 Job 以供检查时很有用;如果你想在失败的 Job 被移除之前用kubectl logs查看,则省略它。
例如,pre-install,hook-succeeded 的组合意味着 hook 运行一次,成功,然后自行清理,除了你的 Job 自己的输出之外不留痕迹;如果你也不想让失败的尝试留在那里,还可以加上 hook-failed。
试一试
kubectl get jobs -w
在另一个终端中:
helm install web ./webapp
观察第一个终端,你应该会看到 hook Job 出现、运行、完成,并(取决于它的删除策略)消失,这一切都发生在 chart 的 Deployment 出现之前。这是真正看到排序过程、而不是照单全收的最简单方式。
Chart 测试:在 release 运行之后验证它
chart 测试是在 release 存在之后按需运行的 Job,用来检查它确实可用:
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ .Values.appName }}-test-connection"
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox:1.36
command: ["wget", "-qO-", "{{ .Values.appName }}"]
restartPolicy: Never
helm install web ./webapp
helm test web
helm test 会运行 release 中所有带有 helm.sh/hook: test 注解的资源,并根据每个 Pod 的退出状态报告通过或失败;得到响应的 wget 以 0 退出,无法连接的则不会。与 install/upgrade hook 不同,测试资源默认不会被自动删除,运行 helm test --logs 可以内联查看它们的输出,或者在两次运行之间自行清理它们。
何时选用哪一个
- 当某件事需要在 release 生命周期的特定时间点恰好发生一次,并且部署的其余部分应当等待它或对它做出反应时,使用 hook:升级之前的 schema 迁移、安装之后通知外部系统、卸载之前清理外部资源。
- 对于任何你想针对一个已在运行的 release 按需重新运行的内容,使用 chart 测试,最常见的是在 CI 流水线中,于
helm install或helm upgrade之后作为冒烟测试,而不是作为部署序列本身的一部分。
在注解之下,两者都是普通的 Kubernetes 资源,所以你已经知道的有关调试 Job 或 Pod 的一切,kubectl describe、kubectl logs,都可以直接适用。
热门指南
-
Helm Chart 剖析:Chart、Values、模板与 Release 每个 chart 共有的文件夹结构,以及让 Helm 不止于 YAML 打包器的三个概念。 -
从现有清单创建你的第一个 Helm Chart 将 Deployment、Service 和 ConfigMap 变成模板化的 chart,然后安装并升级它。 -
一个 Chart,多个环境:dev、staging 和 prod 的 Values 文件 只覆盖环境之间不同的部分,并理解 values 的合并顺序。 -
管理 Release:安装、升级、回滚与卸载 涵盖 release 整个生命周期的命令,以及修订历史如何使回滚成为可能。