Sunil Gajula
Sunil Gajula

Reputation: 1223

Multiple Env Variables in Helm Charts

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?

Upvotes: 9

Views: 23023

Answers (4)

dastrobu
dastrobu

Reputation: 1726

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.

Upvotes: 2

SmujMaiku
SmujMaiku

Reputation: 643

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.

Upvotes: 2

Sunil Gajula
Sunil Gajula

Reputation: 1223

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.

Upvotes: 20

Blokje5
Blokje5

Reputation: 4993

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.

Upvotes: 4

Related Questions