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
| Method | Updates while running | Best use |
|---|---|---|
| Environment variable | No, restart needed | Names, IPs, fixed settings |
| Volume file | Yes, within about a minute | Labels, 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
valuefields. - 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
valueFromandenvFrom. - The Downward API shows a pod its own metadata and limits.
- Volume files refresh themselves; variables do not.
