2

I have a set of environment variables in my deployment using EnvFrom and configMapRef. The environment variables held in these configMaps were set by kustomize originally from json files.

spec.template.spec.containers[0].

envFrom:
  - secretRef:
      name: eventstore-login
  - configMapRef:
      name: environment
  - configMapRef:
      name: eventstore-connection
  - configMapRef:
      name: graylog-connection
  - configMapRef:
      name: keycloak
  - configMapRef:
      name: database

The issue is that it's not possible for me to access the specific environment variables directly.

Here is the result of running printenv in the pod:

...
eventstore-login={
  "EVENT_STORE_LOGIN": "admin",
  "EVENT_STORE_PASS": "changeit"
}

evironment={
  "LOTUS_ENV":"dev",
  "DEV_ENV":"dev"
}

eventstore={
  "EVENT_STORE_HOST": "eventstore-cluster",
  "EVENT_STORE_PORT": "1113"
}

graylog={
  "GRAYLOG_HOST":"",
  "GRAYLOG_SERVICE_PORT_GELF_TCP":""
}
...

This means that from my nodejs app I need to do something like this

> process.env.graylog
'{\n  "GRAYLOG_HOST":"",\n  "GRAYLOG_SERVICE_PORT_GELF_TCP":""\n}\n'

This only returns the json string that corresponds to my original json file. But I want to be able to do something like this:

process.env.GRAYLOG_HOST

To retrieve my environment variables. But I don't want to have to modify my deployment to look something like this:

          env:
            - name: NODE_ENV
              value: dev
            - name: EVENT_STORE_HOST
              valueFrom:
                secretKeyRef:
                  name: eventstore-secret
                  key: EVENT_STORE_HOST
            - name: EVENT_STORE_PORT
              valueFrom:
                secretKeyRef:
                  name: eventstore-secret
                  key: EVENT_STORE_PORT
            - name: KEYCLOAK_REALM_PUBLIC_KEY
              valueFrom:
                configMapKeyRef:
                  name: keycloak-local
                  key: KEYCLOAK_REALM_PUBLIC_KEY

Where every variable is explicitly declared. I could do this but this is more of a pain to maintain.

Wytrzymały Wiktor
  • 11,492
  • 5
  • 29
  • 37

1 Answers1

2

Short answer:

You will need to define variables explicitly or change configmaps so they have 1 environment variable = 1 value structure, this way you will be able to refer to them using envFrom. E.g.:

"apiVersion": "v1",
"data": {
    "EVENT_STORE_LOGIN": "admin",
    "EVENT_STORE_PASS": "changeit"
},
"kind": "ConfigMap",

More details

Configmaps are key-value pairs that means for one key there's only one value, configmaps can get string as data, but they can't work with map.

I tried edited manually the configmap to confirm the above and got following:

invalid type for io.k8s.api.core.v1.ConfigMap.data: got "map", expected "string"

This is the reason why environment comes up as one string instead of structure.

For example this is how configmap.json looks:

$ kubectl describe cm test2

Name:         test2
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
test.json:
----
environment={
  "LOTUS_ENV":"dev",
  "DEV_ENV":"dev"
}

And this is how it's stored in kubernetes:

$ kubectl get cm test2 -o json

{
    "apiVersion": "v1",
    "data": {
        "test.json": "evironment={\n  \"LOTUS_ENV\":\"dev\",\n  \"DEV_ENV\":\"dev\"\n}\n"
    },

In other words observed behaviour is expected.

Useful links:

moonkotte
  • 3,661
  • 2
  • 10
  • 25
  • 1
    Ahh so I do need to reference them individually. They need to make this a map instead or give the option to "flatten" the config maps when they are parsed. Thank you! – Kévin Sanchez Lacroix Sep 02 '21 at 11:56
  • This actually goes from the data storage which is used in kubernetes - this is `etcd` which is correct, `key-value` storage. So I'm not sure it will be changed because it will make the logic much more complex. – moonkotte Sep 02 '21 at 12:07