Kubernetes ConfigMaps and Secrets Managing App Settings
Every application needs configuration — database hostnames, feature flags, API endpoints, and credentials. Hardcoding these values inside your container image is a bad idea because you would need a different image for each environment. ConfigMaps and Secrets let you store configuration separately from your application code and inject it at runtime.
The Core Idea: Separate Config from Code
Think of a hotel room minibar menu. The menu (configuration) is separate from the food items (your application). The hotel changes prices on the menu without replacing the food. You change ConfigMaps without rebuilding the container image.
Container Image (code) + ConfigMap (settings) = Running Application
Same image Different per env Different behavior
ConfigMaps: Non-Sensitive Configuration
A ConfigMap stores plain-text, non-sensitive configuration data as key-value pairs. Use it for settings like database hostnames, log levels, feature toggle flags, or API endpoint URLs.
Creating a ConfigMap from Literal Values
kubectl create configmap app-config \ --from-literal=LOG_LEVEL=info \ --from-literal=DB_HOST=mysql.default.svc.cluster.local \ --from-literal=MAX_CONNECTIONS=50
Creating a ConfigMap from a YAML File
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
LOG_LEVEL: "info"
DB_HOST: "mysql.default.svc.cluster.local"
MAX_CONNECTIONS: "50"
app.properties: |
feature.dark-mode=true
feature.beta-signup=false
ConfigMaps can hold individual key-value pairs or entire file contents (like properties files or configuration JSON).
Using ConfigMaps in Pods
You can inject ConfigMap data into a Pod in two ways: as environment variables or as files mounted into the container filesystem.
Method 1: Environment Variables
spec:
containers:
- name: app
image: my-app:v1
envFrom:
- configMapRef:
name: app-config
This injects every key from the ConfigMap as an environment variable. Your app reads LOG_LEVEL, DB_HOST, and MAX_CONNECTIONS as environment variables.
Method 2: Volume Mount (File-Based)
spec:
volumes:
- name: config-volume
configMap:
name: app-config
containers:
- name: app
image: my-app:v1
volumeMounts:
- name: config-volume
mountPath: /etc/config
Each key in the ConfigMap becomes a file under /etc/config/. The file's content is the key's value. Your app reads configuration by reading files — useful for apps that expect config files rather than environment variables.
Secrets: Sensitive Data
Secrets work exactly like ConfigMaps but store sensitive data — passwords, API keys, TLS certificates, SSH keys. Kubernetes stores Secrets as base64-encoded strings (not encrypted by default, but the encoding prevents accidental exposure in logs).
Base64 encoding is not encryption. Anyone with access to the Secret object can decode the value. Combine Secrets with RBAC to control who can read them, and use external secret managers (like HashiCorp Vault or AWS Secrets Manager) for higher security requirements.
Creating a Secret
kubectl create secret generic db-credentials \ --from-literal=DB_USER=admin \ --from-literal=DB_PASSWORD=SuperSecretPass123
Secret YAML (values must be base64-encoded)
apiVersion: v1 kind: Secret metadata: name: db-credentials type: Opaque data: DB_USER: YWRtaW4= # base64 of "admin" DB_PASSWORD: U3VwZXJTZWNyZXRQYXNzMTIz # base64 of password
To generate base64 encoding in your terminal:
echo -n "admin" | base64 # Output: YWRtaW4=
Using Secrets as Environment Variables
spec:
containers:
- name: app
image: my-app:v1
env:
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_USER
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_PASSWORD
Using Secrets as Mounted Files
spec:
volumes:
- name: secret-volume
secret:
secretName: db-credentials
containers:
- name: app
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
The password file appears at /etc/secrets/DB_PASSWORD with restricted permissions. Applications that handle TLS certificates use this pattern frequently.
ConfigMap vs. Secret: Quick Comparison
| Feature | ConfigMap | Secret |
|---|---|---|
| Data type | Plain text | base64-encoded |
| Use for | Config, flags, URLs | Passwords, tokens, certs |
| Stored in etcd | Plain text | base64 (enable etcd encryption for production) |
| Injection methods | Env vars, volume files | Env vars, volume files |
Updating ConfigMaps and Secrets
When you update a ConfigMap mounted as a volume, Kubernetes automatically refreshes the files inside the running container within about 60 seconds. Environment variables do not update until the Pod restarts. For apps that read config files at startup only, a Pod restart is still required after an update.
Best Practices
- Never put passwords or API keys inside your container image or Dockerfile.
- Always use Secrets for sensitive data, never ConfigMaps.
- Enable etcd encryption at rest in production clusters.
- Use RBAC to restrict which service accounts can read which Secrets.
- Consider external secret management tools (Vault, AWS Secrets Manager) for advanced security requirements.
