Kubernetes ConfigMaps and Secrets: The Vault
Manage Kubernetes configuration securely with ConfigMaps, Secrets, env vars, and volumes
The final gate of the Orchestration Citadel, Warrior. Your workloads run, heal, and connect - but they are hardcoded, brittle things, their database passwords baked into images for any eye to see. A true master never welds configuration to code. In this quest you learn the Vault and the Ledger: ConfigMaps to hold non-sensitive settings, and Secrets to guard credentials, both injected cleanly into your Pods without rebuilding a single image.
Whether you are externalizing a feature flag, mounting a TLS certificate, or stopping a password from leaking into a Git history, this adventure teaches the discipline that separates production-grade clusters from accidents waiting to happen.
📖 The Legend Behind This Quest
In the dark ages, configuration lived wherever it was convenient: hardcoded in source, smuggled into container images, scrawled across deploy scripts. Then a single leaked image with an embedded password would unmake an entire kingdom. The twelve-factor doctrine declared a law: store config in the environment, never in the code. Kubernetes gave that law two instruments - the ConfigMap for the harmless and the Secret for the sensitive - so the same image runs unchanged in dev, staging, and production, with only the injected config differing.
This quest teaches the “why” behind configuration hygiene. Master it, and you close the most common door attackers walk through: secrets left lying in the open.
🎯 Quest Objectives
By the time you complete this epic journey, you will have mastered:
Primary Objectives (Required for Quest Completion)
- ConfigMaps - Store non-sensitive configuration and inject it into Pods
- Secrets - Hold credentials and sensitive data separately from code
- Injection via Environment Variables - Surface config as env vars in a container
- Injection via Volumes - Mount config and secrets as files
Secondary Objectives (Bonus Achievements)
- Config Hygiene - Apply the twelve-factor “config in the environment” rule
- Secret Security - Understand that base64 is encoding, not encryption, and enable at-rest encryption
- Live Reload Awareness - Know which injection methods update without a restart
Mastery Indicators
You’ll know you’ve truly mastered this quest when you can:
- Explain when to use a ConfigMap versus a Secret
- Inject the same data as both env vars and mounted files
- Explain why a Secret’s value is not actually encrypted by default
- Diagnose a Pod stuck because a referenced ConfigMap is missing
🗺️ Quest Prerequisites
📋 Knowledge Requirements
- Completion of Kubernetes Fundamentals and Pods and Workloads
- Comfort writing and applying Deployment manifests
- Awareness of why configuration should live outside code
🛠️ System Requirements
- Modern operating system (Windows 10+, macOS 10.14+, or Linux)
- A running local cluster (
kind,minikube, ork3d) kubectlconfigured and on yourPATH
🧠 Skill Level Indicators
This 🟡 Medium quest expects:
- You can deploy a workload and edit its container spec
- You are ready to separate configuration from code
- Ready for 75-90 minutes of hands-on practice
🌍 Choose Your Adventure Platform
ConfigMaps and Secrets are pure Kubernetes objects - they behave identically on every platform. You only need a working cluster and kubectl.
🍎 macOS Kingdom Path
Click to expand macOS instructions
```bash # Confirm the cluster and set a working namespace kubectl config use-context kind-citadel kubectl create namespace vault kubectl config set-context --current --namespace=vault ```🪟 Windows Empire Path
Click to expand Windows instructions
```powershell kubectl config use-context kind-citadel kubectl create namespace vault kubectl config set-context --current --namespace=vault ```🐧 Linux Territory Path
Click to expand Linux instructions
```bash kubectl create namespace vault kubectl config set-context --current --namespace=vault ```☁️ Cloud Realms Path
Click to expand Cloud/Container instructions
```bash # On managed clusters the same objects work. Production clusters often integrate # an external secret store (AWS Secrets Manager, Vault) via the Secrets Store CSI driver: kubectl create namespace vault kubectl config set-context --current --namespace=vault ``` **Cloud-Specific Notes:** - Cloud KMS can encrypt Secrets at rest in etcd - enable it for production. - External Secrets Operator and the Secrets Store CSI driver sync from cloud vaults.🧙♂️ Chapter 1: ConfigMaps - The Ledger of Settings
A ConfigMap holds non-sensitive key-value configuration: log levels, feature flags, service URLs, entire config files. Decoupling these from the image means one image runs everywhere, configured by its environment.
⚔️ Skills You’ll Forge in This Chapter
- Creating ConfigMaps imperatively and declaratively
- The two shapes: simple keys and whole config files
- Inspecting a ConfigMap
🏗️ Create a ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: "info" # simple key-value settings
FEATURE_DARK_MODE: "true"
app.properties: | # an entire file as one value
server.port=8080
cache.ttl=300
welcome.message=Greetings, adventurer
# Apply the manifest...
kubectl apply -f app-config.yaml
# ...or create one imperatively from literals or files
kubectl create configmap app-config \
--from-literal=LOG_LEVEL=info \
--from-literal=FEATURE_DARK_MODE=true
# Inspect it
kubectl get configmap app-config -o yaml
kubectl describe configmap app-config
🔍 Knowledge Check: ConfigMaps
- What kind of data belongs in a ConfigMap?
- How can a ConfigMap hold an entire config file?
- Name two ways to create a ConfigMap.
⚡ Quick Wins and Checkpoints
- ConfigMap Created:
kubectl get configmap app-configsucceeds - Data Verified: You can see your keys in
describeoutput
🧙♂️ Chapter 2: Secrets - The Guarded Vault
A Secret looks like a ConfigMap but is meant for sensitive data: passwords, tokens, TLS keys. Kubernetes treats Secrets with extra care - but a critical truth: Secret values are only base64-encoded, not encrypted, by default. Encoding is not security.
⚔️ Skills You’ll Forge in This Chapter
- Creating Secrets safely
- Why base64 is not encryption
- Enabling encryption at rest
🏗️ Create a Secret
Prefer creating Secrets imperatively or from files so plaintext never lands in a committed YAML:
# From literals (Kubernetes base64-encodes for you)
kubectl create secret generic db-credentials \
--from-literal=DB_USER=appuser \
--from-literal=DB_PASSWORD='s3cr3t-p@ss'
# A TLS Secret from cert files (common for Ingress)
kubectl create secret tls web-tls --cert=tls.crt --key=tls.key
# Inspect - note the values are base64, NOT encrypted
kubectl get secret db-credentials -o yaml
echo 'czNjcjN0LXBAc3M=' | base64 --decode # anyone can decode this!
If you must declare a Secret in YAML, use stringData so you write plaintext and Kubernetes encodes it - but never commit such a file to Git:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData: # plaintext in, base64 stored (keep out of version control)
DB_USER: appuser
DB_PASSWORD: s3cr3t-p@ss
⚠️ Base64 is encoding, not encryption. Protect real Secrets with RBAC (limit who can
get secrets), enable encryption at rest for etcd, and in production sync from an external vault (AWS Secrets Manager, HashiCorp Vault) via the External Secrets Operator.
🔍 Knowledge Check: Secrets
- Why is a Secret’s value not actually secret on its own?
- Why prefer
kubectl create secretover a committed YAML file? - What three controls harden Secrets in production?
🧙♂️ Chapter 3: Injecting Configuration - Env Vars and Volumes
Configuration is useless until it reaches your container. Kubernetes offers two injection styles: environment variables (simple, but fixed at start) and mounted volumes (files, which can update live).
⚔️ Skills You’ll Forge in This Chapter
- Injecting ConfigMaps and Secrets as env vars
- Mounting them as files via volumes
- Knowing which method updates without a restart
🏗️ Inject Everything Into a Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 2
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "env | sort; cat /etc/appconfig/app.properties; sleep 3600"]
env:
- name: LOG_LEVEL # single key from a ConfigMap
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DB_PASSWORD # single key from a Secret
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_PASSWORD
envFrom:
- configMapRef: # import ALL keys as env vars
name: app-config
volumeMounts:
- name: config-volume # mount the ConfigMap as files
mountPath: /etc/appconfig
- name: secret-volume # mount the Secret as files
mountPath: /etc/secrets
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config
- name: secret-volume
secret:
secretName: db-credentials
# Apply and verify the injection worked
kubectl apply -f app-deployment.yaml
kubectl rollout status deployment/app
# Confirm env vars landed
kubectl exec deploy/app -- sh -c 'echo $LOG_LEVEL; echo $FEATURE_DARK_MODE'
# Confirm mounted files exist (each key becomes a file)
kubectl exec deploy/app -- ls /etc/appconfig /etc/secrets
kubectl exec deploy/app -- cat /etc/appconfig/app.properties
Env vars vs volumes - the live-update difference:
| Method | Updates without restart? | Best for |
|---|---|---|
env / envFrom |
No - env is fixed at container start | Simple scalar settings |
| Volume mount | Yes - the kubelet syncs changes into the file (with a short delay) | Files, certs, settings that may change |
After editing a ConfigMap, env-var consumers need a rollout to pick up changes:
kubectl edit configmap app-config # change a value
kubectl rollout restart deployment/app # required for env vars to refresh
🔍 Knowledge Check: Injection
- What is the difference between
valueFromandenvFrom? - Which injection method reflects ConfigMap edits without a restart?
- What happens to each ConfigMap key when mounted as a volume?
🎮 Mastery Challenges
🟢 Novice Challenge: Externalize a Setting
Objective: Move a hardcoded setting into a ConfigMap.
Requirements:
- Create a ConfigMap with at least two keys
- Inject one key as an env var into a Pod
- Confirm the value is visible inside the container
Validation: kubectl exec shows the env var set from the ConfigMap.
🟡 Intermediate Challenge: Guard a Credential
Objective: Store a password in a Secret and consume it safely.
Requirements:
- Create a Secret with
kubectl create secret(no committed plaintext) - Inject it as an env var AND mount it as a file
- Explain why the stored value is base64, not encrypted
Validation: Both the env var and the mounted file contain the password.
🔴 Advanced Challenge: Full Config-Driven Deployment
Objective: Run one Deployment fully configured by external ConfigMaps and Secrets.
Requirements:
- Use
envFromto import all ConfigMap keys - Mount both a ConfigMap and a Secret as volumes
- Edit the ConfigMap and demonstrate the volume update vs the env-var restart requirement
- State one production hardening step for the Secret
Validation: You can show config arriving via env vars and files, and explain the reload behavior of each.
🏆 Quest Rewards & Achievements
🎖️ Badges Earned:
- 🏆 Keeper of the Vault - You master ConfigMaps and Secrets
- 🔐 Twelve-Factor Adept - You separate configuration from code
🛠️ Skills Unlocked:
- Configuration Injection - Env vars and volume mounts
- Secret Management Best Practices - Encoding vs encryption, RBAC, at-rest encryption
🔓 Unlocked Quests:
- Monitoring Fundamentals - Observe the cluster you now fully command
📊 Progression Points: +75 XP
🗺️ Next Steps in Your Journey
Continue the Main Story:
- 🎯 Monitoring Fundamentals - See inside your cluster
Explore Side Adventures:
- ⚔️ Services and Networking - Revisit how config flows between services
Character Class Recommendations
💻 Software Developer: Advance to Monitoring Fundamentals
🏗️ System Engineer: Revisit Services and Networking
🛡️ Security Specialist: Study the Secret hardening notes above closely
📚 Resources
Official Documentation
- ConfigMaps - Non-sensitive configuration
- Secrets - Sensitive data handling
- Configure a Pod to Use a ConfigMap - Injection patterns
- Encrypting Confidential Data at Rest - Protect etcd
Community Resources
- The Twelve-Factor App: Config - The config-in-the-environment principle
- External Secrets Operator - Sync Secrets from cloud vaults
- Secrets Store CSI Driver - Mount external secrets as volumes
Learning Materials
- kubectl Cheat Sheet - ConfigMap and Secret commands
- Killercoda Configuration Scenarios - Hands-on config labs
🤝 Quest Completion Checklist
Before marking this quest as complete, ensure you’ve:
- ✅ Completed all primary objectives
- ✅ Created a ConfigMap and a Secret
- ✅ Injected config via both env vars and volumes
- ✅ Answered all knowledge check questions
- ✅ Completed at least one mastery challenge
- ✅ Identified your next quest in the journey
🕸️ Knowledge Graph
Structured wiki-links connect this quest to the IT-Journey knowledge graph. Open the Obsidian Graph View to explore connections.
Level hub: [[Level 1001 (9) - Kubernetes Orchestration]] Overworld: [[🏰 Overworld - Master Quest Map]] Prerequisites: [[Kubernetes Fundamentals: Container Orchestration Essentials]] · [[Kubernetes Pods and Workloads: Deployments and StatefulSets]] Sequel quests: [[Monitoring Fundamentals: Master Metrics, Logs & Traces for Observability]] Obsidian docs: [[Obsidian Knowledge Graph and Wiki Links]]
🎁 Rewards
Badges
- 🏆 Keeper of the Vault - Mastered ConfigMaps and Secrets
- 🔐 Twelve-Factor Adept - Separated configuration from code
Skills unlocked
- 🛠️ Configuration Injection (env + volumes)
- 🧠 Secret Management Best Practices
Features unlocked
- Completion of the Level 1001 Kubernetes Orchestration quest line
🕸️ Quest Network
Click a node to open the quest · ⌘/Ctrl-click for a new tab · drag to reposition · scroll to zoom.
Referenced by
- Loading…