ConfigMaps and Secrets: Managing Configuration in Kubernetes
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
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.
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.
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
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro