用库图表把标准标签集中到一处
目标
做一个 type: library 的 Chart,让两个应用 Chart 共用同一套 Deployment 模板和标签规则,并通过渲染确认当父 Chart 重新定义同名模板时,谁会获胜。
为什么重要
Chart 一多,最先散掉的就是标准标签。同一家公司的 Chart,有的加 app.kubernetes.io/instance,有的加 release。监控仪表板和网络策略按标签选择对象,所以这种不一致,以后会变成“为什么只有这个 Pod 抓不到指标”的问题找上门来。library chart 就是把这条规则钉在一处的装置。它自己既不能安装也不能渲染,只包含 define,所以它“只为别人使用而存在”这一点,在类型名称里就体现出来了。在这里还要学另外两件事——用 tpl 把 values 里的字符串重新当作模板运行,以及模板名称在整个 Chart 中是一个名称池(template name space),所以名称一旦重叠就会悄悄被覆盖。
步骤
- 在
/root/hc-library/platform-lib中创建type: library的 Chart(名称platform-lib,版本0.1.0)。在/root/hc-library/platform-lib/templates/_helpers.tpl中用define定义platform-lib.fullname和platform-lib.labels两个。labels 输出app.kubernetes.io/name、app.kubernetes.io/instance、app.kubernetes.io/managed-by、platform.labhub.io/tier四行。templates 下只放以下划线开头的文件。 - 依次运行
helm install liblab /root/hc-library/platform-lib --dry-run和helm template liblab /root/hc-library/platform-lib,把两个输出(包括错误)都放进/root/hc-library/out/library-error.txt。Helm 用什么话拒绝,就是这一步的答案。 - 在
/root/hc-library/platform-lib/templates/_deployment.tpl中定义platform-lib.deployment。这个模板输出一个 Deployment,名称用platform-lib.fullname,metadata.labels用nindent 4插入platform-lib.labels来构成。spec.replicas用.Values.replicas(默认 1),容器名称用.Chart.Name,镜像用带引号的.Values.image。selector 和 Pod 标签只写 name、instance 两行。 - 创建
/root/hc-library/billing应用 Chart(版本0.1.0,appVersion"1.4.2"),把platform-lib0.1.0以file://../platform-lib仓库声明为依赖,并锁定下来。values.yaml包含replicas: 1、image: "registry.local/billing:1.4.2"、tier: core,以及note: "{{ .Release.Name }} in {{ .Release.Namespace }}"四个值,templates/deployment.yaml只放一行 includeplatform-lib.deployment。把helm template shop /root/hc-library/billing的结果保存到/root/hc-library/out/billing.yaml。 - 以同样方式创建
/root/hc-library/reportingChart(版本0.1.0,appVersion"0.9.0"),设为replicas: 3、image: "registry.local/reporting:0.9.0"、tier: batch、note: "{{ .Chart.Name }} {{ .Chart.Version }}",并锁定依赖。把helm template insight /root/hc-library/reporting的结果保存到/root/hc-library/out/reporting.yaml。请确认两个渲染结果的标签键列表相同,只有值不同。 - 在 library 中添加
platform-lib.configmap(/root/hc-library/platform-lib/templates/_configmap.tpl)。名称是<fullname>-note,data.note把.Values.note用tpl再渲染一次并加上引号。给两个 Chart 添加templates/configmap.yaml(一行 include)。note的值已经在第 4、5 步放进了 values.yaml——请保留带花括号的原样。因为改了 library,两个 Chart 必须重新获取依赖。 重新保存两个渲染文件。 - 在
/root/hc-library/billing/templates/_override.tpl中重新定义同名的platform-lib.deployment。内容与 library 的相同,只是在metadata.annotations中多加一行platform.labhub.io/overridden-by: billing。重新渲染两个 Chart 并保存,确认只有 billing 带有这个注解。 - 在
/root/hc-library/out/report.json中整理本实验的结果。键有八个:library(library Chart 名称)、type(Chart 类型)、installable(布尔值)、consumers(消费方 Chart 名称数组)、billing_replicas、reporting_replicas(各渲染结果中实际的 replicas 数字)、shared_label_keys(library 辅助模板生成的标签键个数)、override_winner(重新定义同名模板而获胜的 Chart 名称)。
参考
type: libraryChart 的 templates 中只放以下划线开头的文件- 依赖
repository: "file://../<디렉터리>"(占位符为目录)在这个 Pod 中可以使用(与仓库注册时的file://是不同的位置) helm dependency update会把那一刻的 library 打成 tgz 带走——改了 library 就要重新获取- 常见错误:对 library 执行
helm install,就以为 Chart 坏了 - 常见错误:define 名称不加 Chart 名称,悄悄与其他 Chart 的定义冲突
- 官方文档:https://helm.sh/docs/topics/library_charts/ · https://helm.sh/docs/chart_template_guide/named_templates/
做一个什么也不渲染的 Chart
在 /root/hc-library/platform-lib 中创建 type: library 的 Chart(名称 platform-lib,版本 0.1.0)。在 /root/hc-library/platform-lib/templates/_helpers.tpl 中用 define 定义 platform-lib.fullname 和 platform-lib.labels 两个。labels 输出 app.kubernetes.io/name、app.kubernetes.io/instance、app.kubernetes.io/managed-by、platform.labhub.io/tier 四行。templates 下只放以下划线开头的文件。
library chart 没有会被渲染的模板。Helm 把以 _ 开头的文件当作“不输出的片段”,所以所有内容都放在 _*.tpl 里的 define 块中。tier 可能没有值,所以加上 default 并用 quote 包起来。
试着安装 library chart
依次运行 helm install liblab /root/hc-library/platform-lib --dry-run 和 helm template liblab /root/hc-library/platform-lib,把两个输出(包括错误)都放进 /root/hc-library/out/library-error.txt。Helm 用什么话拒绝,就是这一步的答案。
两条命令都会失败。错误会输出到标准错误,所以必须用 2>&1 一并接收才会写进文件。第二条命令为了不清掉第一条的输出,请用追加(>>)。想想安装被挡住的原因——这个 Chart 没有任何东西可以渲染。
把整套 Deployment 放进 library
在 /root/hc-library/platform-lib/templates/_deployment.tpl 中定义 platform-lib.deployment。这个模板输出一个 Deployment,名称用 platform-lib.fullname,metadata.labels 用 nindent 4 插入 platform-lib.labels 来构成。spec.replicas 用 .Values.replicas(默认 1),容器名称用 .Chart.Name,镜像用带引号的 .Values.image。selector 和 Pod 标签只写 name、instance 两行。
include 会把另一个 define 的结果当作字符串取来,所以可以用管道加上缩进。nindent 4 先放入换行再缩进四个空格——适合在 labels: 正下面一行使用。评分器会把这个定义放进临时 Chart 里直接渲染。
应用 Chart 把 library 声明为依赖
创建 /root/hc-library/billing 应用 Chart(版本 0.1.0,appVersion "1.4.2"),把 platform-lib 0.1.0 以 file://../platform-lib 仓库声明为依赖,并锁定下来。values.yaml 包含 replicas: 1、image: "registry.local/billing:1.4.2"、tier: core,以及 note: "{{ .Release.Name }} in {{ .Release.Namespace }}" 四个值,templates/deployment.yaml 只放一行 include platform-lib.deployment。把 helm template shop /root/hc-library/billing 的结果保存到 /root/hc-library/out/billing.yaml。
library 不能安装,但可以作为依赖挂上。file:// 不能用于仓库注册,但可以用作依赖的 repository。锁定之后会生成 Chart.lock 和 charts/platform-lib-0.1.0.tgz。release 名称给成 shop,对象名称就是 shop-billing。
第二个 Chart 用不同的值使用同一套模板
以同样方式创建 /root/hc-library/reporting Chart(版本 0.1.0,appVersion "0.9.0"),设为 replicas: 3、image: "registry.local/reporting:0.9.0"、tier: batch、note: "{{ .Chart.Name }} {{ .Chart.Version }}",并锁定依赖。把 helm template insight /root/hc-library/reporting 的结果保存到 /root/hc-library/out/reporting.yaml。请确认两个渲染结果的标签键列表相同,只有值不同。
library 发挥价值的地方正是这里——给标签的规则只在一处,各 Chart 不同的只有 values。只想提取标签键来比较,可以对两个文件运行 yq '.metadata.labels | keys'。
把 values 里的模板字符串重新渲染
在 library 中添加 platform-lib.configmap(/root/hc-library/platform-lib/templates/_configmap.tpl)。名称是 <fullname>-note,data.note 把 .Values.note 用 tpl 再渲染一次并加上引号。给两个 Chart 添加 templates/configmap.yaml(一行 include)。note 的值已经在第 4、5 步放进了 values.yaml——请保留带花括号的原样。因为改了 library,两个 Chart 必须重新获取依赖。 重新保存两个渲染文件。
tpl <문자열> <컨텍스트>(占位符依次为字符串、上下文)会当场把字符串当作模板解释。values 里写的花括号只是普通字符,不经过这个函数就会原样输出。helm dependency update 会把那一刻的 library 打成 tgz 放进 charts/——改了 library 之后如果不重新获取,就会一直使用旧副本。
父 Chart 重新定义同名模板,谁会获胜
在 /root/hc-library/billing/templates/_override.tpl 中重新定义同名的 platform-lib.deployment。内容与 library 的相同,只是在 metadata.annotations 中多加一行 platform.labhub.io/overridden-by: billing。重新渲染两个 Chart 并保存,确认只有 billing 带有这个注解。
Helm 的模板名称在整个 Chart 中使用同一个名称池。同名有两个时,后读取的获胜,而父 Chart 的模板比子 Chart 后读取。所以才有了在名称前面加 Chart 名称的惯例——为的是防止意外冲突。
用数字写下 library 抹掉了什么
在 /root/hc-library/out/report.json 中整理本实验的结果。键有八个:library(library Chart 名称)、type(Chart 类型)、installable(布尔值)、consumers(消费方 Chart 名称数组)、billing_replicas、reporting_replicas(各渲染结果中实际的 replicas 数字)、shared_label_keys(library 辅助模板生成的标签键个数)、override_winner(重新定义同名模板而获胜的 Chart 名称)。
数字不要编造,要从渲染结果中读——可以像 yq '. | select(.kind=="Deployment") | .spec.replicas' out/billing.yaml 这样提取。installable 必须是不带引号的布尔值。