What is a Kubernetes ConfigMap?
How does it differ from Secrets?
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:
kubectl create configmap app-config \ --from-literal=DATABASE_HOST=postgres.default.svc \ --from-literal=DATABASE_PORT=5432This 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: v1kind: ConfigMapmetadata: name: app-configdata: 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 likeconfig.jsonornginx.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: v1kind: Podmetadata: name: my-appspec: 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_PORTAnd here is an example mounting the entire ConfigMap as a volume (each key becomes a file):
apiVersion: v1kind: Podmetadata: name: my-appspec: containers: - name: my-app image: my-app:1.0 volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: name: app-configIn the volume mount case, the container would see /etc/config/DATABASE_HOST, /etc/config/DATABASE_PORT, and /etc/config/config.json as individual files.
| ConfigMap | Secret | |
|---|---|---|
| Purpose | Non-sensitive configuration | Sensitive data (passwords, tokens, keys) |
| Encoding | Plain text | Base64 (not encryption) |
| Stored in etcd | Yes | Yes (with optional encryption at rest) |
| Access control | Same RBAC as secrets | Same 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.