07: ConfigMaps

07: ConfigMaps

Objective

  • Understand what ConfigMaps are and when to use them
  • Learn three ways to create ConfigMaps (YAML, --from-literal, --from-file)
  • Use ConfigMaps as environment variables (configMapKeyRef and envFrom)
  • Mount ConfigMaps as files in a volume
  • Master the dry-run export pattern for generating YAML

Theory

What is a ConfigMap?

A ConfigMap is a Kubernetes API object that stores non-confidential configuration data as key-value pairs. It decouples configuration from container images, so you can change settings without rebuilding images.

ConfigMap data can be:

  • Simple key-value strings (e.g., LOG_LEVEL=debug)
  • Entire configuration files (e.g., nginx.conf, app.properties)

Three Ways to Create a ConfigMap

Method Best For
YAML manifest Version-controlled, declarative configuration
--from-literal Quick creation of simple key-value pairs from the CLI
--from-file Loading configuration files directly

Two Usage Modes

graph TB
    CM[ConfigMap]

    CM --> ENV["As Environment Variables<br/>injected at container startup"]
    CM --> VOL["As Volume Mount<br/>files appear in container filesystem"]

    ENV --> E1["configMapKeyRef<br/>(single key)"]
    ENV --> E2["envFrom<br/>(all keys at once)"]

    VOL --> V1["Each key becomes a file"]
    VOL --> V2["File content = value"]

When to Use Env Vars vs Volume Mount

flowchart TD
    START["How will your app consume the config?"] --> Q1{"Is it a simple<br/>key-value pair?"}
    Q1 -->|Yes| Q2{"Does the app read<br/>environment variables?"}
    Q1 -->|No, it is a<br/>config file| VOL["Use Volume Mount"]
    Q2 -->|Yes| ENV["Use Environment Variables"]
    Q2 -->|No, it reads<br/>from a file path| VOL

    ENV --> N1["Simpler setup<br/>Values set at startup<br/>No live reload"]
    VOL --> N2["Files appear in container<br/>Can be multi-line content<br/>Supports live reload"]

Key Points

  • ConfigMaps are namespace-scoped — they must be in the same namespace as the Pod that uses them.
  • Maximum size of a ConfigMap is 1 MiB.
  • When mounted as a volume, Kubernetes can update the files automatically when the ConfigMap changes (with a delay of up to 60 seconds). Environment variables are not updated.
  • ConfigMaps are not encrypted — do not store passwords or secrets in them. Use Secrets instead (Exercise 08).

Practical Tasks

Task 1: Create a ConfigMap — YAML and CLI

Option A: Create from YAML

Create the file configmap-app.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: student-XX
data:
  ENVIRONMENT: "staging"
  LOG_LEVEL: "debug"
  MAX_CONNECTIONS: "100"
kubectl apply -f configmap-app.yaml

Option B: Create from CLI with --from-literal

kubectl create configmap app-config-cli \
  --from-literal=ENVIRONMENT=staging \
  --from-literal=LOG_LEVEL=debug \
  --from-literal=MAX_CONNECTIONS=100 \
  -n student-XX

Option C: Create from a file

Create a file called app.properties:

database.host=db.internal
database.port=5432
database.pool.size=10
kubectl create configmap app-config-file --from-file=app.properties -n student-XX

Inspect the results:

# List ConfigMaps
kubectl get configmap -n student-XX

# View details
kubectl describe configmap app-config -n student-XX

# View as YAML
kubectl get configmap app-config -o yaml -n student-XX

# View the file-based ConfigMap
kubectl get configmap app-config-file -o yaml -n student-XX

Notice how --from-file creates a single key (the filename) with the entire file content as the value, while --from-literal creates individual keys.

Clean up the CLI-created ConfigMaps (keep app-config for the next task):

kubectl delete configmap app-config-cli app-config-file -n student-XX

Task 2: Use ConfigMap as Environment Variables

Using configMapKeyRef (select specific keys)

Create the file pod-env-configmap.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: pod-env-configmap
  namespace: student-XX
spec:
  containers:
    - name: app
      image: busybox
      command: ["sh", "-c", "echo ENVIRONMENT=$ENVIRONMENT LOG_LEVEL=$LOG_LEVEL && sleep 3600"]
      env:
        - name: ENVIRONMENT
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: ENVIRONMENT
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: LOG_LEVEL
  restartPolicy: Never
kubectl apply -f pod-env-configmap.yaml
kubectl logs pod-env-configmap -n student-XX

Expected output:

ENVIRONMENT=staging LOG_LEVEL=debug

Using envFrom (inject all keys at once)

Create the file pod-envfrom-configmap.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: pod-envfrom-configmap
  namespace: student-XX
spec:
  containers:
    - name: app
      image: busybox
      command: ["sh", "-c", "env | sort && sleep 3600"]
      envFrom:
        - configMapRef:
            name: app-config
  restartPolicy: Never
kubectl apply -f pod-envfrom-configmap.yaml
kubectl logs pod-envfrom-configmap -n student-XX | grep -E "ENVIRONMENT|LOG_LEVEL|MAX_CONNECTIONS"

Expected output:

ENVIRONMENT=staging
LOG_LEVEL=debug
MAX_CONNECTIONS=100

All three keys from the ConfigMap are injected automatically without listing them individually.

Clean up:

kubectl delete pod pod-env-configmap pod-envfrom-configmap -n student-XX

Task 3: Mount ConfigMap as a Volume

When a ConfigMap is mounted as a volume, each key becomes a file in the mount path.

Create a ConfigMap with a configuration file:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: student-XX
data:
  nginx.conf: |
    server {
        listen 80;
        server_name localhost;
        location / {
            return 200 'Hello from ConfigMap!\n';
        }
    }
  settings.json: |
    {
      "debug": true,
      "version": "1.0"
    }
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: student-XX
data:
  nginx.conf: |
    server {
        listen 80;
        server_name localhost;
        location / {
            return 200 'Hello from ConfigMap!\n';
        }
    }
  settings.json: |
    {
      "debug": true,
      "version": "1.0"
    }
EOF

Create the file pod-volume-configmap.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: pod-volume-configmap
  namespace: student-XX
spec:
  containers:
    - name: app
      image: busybox
      command: ["sh", "-c", "ls -la /etc/config/ && echo '--- nginx.conf ---' && cat /etc/config/nginx.conf && echo '--- settings.json ---' && cat /etc/config/settings.json && sleep 3600"]
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
          readOnly: true
  volumes:
    - name: config-volume
      configMap:
        name: nginx-config
  restartPolicy: Never
kubectl apply -f pod-volume-configmap.yaml
kubectl logs pod-volume-configmap -n student-XX

Expected output:

total 0
lrwxrwxrwx    1 root     root            17 ... nginx.conf -> ..data/nginx.conf
lrwxrwxrwx    1 root     root            20 ... settings.json -> ..data/settings.json
--- nginx.conf ---
server {
    listen 80;
    server_name localhost;
    location / {
        return 200 'Hello from ConfigMap!\n';
    }
}
--- settings.json ---
{
  "debug": true,
  "version": "1.0"
}

Notice how each key in the ConfigMap became a file in the /etc/config/ directory. The files are symlinks managed by Kubernetes.

Verify with exec:

kubectl exec pod-volume-configmap -n student-XX -- ls /etc/config/
kubectl exec pod-volume-configmap -n student-XX -- cat /etc/config/settings.json

Clean up:

kubectl delete pod pod-volume-configmap -n student-XX
kubectl delete configmap nginx-config -n student-XX

Task 4: Dry-Run Export Pattern

The --dry-run=client -o yaml pattern lets you generate YAML manifests from CLI commands without actually creating resources. This is useful for creating templates.

# Generate ConfigMap YAML from literals
kubectl create configmap my-config \
  --from-literal=DB_HOST=postgres.default.svc \
  --from-literal=DB_PORT=5432 \
  -n student-XX \
  --dry-run=client -o yaml

Output:

apiVersion: v1
data:
  DB_HOST: postgres.default.svc
  DB_PORT: "5432"
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: my-config
  namespace: student-XX

Save it to a file:

kubectl create configmap my-config \
  --from-literal=DB_HOST=postgres.default.svc \
  --from-literal=DB_PORT=5432 \
  -n student-XX \
  --dry-run=client -o yaml > my-config.yaml

This is the recommended pattern for generating YAML scaffolds that you can then customize and commit to version control.

Clean up all remaining resources:

kubectl delete configmap app-config --ignore-not-found -n student-XX

Common Problems

Problem Cause Solution
Pod stuck in CreateContainerConfigError Referenced ConfigMap does not exist Create the ConfigMap before the Pod, or check the name
Env var not updating after ConfigMap change Env vars are set at container startup only Delete and recreate the Pod
Volume mount replaces entire directory ConfigMap volume overwrites the target directory Use subPath to mount individual files without replacing the directory
Key name contains dots (e.g., app.properties) Dots are valid in ConfigMap keys but invalid as env var names Use volume mount instead of envFrom, or rename the key

Best Practices

  1. Use YAML manifests for production — Keep ConfigMaps in version control alongside your Deployment manifests.
  2. Use envFrom for simple key-value configs — Avoids repetitive configMapKeyRef entries.
  3. Use volumes for configuration files — When your app reads from a file path (e.g., nginx.conf), mount the ConfigMap as a volume.
  4. Set readOnly: true on volume mounts — Prevents accidental writes from inside the container.
  5. Name ConfigMaps descriptively — Include the application or component name (e.g., frontend-config, nginx-config).
  6. Use dry-run to generate YAML — Always use --dry-run=client -o yaml to scaffold manifests instead of writing them from scratch.

Summary

In this exercise you learned how to:

  • Create ConfigMaps using YAML manifests, --from-literal, and --from-file
  • Inject ConfigMap values as environment variables using configMapKeyRef and envFrom
  • Mount ConfigMaps as files in a container using volume mounts
  • Use the --dry-run=client -o yaml pattern to generate ConfigMap YAML

Proceed to Exercise 08 to learn about Kubernetes Secrets for sensitive data.

results matching ""

    No results matching ""