How to switch from Helm monorepository to versioned charts
Background
In Altenar for many years there was a helm monorepository, where all the component charts and the library chart were located.
It looked something like this:
.
├── project_1
├── ...
├── project_x
└── library
├── Chart.yaml
└── templates
This option works very simply – you keep only current charts in the master branch, they are not versioned and all have the same chart version `0.1.0`.
All charts have a library chart as a dependency, along the local path:
# component/Chart.yaml
dependencies:
- name: library
version: 0.1.1
repository: file://../library
And templates simply contains the necessary templates from the library:
# component/templates/deployment.yaml
{{- include "templates.deployment" . -}}
The library itself has many different templates, such as deployments, services and other cronjobs. We originally took this example from here https://faun.pub/dry-helm-charts-for-micro-services-db3a1d6ecb80 (probably because there were fewer examples in the Helm documentation before)
In the CI pipeline, the repository is downloaded on the agent and packaged into an artifact, which is versioned and transferred to the CD pipe.
Then, in the CD part, several bash commands are executed, something like this:
$ cd component
$ helm dependency update .
$ helm upgrade --install component -f values.yaml .
And the application is deployed, as if you had done it manually from the repository.
This has worked successfully for many years, but there is always room for improvement.
Some time ago we were working with flux monorepo (you can read it in the previous article) and in one of the new projects the idea came up to use flux objects HelmRelease for deploying our components.
In fact, this is not just a whim, but further we plan to develop an operator to control logically related components, where one of the options is to use HelmRelease objects, but this will be discussed in another article.
And the time has come to finally start collecting versioned charts and store them in your registry, since these objects require normal versioned charts.
Why versioned charts are better
Dependencies: Versioning allows you to specify exactly which version of the library is needed to run a particular chart. And there may be more than one.
StabilityNote: Updates or changes to the library will not affect current configurations. If the chart successfully lives on the old version of the library, there is no need to do anything additional, semver successfully signals incompatible changes.
Reuse: Old versions of charts can be reused, ensuring the same state across different environments.
Rollback: If you have problems, you can easily roll back to the previous version of the chart by simply changing the version. In the current scheme, it is necessary to rollback changes in the helm rep and start the assembly of charts and deployment of components again.
Changelog: And if you have taught each other to read changes in versions, you know what has changed in the chart/or
In general, the use of versioning improves the manageability, reliability and predictability of chart deployments.
And one moment. For HelmRelease objects, we need charts already collected and available from the registry. More details here https://fluxcd.io/flux/components/source/helmcharts/#version
And if you don’t specify the version and always drag the latest, then you yourself know how it will end. If you don’t know, read this opus about antipatterns (it’s about Docker images, but the meaning is the same) https://habr.com/ru/companies/timeweb/articles/557320/
To try out an approach unknown in practice, I played around with the demo and decided to put it into two repositories that demonstrate and will help me repeat my path.
Preparing library chart
In my case, I have an almost ready-made library, but I had to figure out how to compile it, version it and upload it to some kind of registry.
For experiments with the OCI registry, I chose quay.io and GitHub for storing code.
The code was based on the official ones examples
All commands are described in detail in repositories demo-helm-library
In a nutshell – you need to create your own registry, log in to it using Helm
helm registry login -u $QUAY_USERNAME -p $QUAY_PASSWD_ENCRYPTED quay.io
Then pack the chart and push it into the registry
helm package .
helm push demo-library-0.1.1.tgz oci://quay.io/$QUAY_USERNAME/test-helm
After this you will have a library chart loaded into your registry.
Using library chart in other charts
Here everything is even simpler, you need to add the library to your chart as a dependency
dependencies:
- name: demo-library
version: 0.1.1
repository: oci://quay.io/greengrunt/test-helm
Then build these dependencies, collect and push the chart into the registry
helm dependency update .
helm package .
helm push demo-chart-0.1.0.tgz oci://quay.io/$QUAY_USERNAME/test-helm
Everything is also described in detail in another repository demo-helm-chart