Skip to main content

Command Palette

Search for a command to run...

Kubernetes ConfigMaps & Secrets Explained (With Practical Examples)

Updated
7 min read

Modern applications rarely run with fixed configuration.

A typical application needs values like:

  • Database host

  • Port number

  • API endpoints

  • Feature flags

  • Authentication credentials

If these values are hardcoded inside the application, every small change would require rebuilding and redeploying the application.

This is not scalable.

Kubernetes solves this problem using two powerful resources:

  • ConfigMaps

  • Secrets

In this guide, we will understand:

  • What ConfigMaps are

  • Why Secrets exist

  • The difference between ConfigMaps and Secrets

  • How to use them inside Pods and Deployments

  • Two ways to inject configuration into containers


The Problem: Hardcoded Configuration

Imagine a backend application connecting to a database.

The application needs values like:

DB_HOST
DB_PORT
DB_USERNAME
DB_PASSWORD

If these values are written directly in code, problems appear immediately:

  • Database port changes

  • Credentials rotate

  • Environment changes (dev → staging → production)

Every change would require modifying code and redeploying the application.

A better design is:

Separate configuration from the application.

This allows the same container image to run in multiple environments.


What is a ConfigMap in Kubernetes?

A ConfigMap is a Kubernetes resource used to store non-sensitive configuration data.

It stores configuration as key-value pairs.

Typical examples include:

  • application ports

  • configuration flags

  • log levels

  • database host

  • feature toggles

Example ConfigMap YAML:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DATABASE_PORT: "5432"
  LOG_LEVEL: "INFO"

Once created, this ConfigMap can be used by Pods or Deployments.

Applications can read these values through:

  • Environment variables

  • Mounted configuration files


Why Kubernetes Has Secrets

Some configuration values are sensitive.

Examples include:

  • Database passwords

  • API keys

  • TLS certificates

  • OAuth tokens

Storing these inside ConfigMaps would be dangerous.

This is where Secrets are used.

A Secret is designed to store sensitive data securely.

Example Secret:

apiVersion: v1
kind: Secret
metadata:
  name: database-secret
type: Opaque
data:
  DB_PASSWORD: cGFzc3dvcmQxMjM=

Notice something important:

The value is Base64 encoded.

While Base64 itself is not encryption, Kubernetes supports encryption at rest in etcd.


Where Kubernetes Stores ConfigMaps and Secrets

All Kubernetes resources are stored in etcd, the cluster’s key-value store.

Resource Storage
ConfigMaps Stored as plain text
Secrets Stored encoded and can be encrypted at rest

This difference is the main reason Secrets exist.


ConfigMap vs Secret

Feature ConfigMap Secret
Purpose Non-sensitive configuration Sensitive data
Example Data Ports, URLs, flags Passwords, tokens
Storage Plaintext in etcd Encrypted/encoded
Security Basic Stronger security controls
Injection Env vars or volumes Env vars or volumes

Simple rule:

ConfigMaps → configuration

Secrets → credentials


Demo 1 — Creating a ConfigMap

Let's create a simple ConfigMap.

Create a file:

vim database-config.yaml

ConfigMap definition:

apiVersion: v1
kind: ConfigMap
metadata:
  name: database-config
data:
  DB_PORT: "5432"

Apply it:

kubectl apply -f database-config.yaml

Verify it:

kubectl get configmap

Describe the ConfigMap:

kubectl describe configmap database-config

You should see the stored key-value pair.


Demo 2 — Using ConfigMap as Environment Variables

Now we inject this value into a container.

First, create a deployment file that will consume the ConfigMap.

Create a file:

vim deployment.yaml

Add the following Deployment configuration:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web-container
        image: nginx
        env:
        - name: DATABASE_PORT
          valueFrom:
            configMapKeyRef:
              name: database-config
              key: DB_PORT

Apply the deployment:

kubectl apply -f deployment.yaml

Check pods:

kubectl get pods

Enter the container:

kubectl exec -it <pod-name> -- /bin/bash

Check the environment variable:

env | grep DATABASE

Output:

DATABASE_PORT=5432

Your container is now reading configuration from the ConfigMap.


Limitation of Environment Variables

There is one important limitation.

If the ConfigMap value changes, environment variables do not update automatically.

The Pod must be restarted.

In production environments, restarting pods may cause:

  • traffic disruption

  • downtime

  • service instability

So Kubernetes offers another approach.


Demo 3 — Using ConfigMap as a Volume

Instead of environment variables, we can mount the ConfigMap as a file inside the container.

Update the same deployment file (deployment.yaml) created in Demo 2.

Open the file:

vim deployment.yaml

Modify it to include a ConfigMap volume:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web-container
        image: nginx
        volumeMounts:
        - name: config-volume
          mountPath: /app/config

      volumes:
      - name: config-volume
        configMap:
          name: database-config

Apply the updated deployment:

kubectl apply -f deployment.yaml

Enter the container:

kubectl exec -it <pod-name> -- /bin/bash

Check mounted file:

ls /app/config

You should see:

DB_PORT

Check its value:

cat /app/config/DB_PORT

Output:

5432

Dynamic Updates

Now update the ConfigMap file created in Demo 1 (database-config.yaml).

Open the file:

vim database-config.yaml

Update the value:

DB_PORT: "5433"

Apply the change:

kubectl apply -f database-config.yaml

Wait a few seconds and check inside the container again:

cat /app/config/DB_PORT

The value updates automatically without restarting the Pod.

This is why volume mounts are often preferred.


Creating a Secret

Secrets can also be created using CLI.

Example:

kubectl create secret generic db-credentials \
  --from-literal=username=admin \
  --from-literal=password=supersecret

Check it:

kubectl get secrets

Describe the secret:

kubectl get secret db-credentials -o yaml

You will see encoded values.


Decoding a Secret

Example encoded value:

c3VwZXJzZWNyZXQ=

Decode it:

echo c3VwZXJzZWNyZXQ= | base64 --decode

Output:

supersecret

This shows that Kubernetes uses Base64 encoding by default.

For production systems, many teams integrate:

  • HashiCorp Vault

  • AWS Secrets Manager

  • Sealed Secrets


Security Best Practices

When working with Secrets:

Use RBAC (Role-Based Access Control).

Follow the principle of least privilege.

Only authorized users should access Secrets.

Developers may need access to:

  • Pods

  • Deployments

  • ConfigMaps

But not necessarily Secrets.


Key Takeaways

ConfigMaps and Secrets are essential tools for managing application configuration in Kubernetes.

Key points to remember:

  • Never hardcode configuration in containers

  • Use ConfigMaps for normal configuration

  • Use Secrets for sensitive information

  • Environment variables are simple but static

  • Volume mounts support dynamic updates

  • Protect Secrets using RBAC and encryption

Understanding these concepts is critical for anyone working with Kubernetes in production.


Final Thoughts

Separating configuration from application code is a fundamental design principle in cloud-native systems.

Kubernetes provides ConfigMaps and Secrets to make this possible in a scalable and secure way.

Once you understand these resources, managing complex applications across multiple environments becomes significantly easier.

M
MOHAMED3mo ago

#MOHAMED

Kubernetes Deep Dive – From Basics to Production

Part 6 of 8

A hands-on Kubernetes series covering core concepts like Pods, ReplicaSets, and Deployments, progressing toward real-world application deployments with kubectl commands, YAML examples, and practical DevOps insights.

Up next

Kubernetes RBAC Explained: Roles, RoleBindings, and Secure Access Control

When organizations start using Kubernetes in production, security becomes one of the most important concerns. Multiple teams interact with the same Kubernetes cluster: Developers deploy applications