ConfigMaps

ConfigMaps decouple configuration from container images, making applications portable across environments. They store non-sensitive configuration data as key-value pairs, which can be injected into pods as environment variables, command-line arguments, or files mounted as volumes. This allows you to change configuration without rebuilding container images.

What Are ConfigMaps?

A ConfigMap is a Kubernetes object that stores configuration data in key-value pairs. Instead of hardcoding configuration in container images or command-line arguments, you store it in a ConfigMap and reference it in your pod specifications.

graph TB A[ConfigMap] --> B[Configuration Data] B --> C[Key-Value Pairs] C --> D[Environment Variables] C --> E[Command Arguments] C --> F[Volume Mounts] D --> G[Pod Uses Config] E --> G F --> G style A fill:#e1f5ff style C fill:#fff4e1 style G fill:#e8f5e9

Why Use ConfigMaps?

ConfigMaps provide several benefits:

Separate config from code - Change configuration without rebuilding images
Environment-specific configs - Different ConfigMaps for dev, staging, prod
Reusable configuration - Share ConfigMaps across multiple pods
Version control - ConfigMaps can be versioned and managed like code
Dynamic updates - Update ConfigMaps without recreating pods (with volume mounts)
Portability - Same image works in different environments

ConfigMap vs Secrets

ConfigMaps are for non-sensitive data, Secrets are for sensitive data:

graph TB subgraph configmap[ConfigMap] A[ConfigMap] --> B[Non-Sensitive Data] B --> C[Environment Variables] B --> D[Configuration Files] B --> E[Command Arguments] end subgraph secret[Secret] F[Secret] --> G[Sensitive Data] G --> H[Passwords] G --> I[API Keys] G --> J[TLS Certificates] end style A fill:#e1f5ff style F fill:#ffe1e1 style C fill:#e8f5e9 style H fill:#fff4e1

Use ConfigMaps for:

  • Application configuration files
  • Environment variables
  • Command-line arguments
  • Non-sensitive settings

Use Secrets for:

  • Passwords, tokens, keys
  • TLS certificates
  • Any sensitive data

Creating ConfigMaps

There are several ways to create ConfigMaps:

1. From Literal Values

kubectl create configmap my-config \
  --from-literal=key1=value1 \
  --from-literal=key2=value2 \
  --from-literal=database-url=mysql://localhost:3306/mydb

2. From Files

# From a single file
kubectl create configmap my-config --from-file=config.properties

# From multiple files
kubectl create configmap my-config \
  --from-file=config.properties \
  --from-file=logging.properties

# From a directory
kubectl create configmap my-config --from-file=./config/

3. From YAML

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  key1: value1
  key2: value2
  config.properties: |
    database.host=localhost
    database.port=3306
    logging.level=INFO

Using ConfigMaps in Pods

ConfigMaps can be used in three ways:

1. As Environment Variables

Inject all or specific keys as environment variables:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: app
    image: my-app:latest
    envFrom:
    - configMapRef:
        name: my-config
    # Or specify individual keys
    env:
    - name: DATABASE_URL
      valueFrom:
        configMapKeyRef:
          name: my-config
          key: database-url

2. As Command Arguments

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: app
    image: my-app:latest
    command: ["/bin/sh"]
    args:
    - -c
    - echo $(DATABASE_URL)
    env:
    - name: DATABASE_URL
      valueFrom:
        configMapKeyRef:
          name: my-config
          key: database-url

3. As Volume Mounts

Mount ConfigMap data as files in the container:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: app
    image: my-app:latest
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: my-config

ConfigMap Volume Mounts

When mounted as a volume, ConfigMap keys become filenames, and values become file contents:

graph LR A[ConfigMap] --> B[key1: value1] A --> C[key2: value2] A --> D[config.properties: content] B --> E[/etc/config/key1] C --> F[/etc/config/key2] D --> G[/etc/config/config.properties] style A fill:#e1f5ff style E fill:#fff4e1 style F fill:#fff4e1 style G fill:#fff4e1

Mounting Specific Keys

Mount only specific keys from a ConfigMap:

volumes:
- name: config-volume
  configMap:
    name: my-config
    items:
    - key: config.properties
      path: app.properties
    - key: key1
      path: settings/key1

Setting File Permissions

volumes:
- name: config-volume
  configMap:
    name: my-config
    defaultMode: 0644  # File permissions

ConfigMap Updates and Reloading

Environment Variables

When ConfigMaps are used as environment variables, pods must be restarted to pick up changes. Environment variables are injected at pod startup and don’t update automatically.

Volume Mounts

When ConfigMaps are mounted as volumes, they update automatically, but:

  • Updates may take up to the kubelet sync period (default: 1 minute)
  • Applications may need to watch for file changes or periodically reload
  • Some applications detect file changes automatically (e.g., nginx reloads when config changes)
graph TD A[Update ConfigMap] --> B[Kubelet Syncs] B --> C[Volume Updated] C --> D{Application Behavior} D -->|Auto-Reload| E[Application Reloads Config] D -->|Manual Reload| F[Restart Pod or Signal App] style A fill:#e1f5ff style C fill:#fff4e1 style E fill:#e8f5e9

ConfigMap Lifecycle

graph TD A[ConfigMap Created] --> B[ConfigMap Active] B --> C[Referenced by Pod] C --> D[Data Available in Pod] E[ConfigMap Updated] --> F{Usage Type} F -->|Volume Mount| G[Auto-Updated in Pod] F -->|Environment Var| H[Requires Pod Restart] I[ConfigMap Deleted] --> J{Referenced by Pods?} J -->|Yes| K[Pods Continue Using Old Data] J -->|No| L[ConfigMap Removed] style A fill:#e1f5ff style D fill:#e8f5e9 style G fill:#fff4e1 style H fill:#ffe1e1

Common Use Cases

1. Application Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  app.properties: |
    server.port=8080
    logging.level=INFO
    feature.flag.enabled=true
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-app:latest
        volumeMounts:
        - name: config
          mountPath: /etc/app
      volumes:
      - name: config
        configMap:
          name: app-config

2. Environment-Specific Configuration

# Development
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: dev
data:
  environment: development
  api.url: http://api-dev.example.com
  log.level: DEBUG

# Production
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: prod
data:
  environment: production
  api.url: https://api.example.com
  log.level: INFO

3. Nginx Configuration

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx.conf: |
    server {
        listen 80;
        server_name example.com;
        location / {
            proxy_pass http://backend:8080;
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        volumeMounts:
        - name: config
          mountPath: /etc/nginx/conf.d
      volumes:
      - name: config
        configMap:
          name: nginx-config

4. Multiple ConfigMaps

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: app
    image: my-app:latest
    envFrom:
    - configMapRef:
        name: app-config
    - configMapRef:
        name: db-config
    volumeMounts:
    - name: app-config
      mountPath: /etc/app
    - name: log-config
      mountPath: /etc/logging
  volumes:
  - name: app-config
    configMap:
      name: app-config
  - name: log-config
    configMap:
      name: log-config

Best Practices

  1. Use ConfigMaps for non-sensitive data - Use Secrets for sensitive information

  2. Keep ConfigMaps small - ConfigMaps have a 1 MiB size limit

  3. Use meaningful names - Clear, descriptive ConfigMap names

  4. Version your ConfigMaps - Include version in name or use labels

metadata:
  name: app-config-v1
  labels:
    version: "1"
  1. Use namespaces - Organize ConfigMaps with namespaces

  2. Document ConfigMap structure - Use annotations to document keys

metadata:
  annotations:
    description: "Application configuration for production environment"
  1. Handle missing ConfigMaps - Use optional: true if ConfigMap might not exist
envFrom:
- configMapRef:
    name: optional-config
    optional: true
  1. Use volume mounts for files - Better for configuration files than env vars

  2. Test ConfigMap updates - Verify applications handle updates correctly

  3. Avoid hardcoded defaults in images - Use ConfigMaps for all configuration

  4. Use immutable ConfigMaps - For configuration that never changes (Kubernetes 1.19+)

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
immutable: true
data:
  # ...

Immutable ConfigMaps improve performance and prevent accidental updates.

Common Operations

Create ConfigMap

# From literal
kubectl create configmap my-config --from-literal=key=value

# From file
kubectl create configmap my-config --from-file=config.properties

# From YAML
kubectl create -f configmap.yaml

View ConfigMap

# List ConfigMaps
kubectl get configmaps
kubectl get cm

# View ConfigMap data
kubectl get configmap my-config -o yaml

# View specific key
kubectl get configmap my-config -o jsonpath='{.data.key}'

Update ConfigMap

# Edit ConfigMap
kubectl edit configmap my-config

# Update from file
kubectl create configmap my-config --from-file=config.properties --dry-run=client -o yaml | kubectl apply -f -

# Patch ConfigMap
kubectl patch configmap my-config -p '{"data":{"key":"new-value"}}'

Delete ConfigMap

kubectl delete configmap my-config

Troubleshooting

ConfigMap Not Found

# Verify ConfigMap exists
kubectl get configmap my-config

# Check namespace
kubectl get configmap my-config -n <namespace>

# Check pod references
kubectl describe pod my-pod | grep -A 10 "Environment\|Mounts"

Values Not Updating

# Check if using volume mount (auto-updates) or env var (requires restart)
kubectl get pod my-pod -o yaml | grep -A 5 "volumeMounts\|env"

# For env vars, restart the pod
kubectl rollout restart deployment my-deployment

# For volume mounts, check kubelet sync
kubectl describe pod my-pod | grep "Events"

ConfigMap Too Large

# Check ConfigMap size
kubectl get configmap my-config -o yaml | wc -c

# ConfigMaps have 1 MiB limit
# Consider splitting into multiple ConfigMaps

See Also

  • Secrets - For sensitive configuration data
  • Deployments - Using ConfigMaps with Deployments
  • Volumes - Understanding volume mounts