Kubernetes Environment Variables and Downward API

Applications need information to run: a database address, a feature switch, a region name. Hard-coding those values inside an image forces a rebuild for every change. Kubernetes injects values at runtime through environment variables, and the Downward API lets a pod read facts about itself.

Why Runtime Values Matter

Imagine a restaurant chain that prints menus at the factory. Every price change needs a new print run. Menus with blank price slots filled in at each branch solve the problem. Environment variables act as those blank slots. The image stays identical across development, staging, and production, and each environment supplies its own values.

Setting Plain Values

The env field lists name and value pairs for a container.

apiVersion: v1
kind: Pod
metadata:
  name: greeter
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "echo Hello $USER_NAME from $APP_MODE; sleep 3600"]
    env:
    - name: USER_NAME
      value: "Asha"
    - name: APP_MODE
      value: "demo"

Check the result with kubectl logs greeter.

Pulling Values from ConfigMaps and Secrets

Plain values suit small experiments. Real applications read settings from ConfigMaps and passwords from Secrets.

env:
- name: DB_HOST
  valueFrom:
    configMapKeyRef:
      name: app-config
      key: database_host
- name: DB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: app-secret
      key: password

The envFrom field loads every key of a ConfigMap at once.

envFrom:
- configMapRef:
    name: app-config

Diagram: Where Values Come From

 ┌───────────────┐
 │ Plain value   │──┐
 └───────────────┘  │
 ┌───────────────┐  │      ┌──────────────────────┐
 │ ConfigMap     │──┼────▶ │ Container            │
 └───────────────┘  │      │ DB_HOST=db.local     │
 ┌───────────────┐  │      │ DB_PASSWORD=****     │
 │ Secret        │──┤      │ POD_NAME=orders-7f9  │
 └───────────────┘  │      └──────────────────────┘
 ┌───────────────┐  │
 │ Downward API  │──┘
 └───────────────┘

What the Downward API Does

A container often needs to know who it is: the pod name, the namespace, the IP address, or the CPU limit assigned to it. A name tag at a conference works the same way. Staff print the tag, and the wearer reads it without asking anyone. The Downward API exposes this self-knowledge without calling the Kubernetes API server, so the application needs no special permissions.

Exposing Pod Fields as Variables

The fieldRef setting reads fields from the pod definition.

env:
- name: POD_NAME
  valueFrom:
    fieldRef:
      fieldPath: metadata.name
- name: POD_NAMESPACE
  valueFrom:
    fieldRef:
      fieldPath: metadata.namespace
- name: POD_IP
  valueFrom:
    fieldRef:
      fieldPath: status.podIP
- name: NODE_NAME
  valueFrom:
    fieldRef:
      fieldPath: spec.nodeName

Logging libraries use these values to stamp each log line with the pod name, which makes searching in a central log system simple.

Exposing Resource Limits

The resourceFieldRef setting shares the container's CPU and memory settings.

env:
- name: MEMORY_LIMIT
  valueFrom:
    resourceFieldRef:
      containerName: app
      resource: limits.memory

Java and Node.js runtimes read this value to size their memory pools correctly.

Downward API Volume Files

Labels and annotations can change while a pod runs. Environment variables stay frozen at container start, but files in a Downward API volume refresh automatically.

apiVersion: v1
kind: Pod
metadata:
  name: label-reader
  labels:
    app: shop
    tier: frontend
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "cat /etc/podinfo/labels; sleep 3600"]
    volumeMounts:
    - name: podinfo
      mountPath: /etc/podinfo
  volumes:
  - name: podinfo
    downwardAPI:
      items:
      - path: labels
        fieldRef:
          fieldPath: metadata.labels

Choosing Between Variables and Files

MethodUpdates while runningBest use
Environment variableNo, restart neededNames, IPs, fixed settings
Volume fileYes, within about a minuteLabels, annotations, changing data

Available Fields at a Glance

  • metadata.name: the pod name.
  • metadata.namespace: the namespace of the pod.
  • metadata.labels and metadata.annotations: files only.
  • spec.nodeName: the node that runs the pod.
  • spec.serviceAccountName: the identity of the pod.
  • status.podIP: the pod IP address.
  • limits.cpu, limits.memory, requests.cpu, requests.memory: resource values.

Variable Expansion

Kubernetes lets one variable reference another with the $(NAME) syntax.

env:
- name: HOST
  value: "db.internal"
- name: DB_URL
  value: "postgres://$(HOST):5432/shop"

Define the referenced variable above the one that uses it. Kubernetes resolves names in list order.

Good Habits

  • Store passwords in Secrets and keep them out of plain value fields.
  • Pick clear, uppercase names such as DB_HOST.
  • Restart pods after a ConfigMap change when the application reads variables at startup. A rollout restart handles this: kubectl rollout restart deployment shop.
  • Use Downward API files for data that changes during the pod lifetime.

Key Points

  • Environment variables keep images reusable across environments.
  • ConfigMaps and Secrets feed variables through valueFrom and envFrom.
  • The Downward API shows a pod its own metadata and limits.
  • Volume files refresh themselves; variables do not.