<p>How to set Node label to Pod environment variable? I need to know the label <code>topology.kubernetes.io/zone</code> value inside the pod.</p>

<p>The <a href="https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/" rel="nofollow noreferrer">Downward API</a> currently does not support exposing node labels to pods/containers. There is an <a href="https://github.com/kubernetes/kubernetes/issues/40610" rel="nofollow noreferrer">open issue</a> about that on GitHib, but it is unclear when it will be implemented if at all.</p>
<p>That leaves the only option to get node labels from Kubernetes API, just as <code>kubectl</code> does. It is not easy to implement, especially if you want labels as environment variables. I'll give you an example how it can be done with an <code>initContainer</code>, <code>curl</code>, and <code>jq</code> but if possible, I suggest you rather implement this in your application, for it will be easier and cleaner.</p>
<p>To make a request for labels you need permissions to do that. Therefore, the example below creates a service account with permissions to <code>get</code> (describe) nodes. Then, the script in the <code>initContainer</code> uses the service account to make a request and extract labels from <code>json</code>. The <code>test</code> container reads environment variables from the file and <code>echo</code>es one.</p>
<p>Example:</p>
<pre class="lang-yaml prettyprint-override"><code># Create a service account
apiVersion: v1
kind: ServiceAccount
metadata:
  name: describe-nodes
  namespace: &lt;insert-namespace-name-where-the-app-is&gt;
---
# Create a cluster role that allowed to perform describe (&quot;get&quot;) over [&quot;nodes&quot;]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: describe-nodes
rules:
  - apiGroups: [&quot;&quot;]
    resources: [&quot;nodes&quot;]
    verbs: [&quot;get&quot;]
---
# Associate the cluster role with the service account
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: describe-nodes
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: describe-nodes
subjects:
- kind: ServiceAccount
  name: describe-nodes
  namespace: &lt;insert-namespace-name-where-the-app-is&gt;
---
# Proof of concept pod
apiVersion: v1
kind: Pod
metadata:
  name: get-node-labels
spec:
  # Service account to get node labels from Kubernetes API
  serviceAccountName: describe-nodes

  # A volume to keep the extracted labels
  volumes:
    - name: node-info
      emptyDir: {}

  initContainers:
    # The container that extracts the labels
    - name: get-node-labels

      # The image needs 'curl' and 'jq' apps in it
      # I used curl image and run it as root to install 'jq'
      # during runtime
      # THIS IS A BAD PRACTICE UNSUITABLE FOR PRODUCTION
      # Make an image where both present.
      image: curlimages/curl
      # Remove securityContext if you have an image with both curl and jq
      securityContext:
        runAsUser: 0

      # It'll put labels here
      volumeMounts:
        - mountPath: /node
          name: node-info

      env:
        # pass node name to the environment
        - name: NODENAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: APISERVER
          value: https://kubernetes.default.svc
        - name: SERVICEACCOUNT
          value: /var/run/secrets/kubernetes.io/serviceaccount
        - name: SCRIPT
          value: |
            set -eo pipefail

            # install jq; you don't need this line if the image has it
            apk add jq

            TOKEN=$(cat ${SERVICEACCOUNT}/token)
            CACERT=${SERVICEACCOUNT}/ca.crt

            # Get node labels into a json
            curl --cacert ${CACERT} \
                 --header &quot;Authorization: Bearer ${TOKEN}&quot; \
                 -X GET ${APISERVER}/api/v1/nodes/${NODENAME} | jq .metadata.labels &gt; /node/labels.json

            # Extract 'topology.kubernetes.io/zone' from json
            NODE_ZONE=$(jq '.&quot;topology.kubernetes.io/zone&quot;' -r /node/labels.json)
            # and save it into a file in the format suitable for sourcing
            echo &quot;export NODE_ZONE=${NODE_ZONE}&quot; &gt; /node/zone
      command: [&quot;/bin/ash&quot;, &quot;-c&quot;]
      args:
        - 'echo &quot;$$SCRIPT&quot; &gt; /tmp/script &amp;&amp; ash /tmp/script'

  containers:
    # A container that needs the label value
    - name: test
      image: debian:buster
      command: [&quot;/bin/bash&quot;, &quot;-c&quot;]
      # source ENV variable from file, echo NODE_ZONE, and keep running doing nothing
      args: [&quot;source /node/zone &amp;&amp; echo $$NODE_ZONE &amp;&amp; cat /dev/stdout&quot;]
      volumeMounts:
        - mountPath: /node
          name: node-info
</code></pre>
