Sunday, March 1, 2026

ConfigMaps

 

01) ConfigMaps & 3 Types

Ladder 1 — What it is

A ConfigMap stores non-secret configuration outside your container image.

Ladder 2 — Why it exists

Without it, you hardcode configs inside image → changing config requires rebuild + redeploy.

Ladder 3 — How it works

ConfigMap lives in Kubernetes API (etcd). A Pod can consume it in 3 ways:

Type A: env (single key → single env var)

  • You map specific keys to env variables.

Type B: Volume mount (keys become files)

  • Each key becomes a file under a directory (great for nginx.conf, app.properties).

Type C: envFrom (bulk inject all keys)

  • All keys become env vars automatically.

Ladder 4 — Real scenario

  • You run the same Docker image in Dev/Staging/Prod.

  • Only config differs (DB host, feature flag, API URL).

  • You change ConfigMap → rollout restart deployment (or app reloads if built to reload).

Hands-on commands

kubectl create configmap my-config --from-literal=DB_HOST=prod-db
kubectl create configmap my-config --from-file=app.properties
kubectl get cm my-config -o yaml
kubectl describe cm my-config

Words you must know

  • Key-value: DB_HOST=prod-db

  • Immutable config: you can lock ConfigMap updates using immutable: true (avoids accidental changes)

Memory trick

C-E-V → ConfigMap used via Command, Env, Volume


Kubernetes ConfigMaps — Full Deep Understanding (Ladder Method)


🪜 Ladder 1 — What is a ConfigMap?

A ConfigMap stores non-secret configuration data outside your container image.

Think:

  • DB host

  • API URL

  • Feature flags

  • App mode (dev/prod)

  • Logging level

It lives inside Kubernetes (stored in etcd via API Server) and Pods read from it.




🚨 Why Only NON-Secret Configuration?

Because:

ConfigMaps are:

  • Base64 readable

  • Visible via kubectl get cm

  • Stored as plain text in etcd

They are NOT encrypted by default.

So:

Store InUse For
ConfigMapDB host, API URL, feature flag
SecretPasswords, tokens, certificates

🔥 Why ConfigMaps Exist (Very Important)

Without ConfigMap:

ENV DB_HOST=prod-db
ENV API_URL=https://api.company.com

These are written inside your Dockerfile.

If DB changes:

1️⃣ Edit Dockerfile
2️⃣ Rebuild Image
3️⃣ Push to Registry
4️⃣ Update Deployment
5️⃣ Redeploy Pods

That is slow + risky.


🧠 With ConfigMap:

Image stays same.

Only change:

kubectl edit configmap my-config
kubectl rollout restart deployment app

Done.

No rebuild.

No new image.

No CI/CD triggered.


🪜 Ladder 3 — 3 Ways Pod Consumes ConfigMap


🔹 TYPE A — env (Single Key → Single Env Var)

Use specific keys.

env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: my-config
key: DB_HOST

📌 Use when:

  • You need 1 or 2 specific variables


🔹 TYPE B — Volume Mount (Keys Become Files)

Each key becomes a file.

volumeMounts:
- name: config-volume
mountPath: /etc/config

volumes:
- name: config-volume
configMap:
name: my-config

If ConfigMap has:

nginx.conf
app.properties

They become:

/etc/config/nginx.conf
/etc/config/app.properties

📌 Best for:

  • Nginx configs

  • Spring Boot properties

  • Large config files


🔹 TYPE C — envFrom (Bulk Inject)

All keys become environment variables automatically.

envFrom:
- configMapRef:
name: my-config

📌 Best for:

  • Many key-value configs

  • 12-factor apps


🧠 Memory Trick

C-E-V

LetterMeaning
CCommand
EEnvironment
VVolume

ConfigMap can be consumed via:

  • Environment variables

  • Volume

  • Command arguments (advanced usage)


🏢 Real Production Scenario

You run same image:

myapp:v1

In:

  • Dev

  • Staging

  • Production

Only difference:

EnvironmentDB_HOST
Devdev-db
Stagingstaging-db
Prodprod-db

Instead of 3 images…

You create 3 ConfigMaps.

Same image.

Different config.

Clean architecture.


📦 How It Works Internally (Deep View)

Step 1

You run:

kubectl create configmap my-config --from-literal=DB_HOST=prod-db

Step 2

API Server validates request.

Step 3

ConfigMap stored inside etcd.

Step 4

When Pod starts:

  • Kubelet asks API Server

  • Pulls ConfigMap data

  • Injects into container (env or volume)


🛡 Immutable ConfigMap (Production Safety)

You can lock it:

immutable: true

Why?

Prevents accidental config edits in production.

If change needed:

  • Create new ConfigMap

  • Update Deployment

  • Rollout restart

Safer for large systems.


🎯 Why Not Hardcode Inside Image?

Imagine production DB crashes.

You move to new DB.

If hardcoded:

  • Build new image

  • Push

  • CI pipeline

  • Deploy

  • Downtime risk

If using ConfigMap:

  • Update DB_HOST

  • Restart pods

  • Done in seconds

This is called:

👉 Separation of configuration from application code
👉 12-Factor App principle


🔍 Important Commands

kubectl create configmap my-config --from-literal=DB_HOST=prod-db

kubectl create configmap my-config --from-file=app.properties

kubectl get cm

kubectl describe cm my-config

kubectl get cm my-config -o yaml



ConfigMap Deep Dive — Where It Lives, How etcd Stores It, Why Not Hardcode in Dockerfile

You’re thinking correctly like a Kubernetes engineer now 👏
Let’s break this in ladder + architecture + real production view.


🪜 PART 1 — Where Does a ConfigMap Live?

When you run:

kubectl create configmap my-config --from-literal=DB_HOST=prod-db

What REALLY Happens Internally

1️⃣ kubectl sends request → API Server
2️⃣ API Server validates it
3️⃣ API Server stores it in → etcd
4️⃣ Controllers & Kubelet can now access it


📦 Where Inside etcd?

etcd is a key-value distributed database.

Kubernetes stores objects in this structure:

/registry/configmaps/<namespace>/<configmap-name>

Example:

/registry/configmaps/default/my-config

Inside etcd it is stored as:

  • JSON object

  • Serialized Kubernetes object

  • Metadata + data section

Example internal representation:

{
"metadata": {
"name": "my-config",
"namespace": "default"
},
"data": {
"DB_HOST": "prod-db",
"API_URL": "https://api.company.com"
}
}

It is not a file on disk.
It is not inside Pod.
It is not inside container.

It lives in:
👉 Control Plane → etcd database


🏗 Architecture View

You (kubectl)

API Server

etcd (stores ConfigMap)

Kubelet (when Pod starts)

Inject into Container

Important:

Pods NEVER talk directly to etcd.
Only API Server talks to etcd.


🪜 PART 2 — How Pod Consumes It

When Pod is created:

1️⃣ Scheduler places Pod on a Node
2️⃣ Kubelet on that node:

  • Reads Pod spec

  • Sees ConfigMap reference

  • Calls API Server

  • Fetches ConfigMap data

  • Injects it

Depending on usage:

🔹 As ENV

Kubelet converts key-value into environment variable inside container process.

Inside container:

echo $DB_HOST
prod-db

🔹 As Volume

Kubelet creates temporary directory on node:

/var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~configmap/

Then mounts it inside container.


🔹 As envFrom

Bulk injection.


🪜 PART 3 — Without ConfigMap (Hardcoding in Dockerfile)

Example Dockerfile:

FROM node:18

ENV DB_HOST=prod-db
ENV API_URL=https://api.company.com

COPY . .
CMD ["node", "app.js"]

These ENV values become part of:

👉 Docker Image Layer

That means:

  • It is baked permanently into image

  • Stored in image manifest

  • Cannot change without rebuilding image


🔥 What Happens If DB Changes?

Production DB crashes.

New DB:

new-prod-db

Now what?

Without ConfigMap:

1️⃣ Edit Dockerfile
2️⃣ Rebuild image
3️⃣ Push to Docker Hub/ECR
4️⃣ Update Deployment image version
5️⃣ Pods restart

CI/CD pipeline triggered unnecessarily.

Risk:

  • Image promotion issues

  • Rollback complexity

  • Downtime window


With ConfigMap:

kubectl edit configmap my-config

Change:

DB_HOST=new-prod-db

Then:

kubectl rollout restart deployment app

Pods restart using same image.

No rebuild.
No registry push.
No CI pipeline.


🧠 Why This Matters in Real Companies

Imagine:

100 microservices
5 environments
Each has 20 config values

If hardcoded:

100 × 5 images = 500 image variations 😵

With ConfigMap:

100 images only
Different ConfigMaps per environment

Clean separation.


🔐 Why ConfigMap is Only for NON-Secret

Inside etcd:

  • Stored as plain text

  • Base64 readable

  • Anyone with RBAC access can read

For passwords:

Use Secret:

/registry/secrets/default/my-secret

🧠 Deep Kubernetes Engineer Understanding

ConfigMap is:

  • Kubernetes API Object

  • Stored in etcd

  • Versioned

  • Watched by Kubelet

  • Cached locally on Node

  • Injected at container runtime

It is NOT:

  • A file inside Docker image

  • A runtime Docker feature

  • A Node-level config file


🧩 What Happens If ConfigMap Updated While Pod Running?

🔹 If used as ENV

No automatic update.
Need Pod restart.

🔹 If used as Volume

File updates automatically (within seconds).

App must support file reload.



Perfect 👌 let’s take your exact examples and compare WITHOUT ConfigMap vs WITH ConfigMap in a clean production-style explanation.

We’ll use these configs:

  • DB host

  • API URL

  • Feature flags

  • App mode (dev/prod)

  • Logging level


🚫 WITHOUT ConfigMap (Hardcoded in Dockerfile)

Example Dockerfile

FROM node:18

ENV DB_HOST=prod-db
ENV API_URL=https://api.company.com
ENV FEATURE_NEW_UI=true
ENV APP_MODE=production
ENV LOG_LEVEL=info

COPY . .
CMD ["node", "app.js"]

🔍 What Happens Here?

These values are:

  • Stored inside the Docker image layer

  • Baked permanently into image

  • Same for every environment unless rebuilt


🧨 Problem Scenario

🔹 Case 1 — Dev Environment

In dev, you need:

DB_HOST=dev-db
API_URL=https://dev-api.company.com
APP_MODE=development
LOG_LEVEL=debug

What must you do?

1️⃣ Edit Dockerfile
2️⃣ Rebuild image
3️⃣ Push image
4️⃣ Update Deployment
5️⃣ Restart Pods

Now imagine you have:

  • Dev

  • Staging

  • Production

You must build 3 different images 😵


⚠️ Real Enterprise Problem

If DB changes in production:

prod-db → prod-db-v2

You must:

  • Rebuild

  • Retag

  • Push

  • Redeploy

That means CI/CD triggered for just a config change.

That’s bad architecture.


✅ WITH ConfigMap (Correct Cloud-Native Way)

Now Dockerfile becomes CLEAN:

FROM node:18
COPY . .
CMD ["node", "app.js"]

No environment-specific values inside image.


Step 1 — Create ConfigMap

For Production

kubectl create configmap app-config \
--from-literal=DB_HOST=prod-db \
--from-literal=API_URL=https://api.company.com \
--from-literal=FEATURE_NEW_UI=true \
--from-literal=APP_MODE=production \
--from-literal=LOG_LEVEL=info

For Dev

kubectl create configmap app-config \
--from-literal=DB_HOST=dev-db \
--from-literal=API_URL=https://dev-api.company.com \
--from-literal=FEATURE_NEW_UI=false \
--from-literal=APP_MODE=development \
--from-literal=LOG_LEVEL=debug

Same image. Different ConfigMap.


Step 2 — Use in Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
template:
spec:
containers:
- name: app
image: myapp:v1
envFrom:
- configMapRef:
name: app-config

🔎 What Happens Internally?

1️⃣ Pod starts
2️⃣ Kubelet sees configMapRef
3️⃣ Kubelet fetches ConfigMap from API Server
4️⃣ Injects values as environment variables

Inside container:

echo $DB_HOST
prod-db

🎯 Now Let’s Compare Clearly

ScenarioWithout ConfigMapWith ConfigMap
DB host changeRebuild imageEdit ConfigMap
API URL changeRebuild imageEdit ConfigMap
Logging level changeRebuild imageEdit ConfigMap
Feature flag toggleRebuild imageEdit ConfigMap
Dev/Prod differenceMultiple imagesSame image

🏗 Real Production Example

Imagine you are running:

  • 50 microservices

  • 4 environments

  • 20 config variables each

Without ConfigMap:

50 × 4 images = 200 image versions 😵

With ConfigMap:

50 images only
Different ConfigMaps per environment

Clean DevOps practice.


Why Feature Flags Need ConfigMap

Example:

FEATURE_NEW_UI=true

Marketing wants to disable it immediately.

Without ConfigMap:
Rebuild + redeploy.

With ConfigMap:
Edit → restart → done.

Zero image change.


🧩 Logging Level Example

In production:

LOG_LEVEL=info

In troubleshooting:

LOG_LEVEL=debug

Without ConfigMap:
New image build.

With ConfigMap:
Change one value → restart pods.

Much faster incident handling.


🏁 Final Understanding

Without ConfigMap:

Configuration is part of build lifecycle.

With ConfigMap:

Configuration is part of runtime lifecycle.

This is called:

👉 Separation of concerns
👉 12-Factor App principle
👉 Cloud-native design



Here’s exactly how those 5 configs look WITHOUT ConfigMap (Dockerfile ENV) vs WITH ConfigMap (kubectl create configmap …).


🚫 Without ConfigMap (Hardcoded inside Dockerfile)

All environment-specific values get baked into the image:

FROM node:18

# DB host
ENV DB_HOST=prod-db

# API URL
ENV API_URL=https://api.company.com

# Feature flags
ENV FEATURE_NEW_UI=true
ENV FEATURE_PAYMENTS=false

# App mode
ENV APP_MODE=production

# Logging level
ENV LOG_LEVEL=info

COPY . .
CMD ["node", "app.js"]

What this means

  • If you want dev/staging/prod different values → you must edit Dockerfile + rebuild image each time.

  • If DB host changes → rebuild + push + redeploy.


✅ With ConfigMap (Kubernetes way)

1) Create ConfigMap with all 5 types of values

kubectl create configmap my-config \
--from-literal=DB_HOST=prod-db \
--from-literal=API_URL=https://api.company.com \
--from-literal=FEATURE_NEW_UI=true \
--from-literal=APP_MODE=production \
--from-literal=LOG_LEVEL=info

Now your Dockerfile stays clean (no environment-specific values):

FROM node:18
COPY . .
CMD ["node", "app.js"]

2) Use ConfigMap in your Deployment (two common ways)

Option A: envFrom (inject ALL keys as env vars)

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: myapp:v1
envFrom:
- configMapRef:
name: my-config

Inside the container you’ll have:

  • DB_HOST

  • API_URL

  • FEATURE_NEW_UI

  • APP_MODE

  • LOG_LEVEL

Option B: env (pick only specific keys)

containers:
- name: app
image: myapp:v1
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: my-config
key: DB_HOST
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: my-config
key: LOG_LEVEL

🧠 The big difference (in one line)

  • Dockerfile ENV = config is tied to build time (rebuild image to change)

  • ConfigMap = config is tied to runtime (edit ConfigMap + restart pods)


Update example (Production DB moved)

kubectl edit configmap my-config
# change DB_HOST to prod-db-v2

kubectl rollout restart deployment my-app

No rebuild. Same image. Only config changed.


🔷 First: The 3 Types Again

When a Pod consumes a ConfigMap, it has 3 ways:

TypeMethodWhat Happens
AenvOne key → one environment variable
BvolumeKeys → files
CenvFromAll keys → environment variables

🧠 Now Let’s Correlate with Example ConfigMap

Assume this ConfigMap:

kubectl create configmap my-config \
--from-literal=DB_HOST=prod-db \
--from-literal=API_URL=https://api.company.com \
--from-literal=APP_MODE=production \
--from-literal=LOG_LEVEL=info

This creates:

Key Value
-------------------------
DB_HOST prod-db
API_URL https://api.company.com
APP_MODE production
LOG_LEVEL info

🔹 TYPE A → env (Single Key Mapping)

You manually map each key.

env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: my-config
key: DB_HOST

What happens?

Only this one variable appears in container:

DB_HOST=prod-db

If you want 4 variables → write 4 mappings.

So:

Type A = Manual selection of keys.


🔹 TYPE C → envFrom (Bulk Injection)

This is the missing one you asked about.

envFrom:
- configMapRef:
name: my-config

What happens?

All keys become environment variables automatically:

DB_HOST=prod-db
API_URL=https://api.company.com
APP_MODE=production
LOG_LEVEL=info

No need to write each one.

So:

Type C = Auto inject everything.


🔹 TYPE B → Volume Mount (Keys Become Files)

volumeMounts:
- name: config-volume
mountPath: /etc/config

volumes:
- name: config-volume
configMap:
name: my-config

Now inside container:

/etc/config/DB_HOST
/etc/config/API_URL
/etc/config/APP_MODE
/etc/config/LOG_LEVEL

Each key becomes a file.

If you open:

cat /etc/config/DB_HOST

Output:

prod-db

🔥 Now Let’s Correlate All Three Together

Assume you have:

my-config

If you use:

🔹 env → You pick specific keys manually

🔹 envFrom → You inject all keys automatically

🔹 volume → You get keys as files instead of environment variables


🏠 Real Analogy

Think ConfigMap like a notebook.

Type A (env)

You copy one page manually into your pocket.

Type C (envFrom)

You photocopy the entire notebook into your pocket.

Type B (volume)

You keep the notebook on your desk and read from it directly.


🎯 When to Use Which?

ScenarioUse
Only need 1–2 valuesType A (env)
Need many environment variablesType C (envFrom)
Need config files (nginx.conf, app.properties)Type B (volume)

⚠ Important Difference

MethodAuto Updates?
env❌ Needs pod restart
envFrom❌ Needs pod restart
volume✅ File updates automatically

That’s a big interview point.


🧠 Final Memory Trick

E-E-V

• Explicit env → Type A
• Everything env → Type C
• Volume → Type B


Now you fully understand how:

  • Option A = Type A

  • Option B = Type B

  • Missing one (envFrom) = Type C

All are just different consumption styles of same ConfigMap.



ENV DB_HOST=prod-db ENV API_URL=https://api.company.com ENV FEATURE_NEW_UI=true ENV APP_MODE=production ENV LOG_LEVEL=infoactually what ar these explain me the with the real time environment

Excellent question 👌
These lines:

ENV DB_HOST=prod-db
ENV API_URL=https://api.company.com
ENV FEATURE_NEW_UI=true
ENV APP_MODE=production
ENV LOG_LEVEL=info

are environment variables inside a Docker container.

Let’s break this down in a real-time production scenario — the way you’d explain it in an interview or use it in MLOps/DevOps.


🧠 What Is ENV in Real Time?

ENV means:

“When this container runs, give the application these configuration values.”

Instead of hardcoding inside Python/Java code, we pass settings from outside.


🏢 Real Production Example

Imagine you are deploying:

  • Frontend app

  • Backend API

  • PostgreSQL database

  • Running in Kubernetes on AWS

Your backend needs:

  • Where DB is located

  • Which API to call

  • Whether to enable new UI

  • Whether it's dev or prod

  • How much logging to show

These are NOT code.
They are configuration.


🔍 Let’s Explain Each One (Real Environment Meaning)


1️⃣ DB_HOST=prod-db

What it means:

Where is my database?

Real Example:

Your backend app connects like:

connect(DB_HOST)

If:

DB_HOST=prod-db

It connects to production database.

If:

DB_HOST=localhost

It connects to local DB.

If:

DB_HOST=staging-db

It connects to staging DB.

✅ Same code
🔁 Different environment


2️⃣ API_URL=https://api.company.com

What it means:

Which API endpoint should the app call?

Example:

Your app uses:

requests.get(API_URL + "/users")

Without changing code, you switch environments.


3️⃣ FEATURE_NEW_UI=true

What it means:

Feature flag.

Real companies like:

  • Netflix

  • Amazon

  • Meta

Use feature flags to enable/disable features without redeploying.

Example:

if FEATURE_NEW_UI == "true":
show_new_ui()

You can enable new UI only for:

  • Production

  • Only for testing

  • Only for certain users

This is progressive rollout strategy.


4️⃣ APP_MODE=production

What it means:

Which environment am I running in?

Values:

  • development

  • staging

  • production

Your app changes behavior:

if APP_MODE == "development":
enable_debug()

In production:

  • No debug logs

  • Security enabled

  • Caching enabled


5️⃣ LOG_LEVEL=info

What it means:

How detailed should logs be?

Possible values:

  • debug (very detailed)

  • info (normal)

  • warn

  • error

In development:

LOG_LEVEL=debug

In production:

LOG_LEVEL=info

Why?
Because debug logs in production:

  • Slow down system

  • Fill disk

  • Expose sensitive data


🚨 Why This Is Important

If you hardcode like this:

DB_HOST = "prod-db"

Then:
❌ You must rebuild Docker image for every environment
❌ Risk of pushing production config accidentally
❌ Not scalable


🏗 Real DevOps / Kubernetes Way

Instead of Dockerfile ENV, in production we use:

  • Kubernetes ConfigMap

  • Kubernetes Secrets

  • Helm values.yaml

  • CI/CD pipeline variables

Example:

kubectl create configmap app-config \
--from-literal=DB_HOST=prod-db \
--from-literal=APP_MODE=production

Then Pod reads it dynamically.


🏢 Real Company Flow

Developer writes app →
CI builds Docker image →
CD deploys to:

EnvironmentDB_HOSTAPP_MODELOG_LEVEL
Devdev-dbdevelopmentdebug
QAqa-dbstaginginfo
Prodprod-dbproductioninfo

Same image.
Different configuration.

This is 12-factor app principle.



Configuring Java and Maven

  1️⃣ Configure Java Environment Open the Java environment file. sudo vi /etc/profile.d/java.sh Add these lines inside the file: expor...