Skip to content

ConfigMaps and Secrets: Managing Configuration in Kubernetes

DodaTech 5 min read

In this tutorial, you'll learn about ConfigMaps and Secrets: Managing Configuration in Kubernetes. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

ConfigMaps and Secrets are Kubernetes resources that decouple configuration from container images, allowing the same deployment to run across environments with different settings and credentials.

What You'll Learn

This tutorial covers creating and consuming ConfigMaps and Secrets, injecting configuration as environment variables and volumes, managing sensitive data with encryption, and following security best practices for secret rotation.

Why It Matters

Hardcoding configuration in container images forces rebuilds for every environment change. Secrets stored in plaintext or committed to git repositories create security vulnerabilities that can lead to data breaches and Compliance violations.

Real-World Use

Airbnb uses ConfigMaps to manage per-region configuration for their booking platform, enabling different feature flags and service endpoints across US, EU, and APAC deployments without rebuilding images. Spotify rotates database Secrets every 90 minutes using external secret operators integrated with HashiCorp Vault.

graph LR
  A[Pod] --> B[ConfigMap: env vars]
  A --> C[ConfigMap: volume mount]
  D[Pod] --> E[Secret: env vars]
  D --> F[Secret: volume mount]
  B --> G[Non-sensitive config]
  E --> H[Sensitive credentials]

Expected output: diagram showing pods consuming ConfigMaps and Secrets via environment variables and volume mounts.

ConfigMaps

ConfigMaps store non-sensitive data as key-value pairs or structured files.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: production
  LOG_LEVEL: info
  API_TIMEOUT: "30"
  nginx.conf: |
    server {
      listen 80;
      server_name example.com;
    }
# Create ConfigMap from literal values
kubectl create configmap app-config \
  --from-literal=APP_ENV=production \
  --from-literal=LOG_LEVEL=info

# Create ConfigMap from a file
kubectl create configmap nginx-config --from-file=nginx.conf

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

Expected output: the ConfigMap YAML shows all key-value pairs in the data section.

Consuming ConfigMaps as Environment Variables

apiVersion: v1
kind: Pod
metadata:
  name: config-demo
spec:
  containers:
  - name: app
    image: myapp:1.0
    envFrom:
    - configMapRef:
        name: app-config
    env:
    - name: DB_HOST
      valueFrom:
        configMapKeyRef:
          name: db-config
          key: host

Consuming ConfigMaps as Volumes

apiVersion: v1
kind: Pod
metadata:
  name: config-volume-demo
spec:
  containers:
  - name: app
    image: nginx:1.25
    volumeMounts:
    - name: config
      mountPath: /etc/nginx/conf.d
      readOnly: true
  volumes:
  - name: config
    configMap:
      name: nginx-config
# Verify mounted configuration
kubectl exec config-volume-demo -- ls /etc/nginx/conf.d

# Check the content
kubectl exec config-volume-demo -- cat /etc/nginx/conf.d/nginx.conf

Expected output: the nginx.conf file is mounted at /etc/nginx/conf.d with the exact content defined in the ConfigMap.

Secrets

Secrets store sensitive data like passwords, API keys, and TLS certificates. Values must be base64-encoded.

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  username: ZGJfYWRtaW4=
  password: U3VwZXJTZWNyZXQhMjAyNA==
# Create Secret from literal values (Kubernetes encodes automatically)
kubectl create secret generic db-secret \
  --from-literal=username=db_admin \
  --from-literal=password=SuperSecret!2024

# View encoded Secret
kubectl get secret db-secret -o yaml

# Decode a Secret value
kubectl get secret db-secret -o jsonpath="{.data.password}" | base64 -d

Expected output: the decoded password is "SuperSecret!2024". The YAML shows base64-encoded values.

Consuming Secrets as Environment Variables

apiVersion: v1
kind: Pod
metadata:
  name: secret-demo
spec:
  containers:
  - name: app
    image: myapp:1.0
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: password

Consuming Secrets as Volumes

apiVersion: v1
kind: Pod
metadata:
  name: secret-volume-demo
spec:
  containers:
  - name: app
    image: myapp:1.0
    volumeMounts:
    - name: certs
      mountPath: /etc/tls
      readOnly: true
  volumes:
  - name: certs
    secret:
      secretName: tls-cert
# Verify mounted secrets
kubectl exec secret-volume-demo -- ls -la /etc/tls/

# Each secret key becomes a file
kubectl exec secret-volume-demo -- cat /etc/tls/tls.crt

Expected output: each key in the Secret appears as a file in the mount directory containing the decoded value.

Encryption at Rest

Enable encryption at rest for Secrets stored in etcd.

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: c2VjcmV0LWZvci1lbmNyeXB0aW9uLWV0Y2Q=
  - identity: {}
# Apply encryption configuration to API server
# Edit the API server manifest to include --encryption-provider-config
# Then restart the API server

Kubernetes encryption at rest ensures that even if etcd is compromised, Secret data remains protected. Combine this with Cloud Computing KMS providers for key management.

External Secret Operators

Tools like External Secrets Operator and Sealed Secrets sync secrets from external providers into Kubernetes.

# Install External Secrets Operator
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets

# Create a SecretStore referencing AWS Secrets Manager
kubectl apply -f secretstore.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: database-secret
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secret-store
    kind: SecretStore
  target:
    name: db-secret
  data:
  - secretKey: password
    remoteRef:
      key: /production/database/password

Practice Questions

  1. What is the size limit for ConfigMap and Secret data? Kubernetes limits ConfigMaps and Secrets to 1 MiB each. For larger configuration, mount files from a volume or use a database.

  2. How do you ensure Secrets are not stored in etcd in plaintext? Enable encryption at rest with an EncryptionConfiguration resource that specifies aescbc or kms provider.

  3. What happens when a mounted ConfigMap is updated? Mounted files are updated automatically after a delay (controlled by the kubelet sync period, typically 60-90 seconds). Environment variables are not updated; you must restart the pod.

Frequently Asked Questions

Should I use Secrets or ConfigMaps for configuration?

Use ConfigMaps for non-sensitive data like environment names, log levels, and feature flags. Use Secrets for any data that should be kept confidential -- passwords, API keys, tokens, certificates. Secrets support encryption at rest, integration with KMS providers, and audit logging that ConfigMaps do not.

How do I rotate Secrets without restarting pods?

Mount Secrets as volumes rather than environment variables. When the Secret is updated, the mounted files eventually sync to the pod. Most applications can watch for file changes and reload configuration. For immediate rotation, use tools like Reloader that detect Secret changes and trigger rolling restarts of the associated Deployment.

Are Secrets really secure just because they are base64-encoded?

No. Base64 encoding is not encryption -- it is simple encoding that anyone can reverse. Anyone with access to the cluster -- through kubectl, the API server, or etcd -- can read Secrets. Real security requires encryption at rest for etcd, RBAC to limit Secret access, and external secret management for production-grade security.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro