Kubernetes ConfigMaps and Secrets both store configuration data, but they’re fundamentally different in how they handle sensitive information, and picking the wrong one can lead to security headaches or just plain broken deployments.
Let’s see what a ConfigMap looks like in action. Imagine you have an application that needs a connection string and a logging level.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-config
data:
database_url: "postgres://user:password@host:port/dbname"
log_level: "INFO"
This ConfigMap named my-app-config stores two key-value pairs: database_url and log_level. Your application pod can then mount this ConfigMap as a volume or reference its keys as environment variables.
Now, contrast that with a Secret. If that database_url contained actual credentials, you’d use a Secret instead.
apiVersion: v1
kind: Secret
metadata:
name: my-app-credentials
type: Opaque
data:
db_user: dXNlcg== # base64 encoded "user"
db_password: cGFzc3dvcmQ= # base64 encoded "password"
db_connection_string: cG9zdGdyZXM6Ly91c2VyOnBhc3N3b3JkQGhvc3Q6cG9ydC9kYm5hbWU= # base64 encoded "postgres://user:password@host:port/dbname"
Notice the type: Opaque. This is the default for Secrets, indicating arbitrary data. The values here are base64 encoded. This is not encryption; it’s just encoding. Anyone with access to the Kubernetes API or the etcd datastore can easily decode these values. The primary security benefit of Secrets is that they are not intended for direct human consumption and can be managed with more granular RBAC controls, and in some configurations, they can be stored in memory rather than written to disk.
The core problem these objects solve is decoupling configuration from application code. Instead of baking connection strings, API keys, or feature flags directly into your container images, you externalize them. This allows you to change configuration without rebuilding and redeploying your application images, a fundamental tenet of cloud-native development.
Internally, both ConfigMaps and Secrets are stored as objects in Kubernetes’s API server, which in turn persists them in etcd, the cluster’s distributed key-value store. When a pod needs to access a ConfigMap or Secret, the Kubelet on the node where the pod is scheduled retrieves the object’s data and makes it available to the container. This can be done by mounting the data as files within the container’s filesystem or by injecting it as environment variables. The key difference in how they are handled lies in their intended use and how Kubernetes treats them by default: ConfigMaps are for non-sensitive configuration, while Secrets are for sensitive data. Kubernetes also has specific mechanisms for Secrets that can, for example, prevent them from being automatically mounted as files in pods if not explicitly requested, and certain storage backends can be configured to encrypt secrets at rest.
When you define a Secret of type: kubernetes.io/dockerconfigjson, Kubernetes knows how to interpret the data specifically for Docker registry authentication. This allows your pods to pull images from private registries without exposing credentials directly in your deployment manifests. The structure within the data field is a JSON string, base64 encoded, that follows the standard Docker config.json format, containing fields like auths with registry URLs and base64 encoded username/password pairs.
If you’re using a cloud provider’s managed Kubernetes service, like GKE, EKS, or AKS, you might be tempted to store all your sensitive data in Kubernetes Secrets. However, a common pattern is to integrate these Secrets with external secret management systems like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault. In this setup, Kubernetes Secrets act as pointers or references to the actual secrets stored externally. This provides a more robust security posture, centralized management, and auditing capabilities beyond what native Kubernetes Secrets offer on their own, as the sensitive data itself never touches etcd.
The next hurdle you’ll face is managing the lifecycle of these configuration objects across different environments.