Environment Variables
Welcome to the module on Environment Variables. Here you will learn key concepts and best practices to master this topic.
1. The Problem: Hardcoded Brittle Configurations
Imagine you are deploying a brand new microservice that connects to a database. If you hardcode the database connection string directly into your source code (e.g., String dbHost = "production-db.internal";), what happens when you need to run the same code in your local development environment? The service will attempt to connect to the production database, potentially causing data corruption or failing due to firewall restrictions.
To solve this, applications must be decoupled from their environment-specific configurations. The Twelve-Factor App methodology strictly dictates that all configuration likely to vary between deployments (staging, production, local environments) should be stored in the environment.
The Analogy: The Worker’s Clipboard
Think of a Kubernetes Pod as a newly hired worker reporting for their first day on a construction site. The container image is the worker’s innate skills (how to hammer a nail, how to mix cement). However, the worker doesn’t know which house to build or where the materials are located. Environment Variables are like a clipboard handed to the worker the exact moment they step onto the site. The clipboard contains dynamic instructions (e.g., SITE_ADDRESS=123_Main_St, MATERIAL_SUPPLIER=Acme_Corp) that allow the exact same worker to perform their job differently depending on the site they are assigned to.
2. The Solution: env and envFrom
Kubernetes provides two primary ways to inject environment variables into your containers:
env: Allows you to specify explicit key-value pairs or pull individual keys selectively from ConfigMaps or Secrets.envFrom: Allows you to inject all the key-value pairs from an entire ConfigMap or Secret as environment variables simultaneously in a single command.
3. Interactive: Environment Variable Explorer
See the difference between a targeted single env injection and a bulk envFrom injection. Notice how envFrom exposes the entire configuration map, while env gives you granular control over what the container actually sees.
ConfigMap to Env Injection
ConfigMap (app-config)
Container Environment
4. Hardware Reality: Process Environment Space
When a container starts, the container runtime (e.g., containerd) creates a new process for the application. The environment variables you define in your Kubernetes Pod manifest are passed directly to the execve system call when this process is initialized.
Because of this specific hardware reality, there are strict rules and implications:
- Immutability: Environment variables are static. If you update a ConfigMap or Secret that is mapped to a running container’s environment variables, the running Pod’s environment variables do NOT change automatically. The
execvecall has already occurred. You must restart the Pod to inject the new values. - Size Limitations: The total size of the environment space is limited by the operating system kernel (usually bounded by the
ARG_MAXlimit, which restricts the total size of command-line arguments and environment variables combined). You should not attempt to shove massive files (like large SSL certificates or massive JSON configuration blobs) into environment variables. For large or complex configurations, use Volume Mounts instead.
War Story: The Silent Config Mismatch
In a large-scale deployment at a major e-commerce company, engineers updated a ConfigMap containing a feature toggle to disable a failing external payment gateway. However, because the configuration was injected via
envFrom, the running pods did not detect the change. The application continued to route traffic to the failing gateway, resulting in hours of downtime. The team had to manually run a rolling restart (kubectl rollout restart deployment) to force the pods to recreate and pull the updated environment variables. This led to a permanent architectural shift: dynamic feature flags were moved to a dedicated configuration server, while environment variables were reserved only for immutable, startup-critical data.
5. Implementation: Java & Go
// Java: Reading Environment Variables
public class EnvConfig {
public static void main(String[] args) {
// Read DB_HOST injected via env or envFrom
String dbHost = System.getenv("DB_HOST");
String dbPort = System.getenv("DB_PORT");
if (dbHost != null && dbPort != null) {
System.out.println("Connecting to Database at " + dbHost + ":" + dbPort);
} else {
System.err.println("Database configuration missing from environment!");
System.exit(1);
}
}
}
// Go: Reading Environment Variables
package main
import (
"fmt"
"os"
)
func main() {
// Read DB_HOST injected via env or envFrom
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
if dbHost != "" && dbPort != "" {
fmt.Printf("Connecting to Database at %s:%s\n", dbHost, dbPort)
} else {
fmt.Fprintln(os.Stderr, "Database configuration missing from environment!")
os.Exit(1)
}
}
6. YAML Manifests
Using env
Injecting a specific key from a ConfigMap provides explicit visibility into what exact values the container is consuming. It also protects against accidental injections of irrelevant configurations.
apiVersion: v1
kind: Pod
metadata:
name: env-single-demo
spec:
containers:
- name: app
image: my-app:1.0
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
Using envFrom
Injecting all keys from a ConfigMap as environment variables is convenient for services that require a massive amount of distinct configuration values. However, use this with caution, as it could unintentionally expose values to the container process space that it does not need.
apiVersion: v1
kind: Pod
metadata:
name: envfrom-demo
spec:
containers:
- name: app
image: my-app:1.0
envFrom:
- configMapRef:
name: app-config
7. Summary & Best Practices
- Keep it small: Do not store huge payloads in environment variables. Use volumes for files like certificates or large JSON files.
- Prefer explicit
envwhen possible: WhileenvFromis easy to write, explicitenvvariables self-document what exact keys your application needs right in the YAML manifest. - Remember the static nature: Changing a
ConfigMaporSecretwill not update the environment of running pods. A deployment rollout is required to pick up the new changes.