打包图表、发布到私有仓库并重新拉取
目标
亲手走完这一整圈:把 Chart 目录打包成 tgz,生成索引并上传到私有 HTTP 仓库,从该仓库挑选版本下载,再把它锁定为另一个 Chart 的依赖。
为什么重要
Chart 离开自己的目录的那一刻,留下的只有两样东西——tgz 和 index.yaml。Chart 仓库不过是提供这两者下载的静态 HTTP 服务器,所以搭建内部仓库的事比想象中小。不过正因为小,也有相应的事故——索引不会自动更新,所以上传新版本时漏掉 --merge,旧版本就会从列表中整个消失。接收的一方常把 version 和 appVersion 混为一谈,“应用没变,为什么版本升了”的问题反复出现。最后,依赖用 build 还是 update,会让 CI 要么做出可重现的构建,要么每次拉取到不同的版本。把这三件事各亲手引发一次,以后就看得见了。
步骤
- 在
/root/hc-package中用helm create catalog创建 Chart,把/root/hc-package/catalog/Chart.yaml的version改为1.0.0,appVersion改为"2.4.0",description改为상품 목록 서비스(韩文,意为“商品列表服务”)。这两个版本指向不同的东西,这一事实是本实验始终的判定标准。 - 在
/root/hc-package/repo目录中把catalog打包两次。第一次是 Chart 版本1.0.0、appVersion2.4.0,第二次是 Chart 版本1.1.0、appVersion2.5.0。不要再去改Chart.yaml,而是用helm package的选项覆盖。请确认结果文件名是由什么决定的。 - 用
helm repo index生成/root/hc-package/repo/index.yaml。索引里catalog条目必须包含两个版本,每个版本都要有digest和urls。打开索引,确认appVersion在各版本中写的是不同的值。 - 用
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 search repo hclocal/catalog,让所有版本都显示出来,把结果以 JSON 保存到/root/hc-package/out/search.json。也请先看看不带任何选项搜索会出现几条。 - 从仓库中挑选 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。要点是不必下载解包,也能看到内容。 - 在
/root/hc-package/stage中打包 Chart 版本1.2.0、appVersion2.6.0,然后合并已有的索引,生成/root/hc-package/stage/index.yaml。合并后的索引里必须有三个版本。接着把 stage 中的 tgz 和 index.yaml 挪到/root/hc-package/repo,运行helm repo update hclocal,确认能搜到三个版本。 - 创建
/root/hc-package/storefrontChart,声明从仓库(http://127.0.0.1:8971)拉取catalog1.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。
参考
helm package <차트> --version <v> --app-version <a> -d <디렉터리>(占位符依次为 Chart、版本、应用版本、目录)helm repo index <디렉터리> --merge <옛 index.yaml>(占位符依次为目录、旧 index.yaml)helm search repo <저장소>/<차트> --versions -o json(占位符依次为仓库、Chart)- Helm 3 不接受把
file://作为仓库协议——在这个 Pod 中用python3 -m http.server启动 - 常见错误:上传新版本时没有合并索引,旧版本消失
- 常见错误:改了 Chart.yaml 中的依赖版本后运行
helm dependency build,遇到 lock 不一致的错误 - 官方文档:https://helm.sh/docs/topics/chart_repository/ · https://helm.sh/docs/helm/helm_repo_index/
打包之前先写上 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 把错误也一并接收。