Skip to content

Secrets & ConfigMaps – Complete Guide

Store configuration and sensitive data separately from container images.


1. ConfigMap vs Secret

AspectConfigMapSecret
Data typeNon-sensitive configSensitive data
EncodingPlain textBase64 encoded
Use caseApp settings, config filesPasswords, tokens, keys
Size limit1 MB1 MB

2. ConfigMap

Create from Literal

bash
kubectl create configmap app-config \
  --from-literal=APP_ENV=production \
  --from-literal=LOG_LEVEL=info

Create from File

bash
# Single file
kubectl create configmap nginx-config --from-file=nginx.conf

# Directory (all files)
kubectl create configmap configs --from-file=./config-dir/

# With custom key name
kubectl create configmap app-config --from-file=myconfig=config.properties

Create from YAML

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: production
  LOG_LEVEL: info
  config.json: |
    {
      "database": "mysql",
      "port": 3306
    }

3. Secret

Types of Secrets

TypeUse Case
OpaqueGeneric (default)
kubernetes.io/tlsTLS certificates
kubernetes.io/dockerconfigjsonDocker registry auth
kubernetes.io/basic-authBasic authentication
kubernetes.io/ssh-authSSH private keys

Create Generic Secret

bash
# From literal (auto base64 encodes)
kubectl create secret generic db-secret \
  --from-literal=username=admin \
  --from-literal=password=secret123

# From file
kubectl create secret generic tls-secret \
  --from-file=tls.crt --from-file=tls.key

Create TLS Secret

bash
kubectl create secret tls my-tls \
  --cert=tls.crt \
  --key=tls.key

Create Docker Registry Secret

bash
kubectl create secret docker-registry regcred \
  --docker-server=docker.io \
  --docker-username=user \
  --docker-password=pass \
  --docker-email=email@example.com

Create from YAML (manual base64)

yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  username: YWRtaW4=      # echo -n 'admin' | base64
  password: c2VjcmV0MTIz  # echo -n 'secret123' | base64

Using stringData (auto-encode)

yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:
  username: admin      # Plain text, auto base64 encoded
  password: secret123

4. Use in Pods

As Environment Variables

All keys from ConfigMap:

yaml
spec:
  containers:
  - name: app
    image: nginx
    envFrom:
    - configMapRef:
        name: app-config

All keys from Secret:

yaml
spec:
  containers:
  - name: app
    image: nginx
    envFrom:
    - secretRef:
        name: db-secret

Specific keys:

yaml
spec:
  containers:
  - name: app
    image: nginx
    env:
    - name: DATABASE_USER
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: username
    - name: APP_MODE
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: APP_ENV

As Volume Mount

Mount entire ConfigMap:

yaml
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: app-config

Mount entire Secret:

yaml
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: db-secret

Mount specific keys:

yaml
volumes:
- name: config-volume
  configMap:
    name: app-config
    items:
    - key: config.json
      path: app-config.json  # Mounted as /etc/config/app-config.json

Mount with permissions:

yaml
volumes:
- name: secret-volume
  secret:
    secretName: db-secret
    defaultMode: 0400  # Read-only for owner

SubPath Mount (don't overwrite directory)

yaml
volumeMounts:
- name: config-volume
  mountPath: /etc/nginx/nginx.conf
  subPath: nginx.conf

5. Commands Reference

ConfigMap

bash
# Create
kubectl create configmap <name> --from-literal=key=value
kubectl create configmap <name> --from-file=<file>
kubectl create configmap <name> --from-file=<dir>

# View
kubectl get configmap
kubectl describe configmap <name>
kubectl get configmap <name> -o yaml

# Edit
kubectl edit configmap <name>

# Delete
kubectl delete configmap <name>

Secret

bash
# Create
kubectl create secret generic <name> --from-literal=key=value
kubectl create secret generic <name> --from-file=<file>
kubectl create secret tls <name> --cert=<cert> --key=<key>
kubectl create secret docker-registry <name> --docker-server=...

# View
kubectl get secret
kubectl describe secret <name>
kubectl get secret <name> -o yaml

# Decode secret value
kubectl get secret <name> -o jsonpath='{.data.password}' | base64 -d

# Edit
kubectl edit secret <name>

6. Patching

Patch ConfigMap

bash
# Add/update key
kubectl patch configmap app-config -p '{"data":{"NEW_KEY":"new_value"}}'

# Using JSON merge patch
kubectl patch configmap app-config --type merge -p '{"data":{"APP_ENV":"staging"}}'

Patch Secret

bash
# Add/update key (must be base64)
kubectl patch secret db-secret -p '{"data":{"newkey":"bmV3dmFsdWU="}}'

# Using stringData (plain text)
kubectl patch secret db-secret --type merge -p '{"stringData":{"newkey":"newvalue"}}'

7. Immutable ConfigMaps and Secrets

Prevent accidental changes (K8s 1.21+):

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
immutable: true
data:
  APP_ENV: production

Note: Immutable objects cannot be changed; must delete and recreate.


8. Hot Reload

Mount TypeUpdate Behavior
Environment variablesNO auto-reload (Pod restart needed)
Volume mountYES auto-reload (~1 min delay)
SubPath mountNO auto-reload

9. Complete Examples

Example 1: App with ConfigMap and Secret

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: production
  LOG_LEVEL: debug
---
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:
  DB_USER: admin
  DB_PASS: secret123
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: app
    image: nginx
    envFrom:
    - configMapRef:
        name: app-config
    - secretRef:
        name: db-secret

Example 2: Mount Config File

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx.conf: |
    server {
      listen 80;
      server_name localhost;
      location / {
        root /usr/share/nginx/html;
      }
    }
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: config
      mountPath: /etc/nginx/conf.d
  volumes:
  - name: config
    configMap:
      name: nginx-config

10. CKA Exam Tips

  1. kubectl create is fastest for creating ConfigMaps/Secrets
  2. stringData avoids manual base64 encoding
  3. envFrom loads all keys at once
  4. Volume mounts auto-update, env vars don't
  5. Decode secrets: kubectl get secret <name> -o jsonpath='{.data.key}' | base64 -d
  6. Check mounted data: kubectl exec <pod> -- cat /path/to/mounted/file

Released under the MIT License.