Learning objectives
By the end of this module, you should be able to:
- Use ConfigMaps as environment variables or files.
- Use Secrets without putting credentials directly in manifests or images.
- Explain why a Secret object is not automatically equivalent to encrypted-at-rest secret management.
ConfigMaps decouple configuration
ConfigMaps store non-confidential key/value or file-like configuration. Pods can consume them through environment variables, command arguments or mounted volumes.
Secrets are for confidential data
Secrets are a distinct API object for passwords, tokens and keys. Base64 encoding in YAML is encoding, not encryption. Kubernetes documentation warns that Secret data is stored unencrypted in etcd by default unless encryption at rest is configured.
Delivery method affects update behavior
Environment variables are captured when the container starts. Mounted ConfigMap/Secret volumes can update eventually, but applications must be able to reread changed files. Immutable rollout patterns are often easier to reason about.
Worked examples
See the idea in practice.
Create configuration safely
kubectl -n gnu-k8s-fundamentals create configmap app-config --from-literal=APP_MODE=training
kubectl -n gnu-k8s-fundamentals create secret generic app-secret --from-literal=API_TOKEN=demo-token
- ConfigMap is for non-secret configuration.
- Secret is a separate object; production secret management still needs RBAC, encryption and careful access controls.
Hands-on lab
Lab — Inject config and a secret
Goal: Create configuration objects, consume them in one Pod, verify the values, then clean them up.
Before you start
- kubectl is installed and can reach the lab cluster.
- Use the dedicated gnu-k8s-fundamentals namespace unless a step explicitly says otherwise.
STEP 1Create ConfigMap and Secret
kubectl -n gnu-k8s-fundamentals create configmap cfg-demo --from-literal=APP_MODE=training
kubectl -n gnu-k8s-fundamentals create secret generic secret-demo --from-literal=API_TOKEN=demo-token
STEP 2Create the Pod
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: config-demo
namespace: gnu-k8s-fundamentals
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh","-c","echo mode=$APP_MODE; echo token-present=${API_TOKEN:+yes}; sleep 3600"]
env:
- name: APP_MODE
valueFrom:
configMapKeyRef:
name: cfg-demo
key: APP_MODE
- name: API_TOKEN
valueFrom:
secretKeyRef:
name: secret-demo
key: API_TOKEN
EOF
STEP 3Wait and inspect safe output
kubectl -n gnu-k8s-fundamentals wait --for=condition=Ready pod/config-demo --timeout=90s
kubectl -n gnu-k8s-fundamentals logs config-demo
STEP 4Clean up
kubectl -n gnu-k8s-fundamentals delete pod config-demo
kubectl -n gnu-k8s-fundamentals delete configmap cfg-demo
kubectl -n gnu-k8s-fundamentals delete secret secret-demo
Verify
- APP_MODE is read from the ConfigMap.
- The Secret value is injected but the example log does not print the secret itself.
Expected outcome
- Logs show mode=training and token-present=yes.
If it fails
- If a referenced key/name is wrong, describe the Pod and inspect Events.
- Avoid kubectl get secret -o yaml in shared terminals because base64 values are trivially reversible.
Real-world connectionConfiguration separation allows the same image to be promoted across environments while runtime settings change independently.
Avoid these traps
Common mistakes
- Committing real secrets to Git because their YAML uses base64.
- Printing secrets to logs during verification.
- Expecting environment-variable consumers to see ConfigMap updates without a restart.
Knowledge check
Can you explain it without looking back?
Open each answer only after you have tried to answer the question yourself.
1Is base64-encoded Secret data encrypted?
No. Base64 is encoding, not encryption.
2What should hold non-confidential application configuration?
A ConfigMap is designed for that purpose.
3Why might a Pod fail to start after a ConfigMap name is changed?
Its env/volume references may point to an object or key that no longer exists.