Kubernetes
StatefulSet
Environment Variables
Pod Configuration
DevOps

Passing separate env variables to statefulset pods

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

A StatefulSet creates Pods from one shared template, so literal environment variables in the manifest are identical across replicas. If each Pod needs a different value, the usual solution is to derive that value from the Pod's stable identity or load per-Pod configuration at startup.

Start With the StatefulSet Pod Identity

StatefulSet Pods have stable names such as app-0, app-1, and app-2. That naming pattern is the key to per-replica behavior.

You can inject the Pod name with the downward API:

yaml
1env:
2  - name: POD_NAME
3    valueFrom:
4      fieldRef:
5        fieldPath: metadata.name

Once the container knows its own name, it can derive the ordinal suffix and pick the correct configuration.

Derive Values in the Entrypoint

A simple and common pattern is to branch in the startup command:

yaml
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4  name: app
5spec:
6  serviceName: app
7  replicas: 3
8  selector:
9    matchLabels:
10      app: app
11  template:
12    metadata:
13      labels:
14        app: app
15    spec:
16      containers:
17        - name: app
18          image: busybox
19          command:
20            - sh
21            - -c
22            - |
23              ordinal="${HOSTNAME##*-}"
24              if [ "$ordinal" = "0" ]; then
25                export ROLE=primary
26              else
27                export ROLE=replica
28              fi
29              echo "pod=$HOSTNAME role=$ROLE"
30              sleep 3600
31          env:
32            - name: POD_NAME
33              valueFrom:
34                fieldRef:
35                  fieldPath: metadata.name

Here the hostname encodes the ordinal, so the container can decide its own role at runtime.

Use Indexed Config for More Complex Per-Pod Values

If each Pod needs a different address list, token, or config fragment, a derived role may not be enough. In that case, keep several config files in a mounted ConfigMap and select the right one by ordinal.

For example, mount files named node-0.env, node-1.env, and node-2.env, then load the one matching the Pod:

bash
ordinal="${HOSTNAME##*-}"
cp "/config/node-${ordinal}.env" /app/runtime.env

The application can then source or parse /app/runtime.env before starting.

This pattern keeps the StatefulSet manifest generic while still allowing specific behavior for each replica.

What Kubernetes Does Not Do Automatically

Kubernetes does not have a built-in syntax that says "replica zero gets this environment variable, replica one gets another one" inside a single plain env list. The template is copied as-is. StatefulSet identity gives you the raw material, but you still provide the branching logic.

That is why most working designs fall into one of these categories:

  • derive values from Pod name or ordinal
  • load indexed config files
  • query an external configuration service using Pod identity

For clustered systems such as databases, brokers, and consensus services, this is usually a feature rather than a limitation. Replica zero can bootstrap the cluster, while later replicas join using configuration derived from their stable ordinal numbers.

Common Pitfalls

  • Expecting static env values in the StatefulSet template to differ automatically per replica.
  • Ignoring the Pod name and hostname even though they already contain the ordinal you need.
  • Creating a separate manifest per replica when one generic manifest plus ordinal-based logic would be simpler.
  • Storing sensitive per-Pod values in plain ConfigMaps instead of Secrets or external secret management.
  • Making the startup script so complex that it becomes harder to debug than an indexed config-file approach.

Summary

  • StatefulSet replicas share one Pod template, so literal env vars are the same for every Pod.
  • Stable Pod identity such as app-0, app-1, and app-2 is the normal source of per-Pod differences.
  • Use the downward API to inject the Pod name and derive the ordinal at startup.
  • For more complex cases, select indexed config files or external configuration by Pod identity.
  • Keep the StatefulSet manifest generic and make per-Pod behavior explicit.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.