Search code examples
kuberneteskubernetes-helm

How to reuse K8s container environment variables in other containers using helm?


I have a deployment with a pod that has his configuration defined through a lot of environment variables. Now I want to add a sidecar container that requires exactly the same environment variables as the already defined container. Instead of just copy/pasting all the variables I'd like to stick to the DRY principle.

The current definition looks something like this:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: container1
        env:
        - name: MYSQL_HOST
          value: {{ template "mariadb.primary.fullname" .Subcharts.mariadb }}
        - name: MYSQL_DATABASE
          value: {{ .Values.mariadb.auth.database | quote }}
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: {{ .Values.secretName | default (printf "%s-%s" .Release.Name "db") }}
              key: {{ .Values.usernameKey | default "db-username" }}
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ .Values.secretName | default (printf "%s-%s" .Release.Name "db") }}
              key: {{ .Values.passwordKey | default "db-password" }}

The recommended way to reuse environment variables is through a ConfigMap. Now I can create this:

apiVersion: v1
kind: ConfigMap
metadata:
  name: config
data:
  MYSQL_HOST: {{ template "mariadb.primary.fullname" .Subcharts.mariadb }}
  MYSQL_DATABASE: {{ .Values.mariadb.auth.database | quote }}
---
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: container1
        envFrom:
        - configMapRef:
            name: config
      - name: container2
        envFrom:
        - configMapRef:
            name: config

But now I would still need to repeat myself for MYSQL_USER and MYSQL_PASSWORD (and for the 20 other env variables that are like this).

Is it possible to reuse the existing secrets MYSQL_USER and MYSQL_PASSWORD as environment variables without creating duplicates on container1 and container2?


Solution

  • You can create a named template to do this. If you're only going to be using this template within a single Kubernetes object (multiple containers within the same Deployment) you could put it in that object's deployment.yml file, or into the shared _helpers.tpl file.

    {{- define "env.mysql" -}}
    - name: MYSQL_HOST
      value: {{ template "mariadb.primary.fullname" .Subcharts.mariadb }}
    - name: MYSQL_DATABASE
      value: {{ .Values.mariadb.auth.database | quote }}
    - name: ET
      value: cetera
    {{- end -}}
    

    Then wherever you need to use that block of variables, you can include it, and indent it to the correct level.

    spec:
      template:
        spec:
          containers:
          - name: container1
            env:
    {{- include "env.mysql" . | indent 10 }}
              - name: OTHER_ENVIRONMENT_VARIABLES
                value: are okay too
    

    Having defined the template once, you can include it as many times as you need to.