Kubernetes
Node Labeling
Environment Variables
Pod Configuration
DevOps

Set node label to the pod environment variable

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A pod often needs node metadata for logging, routing, or region-aware behavior. Kubernetes can expose the pod name, namespace, and node name through the Downward API, but it does not directly map arbitrary node labels into pod environment variables. The reliable pattern is a two-step flow: inject node name first, then query the Kubernetes API for the node label and write it into an env file the main container can load.

Why Direct Mapping Does Not Exist

The scheduler decides the node at runtime, and node labels are cluster-level metadata. The Downward API is intentionally limited to selected pod and container fields to avoid broad metadata access from every workload. That is why you can reference spec.nodeName, but you cannot use a built-in field to read a label like topology.kubernetes.io/zone directly.

If you need label-driven behavior in application code, plan for explicit API access and RBAC. This keeps permissions auditable and avoids hidden assumptions about cluster internals.

The most practical setup has four parts:

  1. Service account for the workload.
  2. Read-only permission to get node objects.
  3. NODE_NAME environment variable from Downward API.
  4. Init container that queries the node label and writes a small shell file to a shared volume.

Use a cluster role because nodes are cluster-scoped resources.

yaml
1apiVersion: v1
2kind: ServiceAccount
3metadata:
4  name: node-label-reader
5  namespace: app
6---
7apiVersion: rbac.authorization.k8s.io/v1
8kind: ClusterRole
9metadata:
10  name: node-label-reader
11rules:
12  - apiGroups: [""]
13    resources: ["nodes"]
14    verbs: ["get"]
15---
16apiVersion: rbac.authorization.k8s.io/v1
17kind: ClusterRoleBinding
18metadata:
19  name: node-label-reader
20roleRef:
21  apiGroup: rbac.authorization.k8s.io
22  kind: ClusterRole
23  name: node-label-reader
24subjects:
25  - kind: ServiceAccount
26    name: node-label-reader
27    namespace: app

Now wire the pod:

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: node-aware-app
5  namespace: app
6spec:
7  serviceAccountName: node-label-reader
8  restartPolicy: Always
9  volumes:
10    - name: node-meta
11      emptyDir: {}
12  initContainers:
13    - name: resolve-node-zone
14      image: bitnami/kubectl:1.30
15      env:
16        - name: NODE_NAME
17          valueFrom:
18            fieldRef:
19              fieldPath: spec.nodeName
20      command: ["sh", "-c"]
21      args:
22        - |
23          set -eu
24          zone=$(kubectl get node "$NODE_NAME" -o jsonpath='{.metadata.labels.topology\.kubernetes\.io/zone}')
25          [ -n "$zone" ] || zone=unknown
26          printf 'NODE_ZONE=%s\n' "$zone" > /meta/node.env
27      volumeMounts:
28        - name: node-meta
29          mountPath: /meta
30  containers:
31    - name: app
32      image: python:3.12-slim
33      command: ["sh", "-c", ". /meta/node.env && python /app/main.py"]
34      volumeMounts:
35        - name: node-meta
36          mountPath: /meta

In the app process, the variable is now available like any normal environment variable.

python
1import os
2
3zone = os.getenv('NODE_ZONE', 'unknown')
4print(f'running in zone={zone}')

Operational Improvements

For production use, make the label key configurable. Some clusters use custom keys like nodepool, capacity-type, or a company-specific zone tag. A small shell script can read a key from env and safely return a default when the label is absent.

bash
1#!/usr/bin/env sh
2set -eu
3
4: "${NODE_NAME:?missing NODE_NAME}"
5: "${LABEL_KEY:=topology.kubernetes.io/zone}"
6
7escaped_key=$(printf '%s' "$LABEL_KEY" | sed 's/\./\\./g')
8value=$(kubectl get node "$NODE_NAME" -o "jsonpath={.metadata.labels.$escaped_key}" 2>/dev/null || true)
9[ -n "$value" ] || value="unknown"
10printf 'NODE_LABEL=%s\n' "$value"

You can store that script in a ConfigMap and mount it into the init container to keep the pod spec short and reusable.

Common Pitfalls

  • Missing RBAC for nodes. The init container fails with forbidden errors. Fix by granting get on nodes through a cluster role.
  • Assuming every node has the same label. Some autoscaled pools can differ. Fix by handling missing labels with a default value and clear logs.
  • Using app startup before metadata file exists. If you skip an init container and run both steps in one container, ordering bugs appear. Fix by keeping metadata resolution in an init container.
  • Hard-coding one label key forever. Cluster standards change over time. Fix by making the key configurable.
  • Over-privileged service account. Avoid broad permissions. Restrict access to only the get verb on nodes.

Summary

  • Kubernetes does not natively inject arbitrary node labels into pod env vars.
  • The stable pattern is spec.nodeName plus an API query from an init container.
  • Use explicit RBAC with minimal permission to read node metadata.
  • Write resolved values into a shared env file and load it in the main container.
  • Add defaults and configurable label keys so the workload survives cluster variation.

Course illustration
Course illustration

All Rights Reserved.