TT Lab
Get started
Learn Learning paths Courses

Authoring and Shipping Helm Charts

Package a Chart, Publish It to a Private Repository, and Pull It Back

Continue in TT Lab

Goal

You run by hand one full cycle: package a chart directory as a tgz, build an index and upload it to a private HTTP repository, pick and pull a version from that repository, and lock it as a dependency of another chart.

Why it matters

The moment a chart leaves your directory, all that remains is two things: the tgz and index.yaml. A chart repository is nothing more than a static HTTP server that serves those two, so setting up an in-house repository is smaller than you might think. But because it is small, there are accidents — the index is not updated automatically, so if you leave out --merge when uploading a new version, the old versions vanish from the list altogether. On the receiving side, people confuse version and appVersion, and the question "the application is the same, so why did the version go up?" keeps coming back. Finally, depending on whether you use build or update for dependencies, CI either does a reproducible build or pulls in a different version every time. If you trigger each of these three yourself once, you will see them from then on.

Steps

  1. In /root/hc-package, create a chart with helm create catalog, and change /root/hc-package/catalog/Chart.yaml so that version is 1.0.0, appVersion is "2.4.0", and description is 상품 목록 서비스 (a Korean description meaning "product catalog service"). The fact that these two versions point to different things is the criterion for judging throughout this lab.
  2. Package catalog twice into the /root/hc-package/repo directory. The first is chart version 1.0.0 with appVersion 2.4.0, and the second is chart version 1.1.0 with appVersion 2.5.0. Do not edit Chart.yaml again; override them with the options of helm package. Check what the resulting file names are determined by.
  3. Create /root/hc-package/repo/index.yaml with helm repo index. The index must contain the catalog entry for both versions, and each version must have a digest and urls. Open the index and check that appVersion is written differently for each version.
  4. Serve /root/hc-package/repo with python3 -m http.server 8971 --bind 127.0.0.1, then register it with helm repo add hclocal http://127.0.0.1:8971 and run helm repo update hclocal. Here you confirm that a chart repository is nothing more than a static HTTP server.
  5. Run helm search repo hclocal/catalog so that all versions appear and save the result as JSON to /root/hc-package/out/search.json. First also look at how many come out when you search with no options.
  6. Pick the 1.0.0 version from the repository and pull it, unpacked, under /root/hc-package/pulled (/root/hc-package/pulled/catalog/Chart.yaml must be created). Then save the Chart.yaml of the 1.1.0 version to /root/hc-package/out/show-1.1.0.txt and its defaults to /root/hc-package/out/show-values.yaml. The point is that you can see the content without pulling and unpacking it.
  7. Package chart version 1.2.0 with appVersion 2.6.0 into /root/hc-package/stage, then create /root/hc-package/stage/index.yaml merging in the existing index. The merged index must have all three versions. Then move the tgz and index.yaml from stage to /root/hc-package/repo, run helm repo update hclocal, and check that all three versions are found in search.
  8. Create a /root/hc-package/storefront chart, declare that it fetches catalog 1.1.0 from the repository (http://127.0.0.1:8971), and resolve the dependency. Then raise the declaration to 1.2.0, run helm dependency build first and save its output to /root/hc-package/out/dep-build-error.txt, and then resolve again with the appropriate command. When you are done, Chart.lock must say 1.2.0 and /root/hc-package/storefront/charts/catalog-1.2.0.tgz must exist.

Notes

Write the identity into the chart to be packaged first

In /root/hc-package, create a chart with helm create catalog, and change /root/hc-package/catalog/Chart.yaml so that version is 1.0.0, appVersion is "2.4.0", and description is 상품 목록 서비스 (a Korean description meaning "product catalog service"). The fact that these two versions point to different things is the criterion for judging throughout this lab.

version is the version number of the chart itself, and appVersion is the version number of the software the chart carries. The two move separately — if you only edit the templates, only version goes up, and if you only raise the application, only appVersion goes up. It is the convention to wrap appVersion in quotes so that a value like 1.10 is not interpreted as a number.

Package two versions to make tgz files

Package catalog twice into the /root/hc-package/repo directory. The first is chart version 1.0.0 with appVersion 2.4.0, and the second is chart version 1.1.0 with appVersion 2.5.0. Do not edit Chart.yaml again; override them with the options of helm package. Check what the resulting file names are determined by.

It is helm package <차트> --version <v> --app-version <a> -d <디렉터리> (chart, version, app version, and directory in the placeholders). The tgz name is fixed as <이름>-<차트버전>.tgz (name and chart version), and appVersion does not appear in the name — so there can be several chart versions carrying the same appVersion. Look inside the tgz you packaged with tar -tzf.

Build the repository index

Create /root/hc-package/repo/index.yaml with helm repo index. The index must contain the catalog entry for both versions, and each version must have a digest and urls. Open the index and check that appVersion is written differently for each version.

helm repo index <디렉터리> (with the directory in the placeholder) reads all the tgz files in that directory and rewrites index.yaml from scratch. The index is only the repository's list, and the actual chart is inside the tgz. The digest is the sha256 of the tgz, so if the file changes, the index must be rebuilt.

Serve the repository and register it with helm

Serve /root/hc-package/repo with python3 -m http.server 8971 --bind 127.0.0.1, then register it with helm repo add hclocal http://127.0.0.1:8971 and run helm repo update hclocal. Here you confirm that a chart repository is nothing more than a static HTTP server.

Start the server in the background (&). helm 3 does not accept file:// as a repository protocol — if you try it yourself, you get could not find protocol handler for: file. When registration is done, the address is written to $HOME/.config/helm/repositories.yaml and a copy of the index comes down under $HOME/.cache/helm/repository/.

Search so that all versions show

Run helm search repo hclocal/catalog so that all versions appear and save the result as JSON to /root/hc-package/out/search.json. First also look at how many come out when you search with no options.

The default search shows only the single highest version per repository. To see all versions you need one more option. Change the output format with -o json. The keys of the JSON entries are name, version, app_version, and description.

Pick and pull an old version and unpack it to look

Pick the 1.0.0 version from the repository and pull it, unpacked, under /root/hc-package/pulled (/root/hc-package/pulled/catalog/Chart.yaml must be created). Then save the Chart.yaml of the 1.1.0 version to /root/hc-package/out/show-1.1.0.txt and its defaults to /root/hc-package/out/show-values.yaml. The point is that you can see the content without pulling and unpacking it.

helm pull <저장소>/<차트> --version <v> --untar -d <디렉터리> (repository, chart, version, and directory in the placeholders) pulls the tgz and unpacks it on the spot. helm show chart and helm show values read directly from the repository without pulling and print to standard output — helm show readme works the same way.

Upload a new version without deleting the old ones

Package chart version 1.2.0 with appVersion 2.6.0 into /root/hc-package/stage, then create /root/hc-package/stage/index.yaml merging in the existing index. The merged index must have all three versions. Then move the tgz and index.yaml from stage to /root/hc-package/repo, run helm repo update hclocal, and check that all three versions are found in search.

By default, helm repo index rewrites the index looking at only the tgz files in that directory. stage has only 1.2.0, so if you upload it as is, the first two versions vanish from the list. There is a separate option that merges in the old index (helm repo index --help). In practice, it is common for a deployment pipeline to wipe out old versions wholesale by forgetting this.

Lock a dependency from the repository, and make the lock go out of sync

Create a /root/hc-package/storefront chart, declare that it fetches catalog 1.1.0 from the repository (http://127.0.0.1:8971), and resolve the dependency. Then raise the declaration to 1.2.0, run helm dependency build first and save its output to /root/hc-package/out/dep-build-error.txt, and then resolve again with the appropriate command. When you are done, Chart.lock must say 1.2.0 and /root/hc-package/storefront/charts/catalog-1.2.0.tgz must exist.

build trusts Chart.lock as it is and fetches that version — that is why it is the command used in CI. update re-reads Chart.yaml, resolves the range, and rewrites the lock. If you run build after editing the declaration, you get an error that the two are out of sync. To keep the output in a file, capture the error too with 2>&1.