overriding values in kubernetes helm subcharts

4/21/2018

I'm building a helm chart for my application, and I'm using stable/nginx-ingress as a subchart. I have a single overrides.yml file that contains (among other overrides):

nginx-ingress:
  controller:
    annotations:
      external-dns.alpha.kubernetes.io/hostname: "*.{{ .Release.Name }}.mydomain.com"

So, I'm trying to use the release name in the overrides file, and my command looks something like: helm install mychart --values overrides.yml, but the resulting annotation does not do the variable interpolation, and instead results in something like

Annotations: external-dns.alpha.kubernetes.io/hostname=*.{{ .Release.Name }}.mydomain.com

I installed the subchart by using helm fetch, and I'm under the (misguided?) impression that it would be best to leave the fetched thing as-is, and override values in it - however, if variable interpolation isn't available with that method, I will have to put my values in the subchart's values.yaml.

Is there a best practice for this? Is it ok to put my own values in the fetched subchart's values.yaml? If I someday helm fetch this subchart again, I'll have to put those values back in by hand, instead of leaving them in an untouched overrides file...

Thanks in advance for any feedback!

-- Hoopes
kubernetes
kubernetes-helm

2 Answers

2/21/2020

Helm 3.x (Q4 2019) now includes more about this, but for chart only, not for subchart (see TBBle's comment)

Milan Masek adds as a comment:

Thankfully, latest Helm manual says how to achieve this.

The trick is:

  • enclosing variable in " or in a yaml block |-, and
  • then referencing it in a template as {{ tpl .Values.variable . }}

This seems to make Helm happy.

Example:

cat Chart.yaml | grep appVersion
appVersion: 0.0.1-SNAPSHOT-d2e2f42


cat platform/shared/t/values.yaml | grep -A2 image:
image: 
  tag: |-
    {{ .Chart.AppVersion }}


cat templates/deployment.yaml | grep image:
          image: "{{ .Values.image.repository }}:{{ tpl .Values.image.tag . }}"


helm template . --values platform/shared/t/values.betradar.yaml | grep image
          image: "docker-registry.default.svc:5000/namespace/service:0.0.1-SNAPSHOT-d2e2f42"
          imagePullPolicy: Always
      image: busybox

Otherwise there is an error thrown..

$ cat platform/shared/t/values.yaml | grep -A1 image:
image: 
  tag: {{ .Chart.AppVersion }}

1 $ helm template . --values platform/shared/t/values.yaml | grep image
Error: failed to parse platform/shared/t/values.yaml: error converting YAML to JSON: yaml: invalid map key: map[interface {}]interface {}{".Chart.AppVersion":interface {}(nil)}

For Helm subchart, TBBle adds to issue 2133

@MilanMasek 's solution won't work in general for subcharts, because the context . passed into tpl will have the subchart's values, not the parent chart's values.

It happens to work in the specific example this ticket was opened for, because .Release.Name should be the same in all the subcharts.
It won't work for .Chart.AppVersion as in the tpl example.

There was a proposal to support tval in #3252 for interpolating templates in values files, but that was dropped in favour of a lua-based Hook system which has been proposed for Helm v3: #2492 (comment)

That last issue 2492 include workarounds like this one:

You can put a placeholder in the text that you want to template and then replace that placeholder with the template that you would like to use in yaml files in the template.

For now, what I've done in the CI job is run helm template on the values.yaml file.
It works pretty well atm.

cp values.yaml templates/
helm template $CI_BUILD_REF_NAME ./ | sed -ne '/^# Source: 
templates\/values.yaml/,/^---/p' > values.yaml
rm templates/values.yaml

helm upgrade --install ...

This breaks if you have multiple -f values.yml files, but I'm thinking of writing a small helm wrapper that runs essentially runs that bash script for each values.yaml file.

fsniper illustrates again the issue:

There is a use case where you would need to pass deployment name to dependency charts where you have no control.

For example I am trying to set podAffinity for zookeeper. And I have an application helm chart which sets zookeeper as a dependency.

In this case, I am passing pod antiaffinity to zookeeper via values. So in my apps values.yaml file I have a zookeeper.affinity section.
If I had the ability to get the release name inside the values yaml I would just set this as default and be done with it.

But now for every deployment I have to override this value, which is a big problem.

-- VonC
Source: StackOverflow

4/23/2018

I found the issue on github -- it is not supported yet: https://github.com/kubernetes/helm/issues/2133

-- Nick Rak
Source: StackOverflow