kubernetes
environment variables
string operations
devops
container orchestration

String operation on env variables on Kubernetes

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

Kubernetes environment variables support limited string operations natively. You can reference other environment variables using $(VAR_NAME) syntax for simple interpolation, pull values from ConfigMaps and Secrets, and extract pod metadata via the Downward API. However, Kubernetes does not support string manipulation functions (substring, replace, case conversion) directly in pod specs. For advanced string operations, use an init container, an entrypoint shell script, or a tool like envsubst. This article covers what Kubernetes supports natively and how to work around its limitations.

Basic Environment Variable Setting

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: basic-env-pod
5spec:
6  containers:
7    - name: app
8      image: busybox
9      command: ["sh", "-c", "echo $GREETING $TARGET"]
10      env:
11        - name: GREETING
12          value: "Hello"
13        - name: TARGET
14          value: "World"
15# Output: Hello World

Variable Interpolation with $(VAR_NAME)

Kubernetes supports referencing one environment variable inside another using $(VAR_NAME):

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: interpolation-pod
5spec:
6  containers:
7    - name: app
8      image: busybox
9      command: ["sh", "-c", "echo $DATABASE_URL"]
10      env:
11        - name: DB_HOST
12          value: "postgres.default.svc.cluster.local"
13        - name: DB_PORT
14          value: "5432"
15        - name: DB_NAME
16          value: "myapp"
17        - name: DATABASE_URL
18          value: "postgresql://$(DB_HOST):$(DB_PORT)/$(DB_NAME)"
19# Output: postgresql://postgres.default.svc.cluster.local:5432/myapp

Variables must be defined before they are referenced. $(VAR_NAME) is replaced at pod creation time by the kubelet, not at shell runtime.

Escaping Dollar Signs

To use a literal $(...) without interpolation, escape it with $$:

yaml
1env:
2  - name: LITERAL_EXAMPLE
3    value: "$$(NOT_INTERPOLATED)"
4# Result: $(NOT_INTERPOLATED)

Values from ConfigMaps

yaml
1apiVersion: v1
2kind: ConfigMap
3metadata:
4  name: app-config
5data:
6  APP_ENV: "production"
7  LOG_LEVEL: "info"
8  MAX_CONNECTIONS: "100"
9---
10apiVersion: v1
11kind: Pod
12metadata:
13  name: configmap-pod
14spec:
15  containers:
16    - name: app
17      image: myapp:latest
18      env:
19        # Single key from ConfigMap
20        - name: APP_ENV
21          valueFrom:
22            configMapKeyRef:
23              name: app-config
24              key: APP_ENV
25        # Use ConfigMap value in interpolation
26        - name: LOG_PREFIX
27          value: "[$(APP_ENV)]"
28      envFrom:
29        # Load ALL keys from ConfigMap as env vars
30        - configMapRef:
31            name: app-config

Values from Secrets

yaml
1apiVersion: v1
2kind: Secret
3metadata:
4  name: db-credentials
5type: Opaque
6data:
7  DB_USER: YWRtaW4=          # base64 of "admin"
8  DB_PASSWORD: cGFzc3dvcmQ=  # base64 of "password"
9---
10apiVersion: v1
11kind: Pod
12metadata:
13  name: secret-pod
14spec:
15  containers:
16    - name: app
17      image: myapp:latest
18      env:
19        - name: DB_USER
20          valueFrom:
21            secretKeyRef:
22              name: db-credentials
23              key: DB_USER
24        - name: DB_PASSWORD
25          valueFrom:
26            secretKeyRef:
27              name: db-credentials
28              key: DB_PASSWORD
29        - name: DB_CONNECTION
30          value: "postgresql://$(DB_USER):$(DB_PASSWORD)@db:5432/myapp"

Downward API: Pod Metadata as Env Vars

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: downward-api-pod
5  labels:
6    app: myapp
7    version: v2
8spec:
9  containers:
10    - name: app
11      image: busybox
12      command: ["sh", "-c", "env | grep POD"]
13      env:
14        - name: POD_NAME
15          valueFrom:
16            fieldRef:
17              fieldPath: metadata.name
18        - name: POD_NAMESPACE
19          valueFrom:
20            fieldRef:
21              fieldPath: metadata.namespace
22        - name: POD_IP
23          valueFrom:
24            fieldRef:
25              fieldPath: status.podIP
26        - name: NODE_NAME
27          valueFrom:
28            fieldRef:
29              fieldPath: spec.nodeName
30        - name: POD_SERVICE_ACCOUNT
31          valueFrom:
32            fieldRef:
33              fieldPath: spec.serviceAccountName
34        # Combine with interpolation
35        - name: POD_IDENTIFIER
36          value: "$(POD_NAMESPACE)/$(POD_NAME)"

Advanced String Operations via Shell

Kubernetes YAML does not support string functions. For manipulation like substring, case conversion, or search/replace, use the container's shell:

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: shell-string-ops
5spec:
6  containers:
7    - name: app
8      image: busybox
9      command:
10        - sh
11        - -c
12        - |
13          # Uppercase
14          UPPER=$(echo "$APP_ENV" | tr '[:lower:]' '[:upper:]')
15          echo "Uppercase: $UPPER"
16
17          # Substring (first 4 chars)
18          SHORT=$(echo "$POD_NAME" | cut -c1-4)
19          echo "Short name: $SHORT"
20
21          # Replace characters
22          SAFE_NAME=$(echo "$POD_NAME" | tr '-' '_')
23          echo "Safe name: $SAFE_NAME"
24
25          # Default value
26          REGION=${AWS_REGION:-us-east-1}
27          echo "Region: $REGION"
28
29          # Concatenation
30          FULL_TAG="${APP_NAME}-${APP_VERSION}-${BUILD_NUMBER}"
31          echo "Tag: $FULL_TAG"
32      env:
33        - name: APP_ENV
34          value: "production"
35        - name: APP_NAME
36          value: "myapp"
37        - name: APP_VERSION
38          value: "1.2.3"
39        - name: BUILD_NUMBER
40          value: "456"
41        - name: POD_NAME
42          valueFrom:
43            fieldRef:
44              fieldPath: metadata.name

Init Container for Complex Setup

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: init-env-pod
5spec:
6  volumes:
7    - name: env-config
8      emptyDir: {}
9  initContainers:
10    - name: env-setup
11      image: busybox
12      command:
13        - sh
14        - -c
15        - |
16          # Compute derived values and write to shared file
17          echo "export COMPUTED_URL=https://${SERVICE_NAME}.${NAMESPACE}.svc:${PORT}" > /env/computed.sh
18          echo "export SHORT_HASH=$(echo $COMMIT_SHA | cut -c1-7)" >> /env/computed.sh
19      env:
20        - name: SERVICE_NAME
21          value: "api"
22        - name: NAMESPACE
23          valueFrom:
24            fieldRef:
25              fieldPath: metadata.namespace
26        - name: PORT
27          value: "8080"
28        - name: COMMIT_SHA
29          value: "abc123def456789"
30      volumeMounts:
31        - name: env-config
32          mountPath: /env
33  containers:
34    - name: app
35      image: myapp:latest
36      command: ["sh", "-c", "source /env/computed.sh && exec myapp"]
37      volumeMounts:
38        - name: env-config
39          mountPath: /env

Common Pitfalls

  • Referencing a variable before it is defined: $(VAR_NAME) interpolation requires the referenced variable to appear earlier in the env list. If VAR_NAME is not yet defined, the literal string $(VAR_NAME) is used instead without any warning.
  • Expecting shell-style string operations in YAML values: Kubernetes value fields only support $(VAR_NAME) interpolation. Shell constructs like ${VAR:-default}, ${VAR^^}, or ${VAR/old/new} do not work in YAML values — they only work inside a shell command.
  • Mixing $(VAR) (Kubernetes) with $VAR (shell): In a command or args field, $(VAR) is interpolated by Kubernetes at pod creation. $VAR is interpolated by the shell at runtime. Using $(VAR) when you mean shell expansion causes premature substitution with a possibly empty string.
  • ConfigMap changes not propagating to running pods: Environment variables from ConfigMaps are set at pod startup. Updating the ConfigMap does not update the env vars in running pods — you must restart (or recreate) the pod. Use volume-mounted ConfigMaps for live updates.
  • Secrets appearing in pod spec and logs: Environment variable values from Secrets are base64-decoded and injected as plaintext. They appear in kubectl describe pod output and may be logged by the application. For sensitive values, consider volume-mounted Secrets with restrictive file permissions.

Summary

  • Use $(VAR_NAME) for simple string interpolation between environment variables in Kubernetes YAML
  • Pull values from ConfigMaps (configMapKeyRef), Secrets (secretKeyRef), and pod metadata (fieldRef)
  • Kubernetes does not support string manipulation functions in YAML — use shell commands in command for operations like substring, replace, or case conversion
  • Variables must be defined before they are referenced in $(...) interpolation
  • For complex derived values, use an init container that writes computed environment to a shared volume

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.