TT Lab
开始
学习 学习路径 课程

Helm Chart 的制作与发布

打包图表、发布到私有仓库并重新拉取

在 TT Lab 中继续学习

目标

亲手走完这一整圈:把 Chart 目录打包成 tgz,生成索引并上传到私有 HTTP 仓库,从该仓库挑选版本下载,再把它锁定为另一个 Chart 的依赖。

为什么重要

Chart 离开自己的目录的那一刻,留下的只有两样东西——tgz 和 index.yaml。Chart 仓库不过是提供这两者下载的静态 HTTP 服务器,所以搭建内部仓库的事比想象中小。不过正因为小,也有相应的事故——索引不会自动更新,所以上传新版本时漏掉 --merge,旧版本就会从列表中整个消失。接收的一方常把 version 和 appVersion 混为一谈,“应用没变,为什么版本升了”的问题反复出现。最后,依赖用 build 还是 update,会让 CI 要么做出可重现的构建,要么每次拉取到不同的版本。把这三件事各亲手引发一次,以后就看得见了。

步骤

  1. 在 /root/hc-package 中用 helm create catalog 创建 Chart,把 /root/hc-package/catalog/Chart.yaml 的 version 改为 1.0.0,appVersion 改为 "2.4.0",description 改为 상품 목록 서비스(韩文,意为“商品列表服务”)。这两个版本指向不同的东西,这一事实是本实验始终的判定标准。
  2. 在 /root/hc-package/repo 目录中把 catalog 打包两次。第一次是 Chart 版本 1.0.0、appVersion 2.4.0,第二次是 Chart 版本 1.1.0、appVersion 2.5.0。不要再去改 Chart.yaml,而是用 helm package 的选项覆盖。请确认结果文件名是由什么决定的。
  3. 用 helm repo index 生成 /root/hc-package/repo/index.yaml。索引里 catalog 条目必须包含两个版本,每个版本都要有 digest 和 urls。打开索引,确认 appVersion 在各版本中写的是不同的值。
  4. 用 python3 -m http.server 8971 --bind 127.0.0.1 提供 /root/hc-package/repo 服务,然后用 helm repo add hclocal http://127.0.0.1:8971 注册,并运行 helm repo update hclocal。在这里确认 Chart 仓库不过是静态 HTTP 服务器。
  5. 运行 helm search repo hclocal/catalog,让所有版本都显示出来,把结果以 JSON 保存到 /root/hc-package/out/search.json。也请先看看不带任何选项搜索会出现几条。
  6. 从仓库中挑选 1.0.0 版本,下载并解开到 /root/hc-package/pulled 之下(必须生成 /root/hc-package/pulled/catalog/Chart.yaml)。接着把 1.1.0 版本的 Chart.yaml 保存到 /root/hc-package/out/show-1.1.0.txt,把默认值保存到 /root/hc-package/out/show-values.yaml。要点是不必下载解包,也能看到内容。
  7. 在 /root/hc-package/stage 中打包 Chart 版本 1.2.0、appVersion 2.6.0,然后合并已有的索引,生成 /root/hc-package/stage/index.yaml。合并后的索引里必须有三个版本。接着把 stage 中的 tgz 和 index.yaml 挪到 /root/hc-package/repo,运行 helm repo update hclocal,确认能搜到三个版本。
  8. 创建 /root/hc-package/storefront Chart,声明从仓库(http://127.0.0.1:8971)拉取 catalog 1.1.0,并锁定依赖。然后把声明升到 1.2.0,先运行 helm dependency build,把输出保存到 /root/hc-package/out/dep-build-error.txt,再用合适的命令重新锁定。结束时 Chart.lock 必须是 1.2.0,并且要有 /root/hc-package/storefront/charts/catalog-1.2.0.tgz。

参考

打包之前先写上 Chart 的身份

在 /root/hc-package 中用 helm create catalog 创建 Chart,把 /root/hc-package/catalog/Chart.yaml 的 version 改为 1.0.0,appVersion 改为 "2.4.0",description 改为 상품 목록 서비스(韩文,意为“商品列表服务”)。这两个版本指向不同的东西,这一事实是本实验始终的判定标准。

version 是 Chart 自己的版本号,appVersion 是该 Chart 所承载运送的软件的版本号。两者分别变动——只改模板只升 version,只升级应用只升 appVersion。appVersion 照惯例用引号括起来,免得 1.10 这样的值被解释成数字。

打包两个版本,生成 tgz

在 /root/hc-package/repo 目录中把 catalog 打包两次。第一次是 Chart 版本 1.0.0、appVersion 2.4.0,第二次是 Chart 版本 1.1.0、appVersion 2.5.0。不要再去改 Chart.yaml,而是用 helm package 的选项覆盖。请确认结果文件名是由什么决定的。

是 helm package <차트> --version <v> --app-version <a> -d <디렉터리>(占位符依次为 Chart、版本、应用版本、目录)。tgz 名称由 <이름>-<차트버전>.tgz(占位符依次为名称、Chart 版本)决定,appVersion 不会出现在名称中——所以可能有多个 Chart 版本带着相同的 appVersion。请用 tar -tzf 看看打好的 tgz 内部。

生成仓库索引

用 helm repo index 生成 /root/hc-package/repo/index.yaml。索引里 catalog 条目必须包含两个版本,每个版本都要有 digest 和 urls。打开索引,确认 appVersion 在各版本中写的是不同的值。

helm repo index <디렉터리>(占位符为目录)会读取该目录中的全部 tgz,重写 index.yaml。索引只是仓库的目录,真正的 Chart 在 tgz 里。digest 是 tgz 的 sha256,所以文件一变,索引也要重新生成。

启动仓库并注册到 helm

用 python3 -m http.server 8971 --bind 127.0.0.1 提供 /root/hc-package/repo 服务,然后用 helm repo add hclocal http://127.0.0.1:8971 注册,并运行 helm repo update hclocal。在这里确认 Chart 仓库不过是静态 HTTP 服务器。

服务器放到后台启动(&)。Helm 3 不接受把 file:// 作为仓库协议——亲自试一下,会出现 could not find protocol handler for: file。注册完成后,地址会写入 $HOME/.config/helm/repositories.yaml,索引副本会下载到 $HOME/.cache/helm/repository/ 之下。

让所有版本都显示出来地搜索

运行 helm search repo hclocal/catalog,让所有版本都显示出来,把结果以 JSON 保存到 /root/hc-package/out/search.json。也请先看看不带任何选项搜索会出现几条。

默认搜索只显示每个仓库中最高的一个版本。要看所有版本,还需要一个选项。输出格式用 -o json 改变。JSON 条目的键是 name、version、app_version、description。

挑选旧版本下载并解开来看

从仓库中挑选 1.0.0 版本,下载并解开到 /root/hc-package/pulled 之下(必须生成 /root/hc-package/pulled/catalog/Chart.yaml)。接着把 1.1.0 版本的 Chart.yaml 保存到 /root/hc-package/out/show-1.1.0.txt,把默认值保存到 /root/hc-package/out/show-values.yaml。要点是不必下载解包,也能看到内容。

helm pull <저장소>/<차트> --version <v> --untar -d <디렉터리>(占位符依次为仓库、Chart、版本、目录)会下载 tgz 并当场解开。helm show chart 和 helm show values 不下载,直接从仓库读取并输出到标准输出——helm show readme 也是同样的方式。

上传新版本时不删除旧版本

在 /root/hc-package/stage 中打包 Chart 版本 1.2.0、appVersion 2.6.0,然后合并已有的索引,生成 /root/hc-package/stage/index.yaml。合并后的索引里必须有三个版本。接着把 stage 中的 tgz 和 index.yaml 挪到 /root/hc-package/repo,运行 helm repo update hclocal,确认能搜到三个版本。

helm repo index 默认只看那个目录里的 tgz 来重写索引。stage 里只有 1.2.0 一个,所以直接上传,前面两个版本就会从目录中消失。另有合并旧索引的选项(helm repo index --help)。实际工作中,漏掉这一点,部署流水线把旧版本整个弄丢的事故很常见。

在仓库中锁定依赖,再让锁定不一致

创建 /root/hc-package/storefront Chart,声明从仓库(http://127.0.0.1:8971)拉取 catalog 1.1.0,并锁定依赖。然后把声明升到 1.2.0,先运行 helm dependency build,把输出保存到 /root/hc-package/out/dep-build-error.txt,再用合适的命令重新锁定。结束时 Chart.lock 必须是 1.2.0,并且要有 /root/hc-package/storefront/charts/catalog-1.2.0.tgz。

build 是完全信任 Chart.lock、原样拉取那个版本——所以是 CI 里使用的命令。update 会重新读取 Chart.yaml,解析范围并重写 lock。改了声明之后运行 build,就会出现两者不一致的错误。想把输出留到文件里,请用 2>&1 把错误也一并接收。