← Back to Blog Kubernetes

Kubernetes ConfigMap vs Secrets: The Complete 2026 Guide

In the world of Kubernetes, separating your application code from your configuration is a fundamental best practice. It allows you to build a single Docker image and deploy it across dev, staging, and production environments simply by swapping out the configuration.

Kubernetes provides two primary resources to handle this: ConfigMaps and Secrets. While they seem incredibly similar at a glance, using them incorrectly can lead to severe security vulnerabilities or rigid deployments. In this complete guide, we will break down the differences, show you how to mount them using both environment variables and volumes, and expose the most common security misconception surrounding Kubernetes Secrets.

Need to generate manifests quickly? Check out our Kubernetes ConfigMap Generator and Kubernetes Secret Generator to instantly build your YAML files right in your browser.

The Core Difference

Let's get straight to the point:

  • ConfigMaps are used for non-confidential data. Think database URLs, debug flags, language settings, and Nginx configuration files.
  • Secrets are used for confidential, sensitive data. Think database passwords, API keys, SSH keys, and TLS certificates.

Mechanically, they are injected into Pods in the exact same ways. The primary difference is intent and how the Kubernetes API handles them.

The Great Secret Misconception

The most dangerous misconception in Kubernetes is the belief that Secrets are encrypted. They are not.

By default, Kubernetes Secrets are simply Base64 encoded. If an attacker gains access to your cluster's API, or if a developer runs kubectl get secret my-secret -o yaml, they can trivially decode the Base64 string and steal your credentials. Furthermore, they are stored in plaintext in the cluster's underlying etcd datastore.

How to Actually Secure Secrets

To make Secrets truly secure in a production environment, you must implement two things:

  1. Strict RBAC (Role-Based Access Control): Ensure that only specific service accounts and highly privileged administrators have the get and watch permissions for the secrets resource.
  2. Encryption at Rest: You must configure your Kubernetes API server to encrypt Secret data before it is written to etcd. Most managed cloud providers (like EKS, GKE, and AKS) offer this via KMS integration.

Method 1: Mounting as Environment Variables

The easiest way to consume a ConfigMap or Secret is by injecting it as an environment variable.

When to use this method:

  • For simple key-value pairs (e.g., DB_HOST=postgres).
  • When your application expects standard environment variables.

The drawback:

Environment variables are static. If you update the ConfigMap or Secret later, the running Pod will not see the changes. You must manually restart or recreate the Pod for the new values to take effect.

Example Manifest

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
    - name: my-app-container
      image: my-app:latest
      env:
        # Pulling from a ConfigMap
        - name: DATABASE_URL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: db-url
        # Pulling from a Secret
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: db-password

Method 2: Mounting as Volumes

Alternatively, you can mount a ConfigMap or Secret as a file within the container's filesystem.

When to use this method:

  • For large configuration files, such as an nginx.conf, an application settings.json, or a TLS certificate.
  • When you need hot-reloading. When mounted as a volume, Kubernetes uses a symlink mechanism (kubelet sync) to update the files inside the container automatically if the underlying ConfigMap or Secret is updated.

Example Manifest

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-app
spec:
  containers:
    - name: nginx-container
      image: nginx:latest
      volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/conf.d
        - name: secret-volume
          mountPath: /etc/nginx/ssl
  volumes:
    - name: config-volume
      configMap:
        name: nginx-config
    - name: secret-volume
      secret:
        secretName: nginx-tls-secret
Update Delays: When mounting as a volume, be aware that it can take up to a minute (based on the kubelet sync frequency) for an updated ConfigMap to propagate to the Pod's filesystem.

Creating ConfigMaps and Secrets via CLI

While you should ideally manage these resources declaratively via GitOps, you can create them imperatively using kubectl:

# Create a ConfigMap from a literal value
kubectl create configmap my-config --from-literal=LOG_LEVEL=debug

# Create a ConfigMap from an entire file
kubectl create configmap nginx-config --from-file=nginx.conf

# Create a Secret (Docker registry example)
kubectl create secret generic db-secret \
  --from-literal=username=admin \
  --from-literal=password=supersecret

Connecting to Ingress Controllers

One of the most critical uses for Kubernetes Secrets is terminating TLS/SSL traffic. When using an Ingress Controller, you will create a Secret of type kubernetes.io/tls containing your public certificate and private key, and reference it in your Ingress manifest.

If you are setting up routing, use our Kubernetes Ingress Generator to automatically scaffold the routing rules and TLS secret bindings.

Conclusion

Mastering ConfigMaps and Secrets is essential for building scalable, environment-agnostic deployments. Remember: use ConfigMaps for plain text configuration, use Secrets for sensitive data, configure Encryption at Rest, and choose your mounting strategy based on whether you need dynamic file updates or simple environment variables.