Kubernetes ConfigMap and Secret — Manage Configs and Credentials Without Rebuilding Images
> cd .. / HUB_EDITORIALE
Sviluppo di siti web

Kubernetes ConfigMap and Secret — Manage Configs and Credentials Without Rebuilding Images

[2026-08-02] Author: Ing. Calogero Bono
> share
Zenithby Meteora Web The operating system for your business. Social, clients, bookings and invoices in one platform. Gyms, barbers, professionals. Discover Zenith Free demo · no card

Your deployment works locally and breaks in production. Or it works in production and breaks when you rotate a password. The problem is not the code: it's configuration baked into the image. Every time you change an environment variable, you must rebuild the image, push it to the registry, and restart the pods. A nightmare. And if someone commits an API key to the repository, the lesson is harsh.

We, at Meteora Web, have run Kubernetes in production for years. The first thing we teach clients moving to orchestration is this: the container image must be immutable. Configurations are injected from the outside. Code stays untouched, credentials are not burned, and pods update without rebuilding anything.

In this guide we cover how to use ConfigMaps and Secrets to manage configurations and credentials in Kubernetes, with working examples and mistakes to avoid. We talk engineer to engineer: no academic theory, only practice that keeps services alive.

Why are ConfigMaps and Secrets separated in Kubernetes?

Kubernetes separates non-sensitive configuration from credentials for a simple reason: their lifecycle and protection level are different. A ConfigMap holds values like URLs, feature flags, timeouts. A Secret holds passwords, tokens, API keys. If you mix them, anyone with cluster access sees everything. If a Secret ends up in a ConfigMap, you lose the benefit of separation.

The practical difference? A Secret is base64-encoded (not encrypted, mind you) and can be mounted as a file or environment variable. A ConfigMap is meant to be read by multiple pods and updated without painful restarts. But the real separation lies in your workflow: if a value is a credential, it belongs in a Secret, not in a ConfigMap.

Kubernetes Secrets are not encrypted by default. They are just base64-encoded. For real security, you must enable encryption at rest in etcd. Kubernetes has supported Secret encryption at rest since 2017, and teams that don't enable it are taking a risk that eventually pays off — in the worst way.

Sponsored Protocol

How to create a ConfigMap and use it in pods?

The simplest way to create a ConfigMap is from a YAML file. Here is a concrete example:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: production
  APP_DEBUG: "false"
  DB_HOST: postgres.default.svc.cluster.local
  DB_PORT: "5432"
  CACHE_DRIVER: redis
  TIMEOUT: "30"

Apply it with kubectl apply -f configmap.yaml. Then use it in a deployment as environment variables:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
        - name: app
          image: nginx:alpine
          envFrom:
            - configMapRef:
                name: app-config

With envFrom you load all keys from the ConfigMap as environment variables. If you only need a few, use env with valueFrom:

env:
  - name: DB_HOST
    valueFrom:
      configMapKeyRef:
        name: app-config
        key: DB_HOST

A detail many forget: if a ConfigMap does not exist, the pod does not start. If it exists but a key is missing, the pod fails to resolve. Deployment order matters: ConfigMap first, then the deployment. In production, we recommend kubectl apply on the whole manifest directory, but with Helm this is handled automatically by the charts.

When you modify a ConfigMap, running pods do not get the change automatically, unless you use a reload mechanism like Stakater Reloader or run kubectl rollout restart deployment/app. This is one of the first things developers get wrong: they update the ConfigMap and expect the pod to be updated instantly. It is not.

How to mount a ConfigMap as a configuration file?

Some applications do not read environment variables; they want a configuration file. With Kubernetes you can mount a ConfigMap as a volume. Here is an example with application.properties:

Sponsored Protocol

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-properties
data:
  application.properties: |
    spring.datasource.url=jdbc:postgresql://postgres:5432/app
    spring.datasource.username=app
    spring.datasource.password=${DB_PASSWORD}
    server.port=8080

And in the deployment:

volumeMounts:
  - name: config
    mountPath: /app/config
volumes:
  - name: config
    configMap:
      name: app-properties

This way the file application.properties appears at /app/config/application.properties. You can change the configuration without rebuilding the image. Note: if you mount a ConfigMap as a volume, changes to the ConfigMap are propagated to the files with a small delay (up to 10 seconds), but the pod is not restarted. The process inside the application must be able to reload the file. This is where static versus dynamic configuration matters: for true hot reload, use tools like spring-boot-devtools or implement a watcher in your code.

How to create a Secret and protect credentials?

A Secret is created similarly, but with base64-encoded data. You don't have to encode it by hand — kubectl does it for you. The safest and most reproducible way is to create it from files:

echo -n 'S3cretP@ssw0rd' | base64
# Result: UzNjcmV0UEBzc3cwcmQ=

Or, even better, use the imperative command:

kubectl create secret generic db-secret \
  --from-literal=DB_PASSWORD='S3cretP@ssw0rd' \
  --from-literal=DB_USER='admin'

In a YAML file, a Secret looks like this:

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  DB_PASSWORD: UzNjcmV0UEBzc3cwcmQ=
  DB_USER: YWRtaW4=

To use a Secret as an environment variable:

env:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: db-secret
        key: DB_PASSWORD

And as a volume:

Sponsored Protocol

volumeMounts:
  - name: secrets
    mountPath: /etc/secrets
    readOnly: true
volumes:
  - name: secrets
    secret:
      secretName: db-secret

The Secrets volume mounts each key as a separate file in the specified directory. If your application wants to read the password from a file, this is the way.

What are common mistakes with ConfigMaps and Secrets?

Mistakes we see all the time in projects that come to us:

1. Committing Secrets to the Git repository

The most serious one. A Secret YAML with base64 data is just text. If you commit it, you have exposed the credential. Base64 is not encryption. Use sealed secrets or an external vault (HashiCorp Vault, AWS Secrets Manager, Google Secret Manager) to manage secrets securely. If you use Git, add *.secret.yaml to your .gitignore.

2. Using Secrets as ConfigMaps

Putting non-sensitive values (like the environment name) in a Secret is wasteful and increases the exposure surface. Kubernetes logs do not show Secret values, but metadata does. Keep Secrets for sensitive data only.

3. Updating ConfigMaps without restarting pods

As stated, the pod does not see changes unless it is restarted or mounts the ConfigMap as a volume. For applications that do not support hot reload, add a version annotation in the deployment:

spec:
  template:
    metadata:
      annotations:
        configmap.reload: "2026-01-15-v2"

This way, every ConfigMap change requires an annotation update and a kubectl rollout restart. It is a simple and reliable pattern.

4. Not enabling encryption at rest for Secrets

If an attacker gains access to the API server or etcd, they can read the Secrets. Enable encryption at rest as described in the official Kubernetes documentation. In a self-managed cluster, this is configured in the API server with an encryption config file.

How to rotate Secrets without downtime?

When you need to rotate a credential, you should not take the service down. The strategy is simple: update the Secret as a Kubernetes object, then perform a rolling update rollout. The deployment will recreate pods one by one, picking up the new value. To do this:

Sponsored Protocol

kubectl apply -f secret.yaml
kubectl rollout restart deployment/app

If your application supports hot reload of mounted files, you can avoid the reboot by simply replacing the file. For example, with a Secrets volume mounted, Kubernetes updates the file content, but the application must re-read it. Nginx with the reload directive works, but not all apps do it.

Another advanced technique is using a secret rotation controller to automate the process. But for most cases, a rollout restart is sufficient and easy to understand.

How to encrypt Secrets at rest in the cluster?

The configuration is done by modifying the API server. Here is an example encryption config:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: s3cretK3y...
      - identity: {}

Then pass the file path to kube-apiserver with the flag --encryption-provider-config. This is an advanced topic, but in the real world it is the minimum for anyone running clusters in production. Without this, your Secrets are just base64 in etcd.

For full lifecycle management, consider Sealed Secrets. With sealed-secrets, you can commit an encrypted version of the Secret to Git that only the controller in the cluster can decrypt. It is a great compromise between GitOps and security. The official project is on GitHub and the documentation is clear.

What is the difference between ConfigMap and Secret when mounted as volumes?

When you mount a ConfigMap as a volume, the files are readable and updatable by anyone with access to the container. When you mount a Secret as a volume, Kubernetes creates files with 0644 permissions by default, but you can make them more restrictive with defaultMode:

Sponsored Protocol

volumes:
  - name: secrets
    secret:
      secretName: db-secret
      defaultMode: 0400

With 0400, only the owner (root) can read. This matters if your application runs as a non-root user: the user must have permission to read the file, otherwise you will get unexpected errors. A common pattern is to use an image that starts with a dedicated user and mount Secrets with 0440 permissions. General rule: Secret files should only be readable by the container user, not by everyone. Note that Kubernetes mounts Secrets as tmpfs bind mounts, so they are never written to disk; but file system security is still your responsibility.

In summary

Here are immediate actions to implement today on your clusters:

  • Separate ConfigMaps from Secrets now: no credentials in ConfigMaps. A plaintext password is a breach waiting to happen.
  • Enable encryption at rest for Secrets: if your cluster is self-managed, activate --encryption-provider-config with AES-CBC. If you use a cloud provider, enable managed encryption.
  • Adopt Sealed Secrets or an external vault: no plaintext Secrets in the repository. Base64 is not encryption.
  • Use the kubectl rollout restart pattern after every change: for apps that do not support hot reload, this is the simplest and most reliable method.
  • Mount Secrets as volumes with defaultMode 0400: reduce the exposure surface if a container is compromised.

Kubernetes gives you the tools. It is up to you to use them properly. If you want to dive into the full orchestration path, start from our pillar guide on Kubernetes and container orchestration. For managing configuration lifecycle, check the official Kubernetes documentation on Secrets and the etcd encryption task.

> share
Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere informatico, fondatore di Meteora Web e Zenith OS. System administrator e progettista di piattaforme, app e CMS proprietari, con esperienza in sviluppo full-stack, marketing digitale ed ecosistema Google.
[ Read Full Dossier ]

> METEORA_WEB // DIGITAL AGENCY

We build the digital presence your business deserves.

Websites, social media, online advertising, e-commerce and high-performance hosting, engineered with method by computer engineers in Sciacca, for all of Italy.

> MW_JOURNAL

> READ_ALL()