9

I have created common helm charts. In values.yml file, I have set of env variables that need to be set as part of deployment.yaml file.

Snippet of values file.

env:
  name: ABC
  value: 123
  name: XYZ
  value: 567
  name:  PQRS
  value: 345

In deployment.yaml, when the values are referred, only the last name/value are set, other values are overwritten. How to read/set all the names/values in the deployment file?

Sunil Gajula
  • 1,117
  • 2
  • 14
  • 30

4 Answers4

19

I've gone through a few iterations of how to handle setting sensitive environment variables. Something like the following is the simplest solution I've come up with so far:

template:

{{- if or $.Values.env $.Values.envSecrets }}
env:
  {{- range $key, $value := $.Values.env }}
  - name: {{ $key }}
    value: {{ $value | quote }}
  {{- end }}
  {{- range $key, $secret := $.Values.envSecrets }}
  - name: {{ $key }}
    valueFrom:
      secretKeyRef:
        name: {{ $secret }}
        key: {{ $key | quote }}
  {{- end }}
{{- end }}

values:

env:
  ENV_VAR: value
envSecrets:
  SECRET_VAR: k8s-secret-name

Pros:

syntax is pretty straightforward

keys are easily mergeable. This came in useful when creating CronJobs with shared secrets. I was able to easily override "global" values using the following:

  {{- range $key, $secret := merge (default dict .envSecrets) $.Values.globalEnvSecrets }}

Cons:

This only works for secret keys that exactly match the name of the environment variable, but it seems like that is the typical use case.

Sunil Gajula
  • 1,117
  • 2
  • 14
  • 30
  • Another Con : if you planned to use dependent environment variables, then using this syntax will break the order you define your environment variables and may lead to this problem : https://stackoverflow.com/a/62896111/2832282 – Cyril Duchon-Doris Jul 20 '21 at 15:34
  • A workaround I'm using in the meantime regarding the problem I mentioned above, is to have as many env top level keys as I have levels of variable dependency, and I repeat in the template the declaration of Values.env, Values.dependentEnv, etc. – Cyril Duchon-Doris Jul 20 '21 at 15:45
4

This is how I solved it in a common helm-chart I developed previously:

          env:
            {{- if .Values.env }}
            {{- toYaml .Values.env | indent 12 }}
            {{- end }}

In the values.yaml:

env:
- name: ENV_VAR
  value: value
# or
- name: ENV_VAR
  valueFrom:
    secretKeyRef:
      name: secret_name
      key: secret_key

An important thing to note here is the indention. Incorrect indentation might lead to a valid helm-chart (yaml file), but the kubernetes API will give an error.

Blokje5
  • 4,763
  • 1
  • 20
  • 37
  • 1
    seems promising, but I got error (Helm v3.4.1) `helm template pact-broker Error: YAML parse error on ${applicationName}/templates/deployment.yaml: error converting YAML to JSON: yaml: line 44: mapping values are not allowed in this context Use --debug flag to render out invalid YAML ` this was working for me in a better way https://stackoverflow.com/a/60098256/535560 – bedla.czech Dec 10 '20 at 13:22
2

It looks like you've made a typo and forgot your dashes. Without the dashes yaml will evaluate env into a single object instead of a list and overwrite values in unexpected ways.

Your env should like more like this:

env:
- name: ABC
  value: 123
- name: XYZ
  value: 567
- name:  PQRS
  value: 345
- name: SECRET
  valueFrom:
    secretKeyRef:
      name: name
      key: key

https://www.convertjson.com/yaml-to-json.htm can help visualize how the yaml is being interpreted and investigate syntax issues.

SmujMaiku
  • 603
  • 6
  • 10
1

You could let the chart user decide if he wants to take environment variables from a secret, provide the value, or take it from the downward API in the values.yaml

env: 
  FOO: 
    value: foo
  BAR: 
    valueFrom:
      secretKeyRef:
        name: bar
        key: barKey
  POD_NAME:    
    valueFrom:
      fieldRef:
        fieldPath: metadata.name

and render it in the deployment.yaml

spec:
  # ...
  template:
    # ...
    spec:
      # ...
      containers:
        - name: {{ .Chart.Name }}
          env: 
            {{- range $name, $item := .Values.env }}
            - name: {{ $name }}
              {{- $item | toYaml | nindent 14 }}
            {{- end }}
          # ...

This is relatively simple and flexible.

It has the shortcoming of not keeping the order of the environment variables. This can break dependent environment variables.

I have written a bit longer story on how to support corrrect ordering as well: An Advanced API for Environment Variables in Helm Charts.

dastrobu
  • 1,600
  • 1
  • 18
  • 32