43

I've a Deployment object where I expose the POD ID using the Downward API. That works fine. However, I want to set up another env variable, log path, with reference to the POD ID. But, setting that variable value to /var/log/mycompany/${POD_ID}/logs isn't working, no logs are created in the container. I can make the entrypoint script or the app aware of the POD ID, and build up the log path, but I'd rather not do that.

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219

4 Answers4

87

The correct syntax is to use $(FOO), as is described in the v1.EnvVar value: documentation; the syntax you have used is "shell" syntax, which isn't the way kubernetes interpolates variables. So:

containers:
- env:
  - name: POD_ID
    valueFrom: # etc etc
  - name: LOG_PATH
    value: /var/log/mycompany/$(POD_ID)/logs

Also please note that, as mentioned in the Docs, the variable to expand must be defined before the variable referencing it.

FrVaBe
  • 47,963
  • 16
  • 124
  • 157
mdaniel
  • 31,240
  • 5
  • 55
  • 58
  • 12
    Thanks. Why be consistent when you can cook up something new just to confuse people. – Abhijit Sarkar Mar 31 '18 at 04:01
  • 6
    ["That's the good thing about standards: so many to choose from"](https://en.wikiquote.org/wiki/Andrew_S._Tanenbaum) – mdaniel Apr 01 '18 at 06:25
  • how about Kubernetes ConfigMaps? I tried that solution and I failed :-( – devstructor Oct 18 '18 at 08:22
  • @devstructor it smells like you have a new question; please don't hijack other people's comment threads – mdaniel Oct 19 '18 at 03:11
  • @MatthewLDaniel The topic of this question is "Kubernetes: How to refer to one environment variable from another?" In ConfigMaps we can declare environment variables, so my comment is deeply connected the question and provided answer. It also can tell others that solution will not work in ConfigMaps. – devstructor Oct 24 '18 at 12:36
  • When I try this for some reason the $ symbol is being escaped - name: DATA_MOUNT_PATH value: /data/$POD_NAME >>> $DATA_MOUNT_PATH >>> "/data/\$POD_NAME" Very annoying, not sure if it's because I am using statefulsets – Illegal Operator Nov 19 '18 at 16:13
  • 1
    The syntax is, as I both said **and linked to**, `$()` -- there is no "unquoted" flavor, you must enclose the reference with dollar, left-paren, the identifier, right-paren – mdaniel Nov 20 '18 at 06:14
  • It might be useful to know that you can also refer to variables defined in an earlier `envFrom:` `configMapRef:`. We use this to define java properties (`name: JAVA_OPTS` `value: "-Djavaproperty=$(CONFIG_MAP_VARIABLE)"`). – Pianosaurus Nov 13 '20 at 20:20
  • Order is important. Firstly you define a variable and then re-use it. – laimison Nov 27 '20 at 04:40
12

I'd just like to add to this question, a caveat we ran into the other day. According to the documentation:

Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged.

Emphasis mine. If you have

  - name: POD_ID
    valueFrom: # etc etc
  - name: LOG_PATH
    value: /var/log/mycompany/$(POD_ID)/logs

it will work, but if you have

  - name: LOG_PATH
    value: /var/log/mycompany/$(POD_ID)/logs
  - name: POD_ID
    valueFrom: # etc etc

it will not. If you're using a templating engine to generate your specs, beware.

Jonathan Lynch
  • 557
  • 1
  • 5
  • 12
3

Here is an example which reads metadata.name

          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: LOG_FILE_NAME
            value: "/app/log/$(POD_NAME).log"

Here is another example, which reads metadata.namespace

          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: REACT_APP_DB_URI
            value: "http://api-$(POD_NAMESPACE).org.com"

One more example, demonstrating how to read from metadata.labels

          - name: SRVC_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['app']
          - name: LOG_FILE_NAME
            value: '/app/log/$(SRVC_NAME).log'

The key is dependent variable should defined later

Refer this for more details

craftsmannadeem
  • 2,665
  • 26
  • 22
  • What does your answer add to the other ones? Apparently nothing. – Abhijit Sarkar Feb 25 '21 at 01:10
  • Two things: 1) Correct link from Kubernetes on dependent variables 2) Practical use case, reading from meta data, instated of made up. It demonstrate how to read meta data and use it as variables in another dependent variable. – craftsmannadeem Feb 25 '21 at 07:59
0

you can also add a secret first then use newly created secret into your countless deployment files to share same environment variable with value:

kubectl create secret generic jwt-secret --from-literal=JWT_KEY=my_awesome_jwt_secret_code
spec:
      containers:
        - name: auth
          image: lord/auth
          env:
            - name: MONGO_URI
              value: "mongodb://auth-mongo-srv:27017/auth"
            - name: JWT_KEY
              valueFrom:
                secretKeyRef:
                  name: jwt-secret
                  key: JWT_KEY
 process.env.MONGO_URI
 process.env.JWT_KEY
Rafiq
  • 8,987
  • 4
  • 35
  • 35