Kubernetes: Reference Previously-Defined ConfigMap key-value pair

11/9/2018

TL;DR

Can I reference a previously-defined key-value pair in a ConfigMap?

Full Version

I'm writing a deployment specification for an application which accepts its configuration from environment variables at startup. Some of the environment variables are derived from others. If I were setting them up as file to be sourced at application startup, I would simply do:

[me@myserver ~]$ cat ./myenv.sh
export FOO=foo
export BAR=bar
export FOOBAR=$FOO$BAR
[me@myserver ~]$ . ./myenv.sh
[me@myserver ~]$ printenv FOOBAR
foobar

However, the analagous way to do this in a ConfigMap by referencing previously-defined key-value pairs doesn't work (see sample ConfigMap and Pod, below). Here are the results:

[me@myserver ~]$ kubectl create -f my-app-config.yaml -f my-app-pod.yaml
configmap "my-app" created
pod "my-app" created
[me@myserver ~]$ kubectl exec -it my-app -- printenv | grep MY_CONFIGMAP
MY_CONFIGMAP_FOO=foo
MY_CONFIGMAP_FOOBAR=$(MY_CONFIGMAP_FOO)$(MY_CONFIGMAP_BAR)
MY_CONFIGMAP_BAR=bar

Hoped-for value of MY_CONFIGMAP_FOOBAR is foobar.

I attempted to cross-apply the following instructions under Use ConfigMap-defined environment variables in Pod commands from the documentation:

You can use ConfigMap-defined environment variables in the command section of the Pod specification using the $(VAR_NAME) Kubernetes substitution syntax.

However, this obviously did not work, and I've been unable to find an answer in my research.

I suspect I already know the answer, but is there any way to accomplish this?

MCVE

ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app

data:
  MY_CONFIGMAP_FOO: foo
  MY_CONFIGMAP_BAR: bar

  # Desired concatenation would be `foobar`
  MY_CONFIGMAP_FOOBAR: $(MY_CONFIGMAP_FOO)$(MY_CONFIGMAP_BAR)

Pod

apiVersion: v1
kind: Pod
metadata:
  name: my-app

spec:
  containers:
  - name: my-app
    image: alpine
    imagePullPolicy: IfNotPresent
    envFrom:
      - configMapRef:
          name: my-app

    command:
      - /bin/sh

    args:
      - -c
      - "while true; do sleep 3600; done"
-- Doug R.
docker
kubernetes

2 Answers

11/9/2018

You can achieve your expected result with help of this tool: envsubst.

Create the ConfigMap following way,

envsubst < my-app-config.yaml | kubectl apply -f -

Now, all environment variables on your ConfigMap will be replaced with resolved value.

-- Emruz Hossain
Source: StackOverflow

2/20/2019

The recommendation is to use kind: Deployment Combining variables works fine in that config file. I haven't tried pods directly.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app

spec:
  selector:
    matchLabels:
      app: my-app
  replicas: 1
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: alpine
        imagePullPolicy: IfNotPresent
        env:
        - name: MY_CONFIGMAP_FOOBAR
          value: $(MY_CONFIGMAP_FOO)$(MY_CONFIGMAP_BAR)
-- Mike Lingk
Source: StackOverflow