Helm 提供一个 Hook 机制,允许 Chart 开发者在发布的生命周期中的某些时候进行干预。例如,可以使用 Hook 执行以下操作:

  • 在安装期间加载 ConfigMap 或 Secret,然后再加载其他 Chart。
  • 在安装新 Chart 之前执行一个 Job 来备份数据库,然后在升级后执行第二个 Job 来恢复数据。
  • 在删除 release 之前运行作业,以便在删除前优雅地停止服务。

Hook 像常规模板一样,但是它们有特殊的注解,可以使 Helm 以不同的方式使用它们。在本节中,我们介绍 Hook 的基本使用模式。

可用的 Hook

定义了以下 Hook:

注解值 描述
pre-install 在模板渲染后执行,但在 Kubernetes 中创建任何资源之前执行。
post-install 在所有资源加载到 Kubernetes 后执行。
pre-delete 在从 Kubernetes 中删除任何资源之前执行。
post-delete 在所有 Release 的资源被删除后执行。
pre-upgrade 在升级请求中,在模板渲染后但在更新任何资源之前执行。
post-upgrade 在所有资源升级完毕后执行升级。
pre-rollback 在模板渲染后,但在任何资源回滚之前执行。
post-rollback 回滚请求在所有资源被修改后执行。
test 当调用 Helm test 子命令时执行(查看 test 文档)。

请注意,crd-install Hook 已删除,取而代之的是 Helm 3 中的 crds/ 目录。

Hooks 和 Release 声明周期

Hooks 允许 Chart 开发者有机会在 Release 生命周期的关键点执行操作。例如,考虑 helm install 的生命周期。默认情况下,生命周期看起来是这样的:

  1. 用户运行 helm install foo
  2. 调用 Helm 安装接口
  3. 经过一些验证后,渲染 foo 模板
  4. 将生成的资源加载到 Kubernetes 中
  5. 将 Release 对象和其他数据返回给客户端
  6. 客户端退出

Helm 为 install 生命周期定义了两个 Hook。pre-installpost-install。如果 foo Chart 的开发者实现了这两个 Hook,那么生命周期就变为这样:

  1. 用户运行 helm install foo
  2. 调用 Helm 安装接口
  3. crds/ 目录下的 CRD 被安装了
  4. 经过一些验证后,渲染 foo 模板
  5. 执行 pre-install Hook(将 Hook 资源加载到 Kubernetes 中)。
  6. 根据权重(默认值为 0)排序,具有相同权重的 Hook 的按名称升序排序。
  7. 然后,首先加载权重最小的 Hook (从负到正)
  8. 等待 Hook 直到 “Ready” (除了 CRD)
  9. 将生成的资源加载到 Kubernetes 中。注意,如果设置了 --wait 标志,将等待所有资源处于准备就绪状态,并且不会运行post-install Hook,直到它们准备就绪为止。
  10. 执行 post-install Hook(加载 Hook 资源)。
  11. 等待 Hook 直到 “Ready”
  12. 将 Release 对象和其他数据返回给客户端
  13. 客户端退出

等待 Hook 直到就绪是什么意思? 这取决于 Hook 中声明的资源。如果是 JobPod 类型的资源,Helm 将等待 直到它成功运行完成。而如果 Hook 失败了,发布也会失败。这是一个_阻塞操作_,所以 Helm 客户端将在运行 Job 时暂停。

对于所有其他类型的资源,只要 Kubernetes 标记为 loaded(added 或 updated),该资源就被视为 “Ready”。当一个 Hook 中声明了许多资源时,资源是按顺序执行的。如果它们有 Hook 权重(见下文),则按加权顺序执行。否则,顺序不保证。(在 Helm 2.3.0 及之后的版本中,它们按字母顺序排列。但这种行为并未被视为具有约束力,将来可能会发生变化。) 好的做法是增加一个 Hook 的权重,如果权重不重要,可以将其设置为 0

Hook 资源不与相应的 Release 一起进行管理

Hook 创建的资源不作为 Release 的一部分进行跟踪或管理。一旦 Helm 验证 Hook 已经达到就绪状态,它将使 Hook 资源保持独立。当相应的 Release 被删除时,Hook 资源垃圾收集可能会在将来被添加到 Helm 3 中,所以任何不能被删除的 Hook 资源都应该用 helm.sh/resource-policy: keep 进行注释。

实际上,这意味着如果你在 Hook 中创建了资源,就不能依靠 helm uninstall 来删除资源。要销毁这些资源,你需要在 Hook 模板文件中添加一个自定义的 helm.sh/hook-delete-policy 注解,或者设置 Job 资源的存活时间(TTL)字段

写一个 Hook

Hook 只是 Kubernetes manifest 文件,在 metadata 部分有特殊的注解。因为它们是模板文件,所以可以使用所有正常的模板功能,包括读取 .Values, .Release.Template。 例如,这个模板存储在 templates/post-install-job.yaml 中,声明了一个 Job 运行在 post-install 周期。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}"
  labels:
    app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
  annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: "{{ .Release.Name }}"
      labels:
        app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
        app.kubernetes.io/instance: {{ .Release.Name | quote }}
        helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    spec:
      restartPolicy: Never
      containers:
      - name: post-install-job
        image: "alpine:3.3"
        command: ["/bin/sleep","{{ default "10" .Values.sleepyTime }}"]

注解使此模板成为一个 Hook:

1
2
annotations:
  "helm.sh/hook": post-install

一个资源可以实现多种类型的 Hook。

1
2
annotations:
  "helm.sh/hook": post-install,post-upgrade

同样,实现一个给定的 Hook 的不同种类资源数量没有限制 例如,可以同时声明一个 Secret 和 ConfigMap 作为 pre-install hook。

子 Chart 声明 Hook 时,也会评估这些 Hook。顶级 Chart 无法禁用子 Chart 所声明的 Hook。

可以为 Hook 定义权重,这将帮助建立一个确定的执行顺序。权重使用以下注解定义:

1
2
annotations:
  "helm.sh/hook-weight": "5"

Hook 权重可以是正数或负数,但必须用字符串表示。当 Helm 开始执行特定种类的 Hook 时,它将按升序排列这些 Hook。

Hook 删除策略

可以定义策略,决定何时删除相应的 Hook 资源。Hook 删除策略使用以下注解来定义:

1
2
annotations:
  "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded

您可以选择一个或多个定义的注解值:

注解值 描述
before-hook-creation 在启动新的 Hook 之前,删除之前的资源(默认情况下)。
hook-succeeded 成功执行 Hook 后删除资源
hook-failed 如果 Hook 在执行过程中失败,则删除资源

如果没有指定 Hook 删除策略注解,before-hook-creation 行为默认适用。