挂上子 chart,用钩子造出顺序
目标
把两个独立 chart 组装为 parent 与 subchart,亲手实现 dependency 管理的四个核心:value 传递、条件启用、global value 与 hook。
为什么重要
构建 platform chart 时,必然会遇到“这个 component 应放在同一个 chart 中,还是单独拆出”的问题。dependency 是二者之间的答案。child 仍是可独立安装的完整 chart,parent 通过声明引用它并覆盖 value。规则只有一条:parent values 中与 subchart 同名的 key 之下所写内容,会成为 child 的 .Values 顶层。只有必须同时传给 parent 和 child 的值才放在 global 下。本环境没有互联网,因此 repository 必须使用 file:// 本地路径。这并非特殊限制,而是实际工作中在同一 repository 放置多个 chart 并相互引用的常见结构。最后,hook 是在部署中建立顺序的唯一手段;但hook resource 不归 release 所有,若不写删除策略,每次部署都会堆积。
步骤
- 在
/root/helm/deps/cache创建名为cache的 chart,在/root/helm/deps/platform创建 parent chart。两者都必须包含Chart.yaml、values.yaml、templates/。将/root/helm/deps/cache/values.yaml的replicaCount设为1,并预先创建产物目录/root/helm/deps/out。 - 在
/root/helm/deps/platform/Chart.yaml的dependencies第一项写入name: cache、repository: "file://../cache"、与 cache chartversion相同的version(例如0.1.0),以及condition: cache.enabled。由于没有互联网,远程 repository URL 无法使用。 - 执行
helm dependency update /root/helm/deps/platform。必须生成/root/helm/deps/platform/Chart.lock,其中第一项 dependency 名称为cache,digest以sha256:开头,且/root/helm/deps/platform/charts/中存在 cache package。 - 在
/root/helm/deps/platform/values.yaml中写入cache.enabled: true与cache.replicaCount: 3,再用helm template platform /root/helm/deps/platform > /root/helm/deps/out/rendered.yamlrender。名称含cache的 Deployment,其spec.replicas必须为 3。此时/root/helm/deps/cache/values.yaml中的replicaCount必须仍为 1,本步骤用于确认 parent override。 - 保存
helm template platform /root/helm/deps/platform --set cache.enabled=false > /root/helm/deps/out/disabled.yaml。该文件中不能出现任何cache字符串,parent chart object 必须仍保留至少 1 个。parent chart 自身的 resource 名称或内容不要使用cache。 - 在
/root/helm/deps/platform/values.yaml中设置global.environment: stage,并在 parent 与 subchart 两侧 template 的metadata.labels中加入labhub.io/environment: {{ .Values.global.environment }}。重新 render 的/root/helm/deps/out/rendered.yaml中必须至少出现两行labhub.io/environment: stage,名称含cache的 object 也必须带该 label。 - 在
/root/helm/deps/platform/templates/中添加一个 hook Job。名称形如{{ .Release.Name }}-db-migrate(不要含cache);annotation 为helm.sh/hook: pre-install,pre-upgrade、helm.sh/hook-weight: "-5"、helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded。将包含 hook 的 render 保存到/root/helm/deps/out/hooks.yaml(helm template默认也输出 hook)。 - 创建
/root/helm/deps/out/deps-report.json,含四个 key。object_count是/root/helm/deps/out/rendered.yaml中以kind:开头的行数;subcharts为["cache"];lock_digest原样取自/root/helm/deps/platform/Chart.lock的digest;hooks是含至少一个 hook resource 名称的数组。此外,render 后至少一个 Deployment 名称必须包含 release nameplatform。
参考
- 每次实验会启动新 Pod,其他实验创建的 chart 不会保留。两个 chart 都要在
/root/helm/deps下从头创建,这体现了 chart 是可复现 package。 file://路径以parent chart 目录为基准解析。绝对路径也能使用,但移动 repository 后会失效。helm dependency update会填充charts/并重写Chart.lock。helm dependency build只按 lockfile 复现,因此 CI 应使用 build。- subchart value 写在 parent values 中与 subchart 同名的 key下。
cache:下的内容就是 child.Values顶层。 - 常见错误 1:关闭 child 后,parent template 仍创建名称含 child 的 resource,导致第 5 步失败。condition 只关闭 child chart。
- 常见错误 2:hook 遗漏
hook-delete-policy。hook resource 不归 release 所有,不会自动清理,下次部署会发生同名冲突。
准备 subchart 与 parent chart
在 /root/helm/deps/cache 创建名为 cache 的 chart,在 /root/helm/deps/platform 创建 parent chart。两者都必须包含 Chart.yaml、values.yaml、templates/。将 /root/helm/deps/cache/values.yaml 的 replicaCount 设为 1,并预先创建产物目录 /root/helm/deps/out。
需要两个独立 chart。child chart 本身也必须具备完整结构(metadata、默认值、template),之后才能 package。
在 parent Chart.yaml 中声明 dependency
在 /root/helm/deps/platform/Chart.yaml 的 dependencies 第一项写入 name: cache、repository: "file://../cache"、与 cache chart version 相同的 version(例如 0.1.0),以及 condition: cache.enabled。由于没有互联网,远程 repository URL 无法使用。
此环境没有互联网,请使用相对于 parent chart 的路径,而非远程 repository URL;同时写入可控制启停的字段。
锁定 dependency 并填充 charts/
执行 helm dependency update /root/helm/deps/platform。必须生成 /root/helm/deps/platform/Chart.lock,其中第一项 dependency 名称为 cache,digest 以 sha256: 开头,且 /root/helm/deps/platform/charts/ 中存在 cache package。
锁定 dependency 后会生成 lockfile,并把 package 放入 charts/。声明 version 与 child chart version 不同时会在此失败。
从 parent override subchart value
在 /root/helm/deps/platform/values.yaml 中写入 cache.enabled: true 与 cache.replicaCount: 3,再用 helm template platform /root/helm/deps/platform > /root/helm/deps/out/rendered.yaml render。名称含 cache 的 Deployment,其 spec.replicas 必须为 3。此时 /root/helm/deps/cache/values.yaml 中的 replicaCount 必须仍为 1,本步骤用于确认 parent override。
不要修改 child chart 的默认 values 文件。在 parent values 中与 subchart 同名的 key 下写入 value,该内容就成为 child 的顶层 value。
通过 condition 关闭 subchart
保存 helm template platform /root/helm/deps/platform --set cache.enabled=false > /root/helm/deps/out/disabled.yaml。该文件中不能出现任何 cache 字符串,parent chart object 必须仍保留至少 1 个。parent chart 自身的 resource 名称或内容不要使用 cache。
condition 只关闭 child chart。若关闭后结果中仍出现 child 名称,说明 parent template 自己创建了该 resource。
把 global value 传递给 subchart
在 /root/helm/deps/platform/values.yaml 中设置 global.environment: stage,并在 parent 与 subchart 两侧 template 的 metadata.labels 中加入 labhub.io/environment: {{ .Values.global.environment }}。重新 render 的 /root/helm/deps/out/rendered.yaml 中必须至少出现两行 labhub.io/environment: stage,名称含 cache 的 object 也必须带该 label。
需要同时传到 parent 和 child 的值有专门位置。请在两侧 template 添加同一 label,并查看 render 结果确认确实传递。
添加安装 hook
在 /root/helm/deps/platform/templates/ 中添加一个 hook Job。名称形如 {{ .Release.Name }}-db-migrate(不要含 cache);annotation 为 helm.sh/hook: pre-install,pre-upgrade、helm.sh/hook-weight: "-5"、helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded。将包含 hook 的 render 保存到 /root/helm/deps/out/hooks.yaml(helm template 默认也输出 hook)。
hook 通过三个 annotation 定义,分别说明何时执行、多个 hook 的顺序,以及完成后由谁清理。
创建 umbrella render 报告
创建 /root/helm/deps/out/deps-report.json,含四个 key。object_count 是 /root/helm/deps/out/rendered.yaml 中以 kind: 开头的行数;subcharts 为 ["cache"];lock_digest 原样取自 /root/helm/deps/platform/Chart.lock 的 digest;hooks 是含至少一个 hook resource 名称的数组。此外,render 后至少一个 Deployment 名称必须包含 release name platform。
从 render 结果与 lockfile 直接提取数字并整理为 JSON。object 数与 digest 不要手写,应从文件读取。