Never hardcode configuration or secrets inside your container image. Kubernetes provides two objects for this:
- ConfigMap — non-sensitive config (URLs, settings, feature flags)
- Secret — sensitive data (passwords, API keys, TLS certificates)
Both can be consumed in two ways:
- Environment variables — inject as env vars
- Volume mounts — mount as files inside container
Create a ConfigMap
# Method 1: From literal values
kubectl create configmap app-config \
--from-literal=APP_ENV=production \
--from-literal=LOG_LEVEL=info \
--from-literal=MAX_CONNECTIONS=100
# Method 2: View what was created
kubectl get configmap app-config -o yaml
# Method 3: YAML manifest (recommended — version controlled)
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
APP_ENV: "production"
LOG_LEVEL: "info"
DB_POOL_SIZE: "10"
# Multi-line config file
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://localhost:3000;
}
}
kubectl apply -f configmap.yaml
kubectl describe configmap app-config
Use ConfigMap as Environment Variables
spec:
containers:
- name: myapp
image: myapp:latest
# Inject ALL keys as env vars
envFrom:
- configMapRef:
name: app-config
# Or inject specific key only
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
# Verify inside container
kubectl exec pod-name -- env | grep APP_ENV
# APP_ENV=production
Mount ConfigMap as File
Great for config files like nginx.conf, application.yaml:
spec:
volumes:
- name: config-volume
configMap:
name: app-config
containers:
- name: myapp
volumeMounts:
# Mount specific key as specific file
- name: config-volume
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
# Mount all keys as directory
- name: config-volume
mountPath: /etc/config
# Verify file is mounted
kubectl exec pod-name -- cat /etc/nginx/nginx.conf
Auto-updates when ConfigMap changes within ~1 minute!
(Environment variables do NOT auto-update — need pod restart)
Create Secrets
# Method 1: kubectl create (auto base64 encodes values)
kubectl create secret generic db-credentials \
--from-literal=DB_PASSWORD=supersecret123 \
--from-literal=DB_USER=myapp
# View secret (values are base64 encoded)
kubectl get secret db-credentials -o yaml
# Decode a value
kubectl get secret db-credentials \
-o jsonpath="{.data.DB_PASSWORD}" | base64 -d
# Output: supersecret123
# YAML manifest — encode values yourself first
# echo -n "supersecret123" | base64
# Output: c3VwZXJzZWNyZXQxMjM=
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
DB_PASSWORD: c3VwZXJzZWNyZXQxMjM=
DB_USER: bXlhcHA=
Use Secrets in Pods
spec:
containers:
- name: myapp
# As environment variables
envFrom:
- secretRef:
name: db-credentials
# Or specific key
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_PASSWORD
# As volume mount (MORE SECURE — not in process list)
spec:
volumes:
- name: secrets-vol
secret:
secretName: db-credentials
defaultMode: 0400 # Read-only, owner only!
containers:
- name: myapp
volumeMounts:
- name: secrets-vol
mountPath: /etc/secrets
readOnly: true
# Files created:
# /etc/secrets/DB_PASSWORD
# /etc/secrets/DB_USER
Important: Secrets Are NOT Truly Secret By Default
Kubernetes Secrets are only base64 encoded in etcd — not encrypted!
Anyone with etcd access can read them.
Production solution — External Secrets Operator:
# Install External Secrets Operator
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets
# Sync from AWS Secrets Manager automatically
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secretsmanager
kind: ClusterSecretStore
target:
name: db-credentials # K8s secret created automatically
data:
- secretKey: DB_PASSWORD
remoteRef:
key: production/myapp/db
property: password
ConfigMap vs Secret — When to Use What
| Use Case | Use |
|---|---|
| App settings, URLs, flags | ConfigMap |
| Database passwords | Secret |
| API keys, tokens | Secret |
| TLS certificates | Secret (type: tls) |
| Config files (nginx.conf) | ConfigMap volume mount |
| Dynamic config updates | ConfigMap volume mount |
| Production secrets | External Secrets Operator |
Quick Reference Commands
# ConfigMap
kubectl create configmap name --from-literal=key=value
kubectl get configmaps
kubectl describe configmap name
kubectl edit configmap name
# Secret
kubectl create secret generic name --from-literal=key=value
kubectl get secrets
kubectl describe secret name
kubectl get secret name -o jsonpath="{.data.key}" | base64 -d
# Delete
kubectl delete configmap name
kubectl delete secret name
Practice Kubernetes Interview Questions
535+ real DevOps interview questions — Kubernetes, Docker, AWS, Terraform and more.
Completely free at devopsrise.vercel.app
No login required. Bookmark questions. Download PDF.
Top comments (0)