If you have ever rebuilt a container image just to change a single environment variable or update an HTML file, you already know why Kubernetes ConfigMap is one of the most important resources in the CKA exam and in production DevOps workflows.
In this hands-on tutorial, I will walk through the exact commands I use to create a ConfigMap, inject its data as environment variables, and mount a file into an Nginx Pod. I will also share the hard-earned lessons from 5+ years of running Kubernetes on AWS that the documentation often glosses over.
Table of Contents
Why Kubernetes ConfigMap Matters in Real Production
A Kubernetes ConfigMap decouples configuration artifacts from container images. This means the same Nginx image can serve a development page, a staging banner, or a production landing page without a single docker build. For teams running microservices on EKS, this separation is not a luxury—it is a requirement for GitOps and twelve-factor app compliance.

Before touching the terminal, verify your cluster context. I always run these two commands as a sanity check, especially when juggling multiple AWS profiles or kubeconfig files.
kubectl cluster-info
kubectl get nodesThe first returns the control plane endpoint; the second confirms your worker nodes are Ready. If you are on a managed EKS cluster, cluster-info should point to the EKS endpoint, not a local VM.
Step 1: Create the Namespace and Test Artifact
Isolation matters. Even in a demo, I create a dedicated namespace so cleanup is a single kubectl delete ns command.
kubectl create ns cm-demo
mkdir ~/cm-demo
cd ~/cm-demoNow create the file we will eventually mount into Nginx. This simulates a real-world static asset that operations teams need to update without rebuilding the web server image.
echo "<html><head><title>ConfigMap Tutorial Test Page</title></head><body><h2>ConfigMap Tutorial Test Page from CentLinux</h2></body></html>" > index.htmlPro Tip: Always verify the file exists and looks correct with ls and cat before referencing it in a Kubernetes ConfigMap. A missing --from-file path will cause kubectl to fail with a cryptic error that wastes five minutes of troubleshooting.
Step 2: Create the Kubernetes ConfigMap with Literals and a File
Here is where the power of kubectl create configmap shines. You can mix simple key-value pairs (--from-literal) with file-backed data (--from-file) in a single command.
kubectl create configmap -n cm-demo cm-nginx-01 \
--from-literal=APP_COLOR=blue \
--from-literal=APP_MODE=prod \
--from-file=./index.htmlThe resulting Kubernetes ConfigMap object has three keys: APP_COLOR, APP_MODE, and index.html. The filename becomes the key, and the file contents become the value.
Critical Habit: Always inspect what you created before deploying a Pod that depends on it.
kubectl describe configmap -n cm-demo cm-nginx-01Look at the Data section. If you see the HTML string and the two environment values, you are good. I have seen engineers skip this step, only to discover a typo in the key name that causes a CreateContainerConfigError later.
Opinion from Experience: The
kubectl create configmapimperative command is fantastic for learning and quick tests, but for production I strongly recommend storing the YAML declaratively in Git. Imperative commands do not leave a trace of how the Kubernetes ConfigMap was created, which complicates drift detection and disaster recovery.
Step 3: Generate the Pod Manifest (The Dry-Run Trick)
Instead of writing YAML from scratch, generate a skeleton and edit it. This is a CKA exam habit that saves time and prevents indentation errors.
kubectl run nginx-01 -n cm-demo --image=nginx --dry-run=client -o yaml > nginx-01.yamlOpen the file and transform it into a Pod that consumes the Kubernetes ConfigMap in two ways simultaneously: environment variables and a mounted volume. Here is the final manifest:
apiVersion: v1
kind: Pod
metadata:
labels:
run: pod
name: pod
namespace: cm-demo
spec:
containers:
- image: nginx
name: pod
envFrom:
- configMapRef:
name: cm-nginx-01
volumeMounts:
- name: cm-index-page
mountPath: /usr/share/nginx/html/index.html
subPath: index.html
volumes:
- name: cm-index-page
configMap:
name: cm-nginx-01
items:
- key: index.html
path: index.html
dnsPolicy: ClusterFirst
restartPolicy: AlwaysKey details that trip people up:
envFromwithconfigMapRefloads all keys from the Kubernetes ConfigMap as environment variables. If you only want specific keys, useenvwithconfigMapKeyRefinstead.- The
subPathinvolumeMountsis essential here. Without it, mounting to/usr/share/nginx/html/index.htmlwould create a directory namedindex.html, and Nginx would return a 403. ThesubPathtells Kubernetes to mount the file directly. - The
itemsarray undervolumes.configMaprestricts which keys are projected. Since we only want the HTML file, we specify it explicitly.
Warning Based on Hard Experience: Using
subPathmeans the mounted file will not receive automatic updates if the Kubernetes ConfigMap changes. The Kubernetes documentation explicitly states thatsubPathvolumes do not get update propagation. If you need hot-reload behavior for configuration files, mount the entire volume to a directory and avoidsubPath.
Step 4: Deploy and Verify
Apply the manifest:
kubectl apply -f nginx-01.yamlWait a few seconds for the image to pull if it is not cached, then verify the environment variables were injected:
kubectl exec pod -n cm-demo -- printenv | grep APPExpected output:
APP_COLOR=blue
APP_MODE=prodNext, confirm the Kubernetes Pod is running and grab its IP:
kubectl get pod -n cm-demo -o wideFinally, curl the Pod IP to verify Nginx is serving the HTML file from the Kubernetes ConfigMap:
curl http://<POD_IP>You should see the HTML title ConfigMap Tutorial Test Page from CentLinux. This proves the volume mount worked and Nginx is reading the projected file from the Kubernetes ConfigMap rather than the default index.html baked into the image.
Kubernetes ConfigMap Best Practices from 5+ Years in the Trenches
1. Never put secrets in a Kubernetes ConfigMap.
Kubernetes ConfigMaps store plaintext data. Environment variables injected via envFrom are visible in kubectl describe pod output and may leak into crash logs. Use Kubernetes Secrets for API keys and passwords, even though Secrets are only base64-encoded by default.
2. Choose your injection method deliberately.
- Environment variables are simpler for feature flags and short strings, but changes require a Pod restart.
- Volume mounts are better for configuration files and support eventual updates (except with
subPath), but require the application to re-read the file.
3. Mark stable Kubernetes ConfigMaps as immutable.
If a Kubernetes ConfigMap should never change after creation, set immutable: true. This reduces API server load on large clusters because the kubelet can stop watching for changes. The trade-off: you must delete and recreate the Kubernetes ConfigMap to modify it.
4. Watch the 1 MiB size limit.
Each Kubernetes ConfigMap is capped at 1 MiB of data. For large configuration files, mount a PersistentVolume or use an external configuration service. I have seen teams try to stuff a 5 MB certificate bundle into a Kubernetes ConfigMap and wonder why etcd rejects it.
5. Keep Kubernetes ConfigMaps in the same namespace as the Pod.
A Pod cannot reference a Kubernetes ConfigMap in another namespace. This is a common source of confusion when migrating workloads between environments.
Cleanup
Delete the namespace to remove everything in one shot:
kubectl delete ns cm-demo
rm -rf ~/cm-demoThis is why I always demo in a dedicated namespace—cleanup is atomic and you will not accidentally delete a production ConfigMap.
Final Thoughts
The Kubernetes ConfigMap is deceptively simple. On the surface, it is just a key-value store. But the subtle behaviors—subPath blocking updates, envFrom exposing all keys, namespace boundaries—are what separate a working demo from a production-ready configuration strategy. Practice this workflow until the kubectl create configmap flags and the volume mount syntax become muscle memory. Your future self, debugging a 2 AM incident, will thank you.
Frequently Asked Questions
Q1: My Pod is stuck in CreateContainerConfigError. What is the root cause and how do I fix it?
This error almost always means the kubelet cannot find or read a Kubernetes ConfigMap or Secret referenced by the Pod. The three most common causes are: (a) a key name mismatch between configMapKeyRef.key and the actual key in the ConfigMap, (b) the ConfigMap exists in a different namespace than the Pod, or (c) optional: true was omitted on a reference to a Kubernetes ConfigMap that does not exist yet.
Run kubectl describe pod <name> and look at the Events section—the exact missing key or resource name is printed there. Fix the reference, then kubectl delete pod to force recreation, since environment-variable references are resolved only at container start.
Q2: If I update a Kubernetes ConfigMap, will my running Pod pick up the change automatically?
It depends entirely on the injection method. Volume-mounted ConfigMaps (without subPath) are updated by the kubelet asynchronously, typically within 30–120 seconds, but your application must re-read the file to notice—Nginx, for example, needs a reload signal. Environment variables are frozen at container start and will never update; a Pod restart or rollout is mandatory. And the critical gotcha: any mount using subPath does not receive updates at all. For configuration that must hot-reload, mount the entire directory and have the app watch the file, or run a sidecar that triggers a reload.
Q3: How do I safely rotate or version a K8s ConfigMap without causing downtime?
Do not mutate a live ConfigMap in place. Instead, adopt a versioned naming convention (for example, cm-app-config-v2) and update the Pod template to reference the new name. With a Deployment, this triggers a rolling update with zero downtime and gives you a clean rollback path—just point the template back to v1. This also plays well with GitOps tools like Argo CD, which will flag the new Kubernetes ConfigMap as a distinct resource rather than an in-place drift. Combine this with immutable: true on the old Kubernetes ConfigMap to prevent accidental edits during the transition.
Q4: When should I use a ConfigMap instead of a Secret or an external configuration store?
Use a Kubernetes ConfigMap for non-sensitive, environment-specific settings: feature flags, log levels, service URLs, and configuration files. Use a Secret for anything credential-like—API keys, tokens, TLS material—even though base64 is not encryption; enable encryption at rest on etcd and consider an external KMS provider. Reach for an external store (AWS Secrets Manager, HashiCorp Vault, or the External Secrets Operator) when you need centralized audit trails, automatic rotation, or multi-cluster consistency. A practical rule I apply: if leaking the value would trigger a security incident, it does not belong in a Kubernetes ConfigMap.
Q5: What is the best way to keep Kubernetes ConfigMaps under source control and avoid environment drift?
Treat Kubernetes ConfigMaps as first-class manifests in Git and manage them declaratively—never via imperative kubectl create in production. Use Kustomize overlays to generate per-environment ConfigMaps from a shared base, so dev, staging, and prod differ only by their overlay patches.
Add a CI validation step that runs kubectl diff -f against the target cluster to surface drift before merge, and pair it with kubectl apply --server-side for conflict-free reconciliation. For team environments, enforce a policy (Kyverno or OPA Gatekeeper) that blocks Kubernetes ConfigMaps lacking required labels like app, env, and owner, which keeps configuration discoverable and auditable as the cluster scales.
Recommended Books
If you are preparing for the CKA exam or want to deepen your understanding of how ConfigMaps fit into the broader Kubernetes ecosystem, I highly recommend The Kubernetes Book (2025 Edition) by Nigel Poulton. It is consistently the #1 best-selling Kubernetes book on Amazon for a reason—it dedicates a full chapter to ConfigMaps and Secrets, breaking down the exact injection methods we just practiced without the jargon .
For those of you looking to validate your cloud skills alongside your Kubernetes knowledge, the AWS Certified Solutions Architect Study Guide (SAA-C03) by Ben Piper and David Clinton is another top-tier resource that pairs perfectly with the AWS-centric workflows I use in production . Both are staples on my desk and are excellent investments for anyone serious about cloud-native engineering.
Disclosure: As an Amazon Associate, I earn from qualifying purchases. This means if you click through and make a purchase, I may receive a small commission at no extra cost to you. I only recommend books I have personally used or vetted for their technical accuracy.
Recommended Courses
If you’re eager to kickstart your journey into cloud-native technologies, “Kubernetes for the Absolute Beginners – Hands-on” by Mumshad Mannambeth is the perfect course for you. Designed for complete beginners, this course breaks down complex concepts into easy-to-follow, hands-on lessons that will get you comfortable deploying, managing, and scaling applications on Kubernetes.
Whether you’re a developer, sysadmin, or IT enthusiast, this course provides the practical skills needed to confidently work with Kubernetes in real-world scenarios. By enrolling through the links in this post, you also support this website at no extra cost to you.
Disclaimer: Some of the links in this post are affiliate links. This means I may earn a small commission if you make a purchase through these links, at no additional cost to you.









Leave a Reply
You must be logged in to post a comment.