0

I would like a CI pipeline to build an image and a Helm chart. A part of that is of course to set the FQIN of the Helm chart before publishing it.

There are lots of examples on how to do it during installation, but not during packaging. I was surprised that I couldn't find examples on this common use case on https://helm.sh. Hand editing the values file of the chart is not an option because it is a CI pipeline.

What is the best practice for doing this without introducing complex CICD tools.

Erik Martino
  • 4,023
  • 1
  • 19
  • 12
  • What's a "FQIN"? In your CD pipeline, you should be able to create additional YAML (or equivalently JSON) files and pass them in using a `helm install -f` option; that's probably the most reliable way to provide deploy-time settings. – David Maze Dec 05 '21 at 11:11
  • FQIN=Fully Qualified Image Name (repo/name:tag). Image names are not really a deploy time setting, they are shared between installations. I can see it would work, to pass it at install time, but you would need a side channel to pass the image names to the installer. – Erik Martino Dec 06 '21 at 07:36

1 Answers1

3

Your "fully qualified image name" is made up of three parts: a registry host name, the image name itself, and the tag of the image. I'd recommend passing all three as Helm values, even if only some of them will change.

image: '{{ .Values.registry }}/{{ .Values.image }}:{{ .Values.tag }}'
registry: docker.io
image: my/image
tag: latest

(When Docker Hub started rate-limiting, I started being really grateful for charts where you could configure the registry address to point at a local mirror.)

Then when you go to actually deploy the image, you need to specify the tag. In Kubernetes you are all but required to use a unique tag for each build.

docker build -t my/image:20211206 .
docker push my/image:20211206
helm upgrade --install --namespace myapp myapp ./charts/myapp \
  --set-string tag=20211206

If your CI system can write out JSON files, consider putting the tag and other deploy-time settings into a JSON file and passing that as a helm install -f option, instead of --set or --set-string. The syntax is much more familiar and you'll have more control over object types when it matters.

There's an alternative approach that involves actually editing the chart as part of the build. You might have a "GitOps" style workflow where one part of your build system actually commits to source control, and the resulting push triggers the next step. This has some advantages in that it's easy to verify the file output of one stage, and it's easy to see the history of exactly what got deployed when (because deployment history is source control history).

To do this, your CI system itself would need to change the tag: in values.yaml. Chart.yaml has an appVersion: setting which can match this, plus if you're making automated changes to the chart itself it's a good idea to increment the chart's version:. The CI system would make these changes, commit, and push, and then the push would trigger itself to do the next step of deploy. Since now the right settings are in values.yaml you don't need a --set-string option.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • The first optional, let helm set the values at install time is unsatisfying because it breaks encapsulation and there is no tooling support for passing around these values. If you have several services that doesn't share versions it is quite cumbersome. However it does have helm support. The second solution is the one I am using, but I wonder why there is no helm support for it during package time. – Erik Martino Dec 08 '21 at 07:53
  • A variant of your solution that comes to mind is to have an autogenerated umbrella helm chart that has subcharts as dependencies and contains the specific image versions in the values file. That lets you install your complete ci environment in one go. – Erik Martino Dec 08 '21 at 08:02