A Deployment applies cleanly, but its Pods never become ready. They are not restarting and there is nothing in the logs:
$ kubectl get pods -n shop
NAME READY STATUS RESTARTS AGE
api-6d8f7c9b5d-q7m2z 0/1 CreateContainerConfigError 0 2m14s
$ kubectl describe pod api-6d8f7c9b5d-q7m2z -n shop
Events:
Warning Failed 20s (x6 over 2m) kubelet Error: configmap "app-config" not foundThe kubelet received the Pod, resolved the node and the image, then failed while assembling the container’s environment and mounts. It never called the container runtime, so the container never ran.
Quick fix checklist
- Read the event:
kubectl describe pod <pod> | sed -n '/Events/,$p'. - The message names the kind and the object:
configmap "x" not found,secret "x" not found, orcouldn't find key <key> in configmap/secret <name>. - Check the object exists in the same namespace:
kubectl get configmap <name> -n <ns>/kubectl get secret <name> -n <ns>. - For a key error, compare the key in the manifest with the object’s keys (
kubectl get configmap <name> -o jsonpath='{.data}'). - Create the missing object, or fix the name/key in the Pod template.
- A Secret referenced by a ServiceAccount or image pull can also surface here with a
secret "..." not foundmessage. - Set
optional: trueon avalueFrom/envFromentry only if the container can start without it.
Before you start
You need kubectl access to the namespace and permission to read ConfigMaps and Secrets there. The examples use Kubernetes 1.30 and later; the event wording for these errors has been stable for several releases. Remember that kubectl get secret cannot show the contents of a secret with a data key you cannot decode; use kubectl get secret <name> -o jsonpath='{.data}' and the referenced key name has to match exactly.
Why it happens
Before a container can start, the kubelet turns the Pod spec into a concrete container config: environment variables from env, envFrom and valueFrom, plus files projected from ConfigMaps and Secrets. Every one of those references must resolve within the Pod’s namespace. If any reference points at a ConfigMap, Secret or key that does not exist, the kubelet cannot finish that translation and reports CreateContainerConfigError. The container is never created, which is why kubectl logs shows nothing useful and restartCount stays at zero: this is a configuration failure, not a crash.
The common causes, in order of frequency:
- A typo or a renamed object. The ConfigMap is
app-configbut the manifest (or a Helm value) saysapp_config. - The wrong namespace. The object exists in
defaultorstaging, but the Pod runs inshop. References never cross namespaces. - A missing key. The ConfigMap exists but the
keyinvalueFrom.configMapKeyRef.keyis not one of its entries. - Ordering. A manifest applied before its ConfigMap/Secret; in GitOps the object may simply not be reconciled yet.
- A missing pull or service-account secret named in the Pod or its ServiceAccount.
Step-by-step walkthrough
Step 1: Read the exact event
kubectl describe pod <pod> -n <ns> | sed -n '/Events/,$p'Copy the message verbatim. configmap "app-config" not found is a name/namespace problem; couldn't find key DATABASE_URL in configmap app-config is a key problem. The two need different fixes, so do not guess.
Step 2: Check the object in the Pod’s namespace
kubectl get configmap app-config -n shop
kubectl get secret db-credentials -n shopIf both return Error from server (NotFound), the object is missing here, whatever exists elsewhere. Confirm the namespace with kubectl config view --minify -o jsonpath='{..namespace}' so you are looking at the right one.
Step 3: Compare the keys
kubectl get configmap app-config -n shop -o jsonpath='{.data}' | tr ',' '\n'Match the key against the manifest’s configMapKeyRef.key (or the environment name). A single stray character or a - versus _ is enough to trigger the error.
Step 4: Fix the reference or create the object
Choose one, based on what the event said:
# fix the name
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config # was app_config
key: LOG_LEVEL# or create the missing object in the right namespace
kubectl create configmap app-config --from-file=app.properties -n shopFor data the app can run without, mark the reference optional so a missing object does not block startup:
envFrom:
- configMapRef:
name: feature-flags
optional: trueStep 5: Recreate the Pod
ConfigMaps and Secrets are read when the container config is built, so an existing Pod does not pick up a newly created object automatically. Apply the fixed manifest or delete the Pod so the ReplicaSet creates one that resolves:
kubectl delete pod <pod> -n shop
# a Deployment/ReplicaSet creates a replacementWorked scenario
A team promotes a Deployment to a new namespace with kubectl apply but the ConfigMap lives in the old one. Pods show CreateContainerConfigError and describe says configmap "app-config" not found. kubectl get configmap app-config -n shop returns NotFound, while -n staging returns the object. The namespace of a reference is the Pod’s, not the object’s: the fix is to create the ConfigMap in shop (or to make it part of the same applied manifest set), not to change the Pod. Once created, deleting the stuck Pods lets the ReplicaSet start clean ones.
Common mistake
Adding optional: true to silence the error. It makes the Pod start, but the app then runs without configuration it expected: an empty database URL, an empty API key, or a feature flag defaulting to on. The error was correct; making the reference optional hides a real misconfiguration and moves the failure into the running process, where it is harder to trace.
Verify the behavior
After the fix, a fresh Pod should move past the configuration stage:
kubectl get pods -n shop -l app=api -w
kubectl describe pod -n shop -l app=api | sed -n '/Events/,$p'NAME READY STATUS RESTARTS AGE
api-6d8f7c9b5d-t9zp4 1/1 Running 0 35sNo further Failed ... configmap/secret ... not found events appear, and the container reaches Running with its environment filled in.
Interview exercise
“Pods show CreateContainerConfigError in one cluster and CrashLoopBackOff in another for what looks like the same Deployment. How do you tell them apart, and why do they behave differently?”
Answer and reasoning
The two states mean different things at different stages. CreateContainerConfigError is a kubelet failure while building the container config: the container never starts, restartCount stays zero, and kubectl logs is empty, so the cause is in the describe events (a missing ConfigMap, Secret or key). CrashLoopBackOff means the container started and its process exited repeatedly, so the cause is in the logs and the exit code. The same manifest can produce both if one cluster has the referenced objects and the other does not: wherever the ConfigMap is missing, the Pod cannot even create its container; wherever it exists, the app starts and then fails for an application reason. I would read the status and events first, since that already tells me which of the two problems I am chasing.
Continue learning
- Kubernetes interview questions and Kubernetes MCQs
- Kubernetes ConfigMaps versus Secrets
- Kubernetes CrashLoopBackOff
- Kubernetes OOMKilled and exit code 137
- Kubernetes troubleshooting from symptoms to evidence
- Kubernetes namespace boundaries
- Official reference: ConfigMaps, Secrets and Configure a Pod to use a ConfigMap