Search code examples
kubernetescontinuous-integrationkubernetes-helm

Best practice for setting the fqin in a Helm chart


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.


Solution

  • 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.