Home/Learn/Kubernetes/ConfigMaps & Secrets

ConfigMaps & Secrets

Beginner
Configuration

ConfigMaps store non-sensitive configuration; Secrets store sensitive data (passwords, tokens, certs). Both decouple configuration from container images and can be injected as environment variables or mounted as files.

Overview

Baking configuration directly into container images means rebuilding images for every environment change. ConfigMaps and Secrets decouple configuration from images, following the 12-factor app methodology. ConfigMaps store non-secret config (database URLs, feature flags, config files). Secrets store sensitive data (database passwords, API keys, TLS certificates) — they are base64-encoded (not encrypted by default; use etcd encryption or external secrets managers for production). Both can be injected as environment variables or mounted as files inside pods.

ConfigMap

ConfigMaps store key-value configuration data. They can be created from YAML, literal values, or config files.

configmap.yaml — ConfigMap usage patterns
# configmap.yaml

apiVersion: v1

kind: ConfigMap

metadata:

  name: my-app-config

data:

  LOG_LEVEL: "info"

  DATABASE_HOST: "postgres.production.svc.cluster.local"

  DATABASE_PORT: "5432"

  MAX_CONNECTIONS: "100"

  # Multi-line value: a full config file

  nginx.conf: |

    server {

      listen 80;

      location /health { return 200 'OK'; }

    }



---

# Use ConfigMap in a Deployment — method 1: envFrom (all keys as env vars)

spec:

  containers:

    - name: app

      image: my-app:v1.2.3

      envFrom:

        - configMapRef:

            name: my-app-config



# method 2: specific key as env var

      env:

        - name: LOG_LEVEL

          valueFrom:

            configMapKeyRef:

              name: my-app-config

              key: LOG_LEVEL



# method 3: mount as file

      volumeMounts:

        - name: config-vol

          mountPath: /etc/nginx/conf.d/

  volumes:

    - name: config-vol

      configMap:

        name: my-app-config

        items:

          - key: nginx.conf

            path: nginx.conf

# Result: /etc/nginx/conf.d/nginx.conf is the ConfigMap value

Secrets

Secrets are like ConfigMaps but for sensitive data. Values are base64-encoded (not encrypted at rest by default). Mount as files rather than env vars for better security posture.

secret.yaml — Kubernetes Secrets
# Create secret from CLI (base64 encoding is automatic)

kubectl create secret generic db-credentials \

  --from-literal=username=admin \

  --from-literal=password=supersecret



# Create TLS secret from cert files

kubectl create secret tls my-tls-cert \

  --cert=tls.crt --key=tls.key



# secret.yaml (values must be base64-encoded manually if writing YAML)

apiVersion: v1

kind: Secret

metadata:

  name: db-credentials

type: Opaque

data:

  username: YWRtaW4=        # echo -n 'admin' | base64

  password: c3VwZXJzZWNyZXQ= # echo -n 'supersecret' | base64

# stringData: (alternative — plain text, K8s base64-encodes it)

stringData:

  username: admin

  password: supersecret



---

# Use in a Deployment — mount as file (preferred: not in env, not in ps output)

spec:

  containers:

    - name: app

      volumeMounts:

        - name: db-creds

          mountPath: /run/secrets

          readOnly: true

  volumes:

    - name: db-creds

      secret:

        secretName: db-credentials

# App reads: fs.readFileSync('/run/secrets/password').toString().trim()



# As env var (less secure but convenient)

      env:

        - name: DB_PASSWORD

          valueFrom:

            secretKeyRef:

              name: db-credentials

              key: password

Production Secrets Management

Base64 in etcd is not real encryption. Production secrets management uses external stores with the External Secrets Operator or Vault Agent.

Production secrets management patterns
# Problem: K8s Secrets are base64 in etcd (anyone with etcd access can read them)

# Solutions:



# Option 1: etcd Encryption at Rest (built-in)

# /etc/kubernetes/encryption-config.yaml on control plane:

# kind: EncryptionConfiguration

# resources:

#   - resources: [secrets]

#     providers:

#       - aescbc: {keys: [{name: key1, secret: <32-byte-base64-key>}]}

#       - identity: {}



# Option 2: External Secrets Operator (ESO) — pulls from AWS/GCP/Vault

# Install: helm install eso external-secrets/external-secrets

# ExternalSecret resource pulls secret from AWS Secrets Manager:

apiVersion: external-secrets.io/v1beta1

kind: ExternalSecret

metadata:

  name: db-password

spec:

  refreshInterval: 1h

  secretStoreRef:

    name: aws-secretsmanager

    kind: ClusterSecretStore

  target:

    name: db-credentials        # creates this K8s Secret

  data:

    - secretKey: password

      remoteRef:

        key: /production/db/password   # AWS Secrets Manager path



# Option 3: Vault Agent Injector

# Vault injects secrets as files into pod via init container sidecar

# Annotations on pod:

# vault.hashicorp.com/agent-inject: "true"

# vault.hashicorp.com/role: "my-app"

# vault.hashicorp.com/agent-inject-secret-db-password: "secret/data/my-app/db"

Key Points to Remember

  • 1ConfigMaps for non-sensitive config; Secrets for passwords, keys, and certs.
  • 2Both decouple config from images — change config without rebuilding the image.
  • 3Prefer mounting secrets as files over env vars — not visible in process list or docker inspect.
  • 4Base64 is encoding, not encryption — etcd encryption at rest or external secret managers are needed for true security.
  • 5Updates to ConfigMaps/Secrets are not automatically picked up by running pods — you need a rolling restart.
  • 6envFrom: configMapRef injects all keys at once; env.valueFrom.configMapKeyRef injects one key.

Interview Questions

Sign in to ask Aria
1

Are Kubernetes Secrets actually secure?

2

Why should you mount secrets as files rather than environment variables?

Ask Aria about ConfigMaps & Secrets

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…