Skip to content
Lucas Mauro

What is a Kubernetes ConfigMap?

How does it differ from Secrets?

kubernetes 2 min read

A ConfigMap is a Kubernetes object used to store non-sensitive configuration data as key-value pairs. It separates configuration from application code, allowing us to change settings without rebuilding or redeploying our containers.

ConfigMaps are similar to Secrets, but whereas secrets are intended for sensitive information (passwords, API keys, tokens), ConfigMaps are meant for everything else: database hostnames, feature flags, configuration files, and so on.

There are a few ways to create a ConfigMap. One of them being from the command line:

Terminal window
kubectl create configmap app-config \
--from-literal=DATABASE_HOST=postgres.default.svc \
--from-literal=DATABASE_PORT=5432

This creates a ConfigMap called app-config with two key-value pairs. We can also create ConfigMaps from a file (--from-file=config.yaml) or from a directory of files (--from-file=configs/).

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_HOST: postgres.default.svc
DATABASE_PORT: '5432'
config.json: |
{
"logLevel": "info",
"maxRetries": 3
}

Meaning:

  • data holds the key-value pairs (all values are strings; numeric values must be quoted);
  • The | block allows us to embed multi-line configuration files directly in the manifest (useful for things like config.json or nginx.conf).

We can expose ConfigMap data to containers in two main ways:

  • Environment variables: inject a ConfigMap value as an environment variable;
  • Volume mounts: mount the ConfigMap as a file inside the container’s filesystem.

Here is an example using an environment variable:

apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: my-app
image: my-app:1.0
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
- name: DATABASE_PORT
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_PORT

And here is an example mounting the entire ConfigMap as a volume (each key becomes a file):

apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: my-app
image: my-app:1.0
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config

In the volume mount case, the container would see /etc/config/DATABASE_HOST, /etc/config/DATABASE_PORT, and /etc/config/config.json as individual files.

ConfigMapSecret
PurposeNon-sensitive configurationSensitive data (passwords, tokens, keys)
EncodingPlain textBase64 (not encryption)
Stored in etcdYesYes (with optional encryption at rest)
Access controlSame RBAC as secretsSame RBAC as ConfigMaps

The line between the two can sometimes blur (e.g. a database hostname is not sensitive, but the port might be). A good rule of thumb: if it would be a problem if it leaked, use a secret.

Comments