Cloud Native 10 min read

Mastering Kubernetes ConfigMap & Secret: Secure, Dynamic Configuration Practices

This guide explains how ConfigMap and Secret enable secure, decoupled configuration management in Kubernetes, covering their definitions, differences, best‑practice creation, usage in Pods, encryption at rest, dynamic updates, CI/CD integration, and essential command tips.

Ray's Galactic Tech
Ray's Galactic Tech
Ray's Galactic Tech
Mastering Kubernetes ConfigMap & Secret: Secure, Dynamic Configuration Practices

What Are ConfigMap and Secret?

ConfigMap : stores non‑sensitive plain‑text configuration such as environment variables, config files, or log levels.

Secret : stores sensitive data like database passwords, API keys, or TLS certificates.

Both are stored as key‑value pairs and can be mounted into Pods as environment variables or volumes.

Quick Comparison

Purpose : ConfigMap for non‑sensitive config, Secret for sensitive data.

Encoding : ConfigMap data is plain text; Secret data is Base64‑encoded (light obfuscation).

Default File Permissions : ConfigMap 0644, Secret 0400.

Creation Sources : ConfigMap – from‑literal, from‑file, from‑env‑file; Secret – from‑literal, from‑file, TLS, docker‑registry.

Update Behaviour : Neither automatically updates running Pods.

Security : ConfigMap low, Secret higher (especially when combined with encryption at rest).

Maximum Size : Both limited to 1 MiB.

Best Practices

Store ordinary parameters in ConfigMap.

Store passwords and keys in Secret.

For compliance‑required keys, use Encryption at Rest, SealedSecret, or external vault solutions.

ConfigMap Practical Example

YAML Definition

# configmap-basic.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: default
data:
  APP_NAME: "my-application"
  APP_VERSION: "1.0.0"
  LOG_LEVEL: "INFO"
  application.properties: |
    server.port=8080
    database.host=mysql-service
    database.port=3306
    cache.enabled=true
  nginx.conf: |
    server {
      listen 80;
      server_name localhost;
      location / {
        proxy_pass http://backend;
      }
    }

Creation and Inspection Commands

# Create from files or literals
kubectl create configmap game-config --from-file=./configs/game.properties --from-file=./configs/ui.properties
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

# List ConfigMaps
kubectl get configmaps

# Describe a specific ConfigMap
kubectl describe configmap app-config

# Output as YAML
kubectl get configmap app-config -o yaml

# Delete
kubectl delete configmap app-config

Secret Practical Example

YAML Definition (Base64‑encoded data)

# secret-basic.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
data:
  username: YWRtaW4=   # admin
  password: cGFzc3dvcmQxMjM=   # password123
  api-key: bXktYXBpLWtleS1zZWNyZXQ=   # my-api-key-secret

Alternatively, use stringData to let Kubernetes encode automatically:

apiVersion: v1
kind: Secret
metadata:
  name: database-secret
type: Opaque
stringData:
  database-url: "postgresql://user:pass@host:5432/db"
  redis-url: "redis://:password@redis-host:6379/0"

Creation and Inspection Commands

# Create generic secret from literals
kubectl create secret generic app-secret --from-literal=username=admin --from-literal=password=secret123

# List secrets
kubectl get secrets

# Describe a secret
kubectl describe secret app-secret

# Decode a secret value
kubectl get secret app-secret -o jsonpath='{.data.username}' | base64 --decode

Using ConfigMap and Secret Inside a Pod

1. Inject as Environment Variables

apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  containers:
  - name: app-container
    image: my-app:1.0
    env:
    - name: APP_NAME
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: APP_NAME
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: database-secret
          key: password
    envFrom:
    - configMapRef:
        name: app-config
    - secretRef:
        name: app-secret

2. Mount as Files (Volume)

apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-pod
spec:
  containers:
  - name: app-container
    image: nginx:1.19
    volumeMounts:
    - name: config-volume
      mountPath: /etc/app-config
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true
  volumes:
  - name: config-volume
    configMap:
      name: app-config
  - name: secret-volume
    secret:
      secretName: app-secret

Secret Encryption at Rest

Secrets are only Base64‑encoded by default; to truly encrypt them, enable static encryption (Encryption at Rest) in the API server.

Enable Encryption

Edit the kube‑apiserver startup parameters:

--encryption-provider-config=/etc/kubernetes/encryption-config.yaml

Create an encryption configuration file:

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

Restart the kube‑apiserver: systemctl restart kube-apiserver After these steps, Secrets stored in etcd are encrypted.

Dynamic ConfigMap Update Methods

Manual Restart : Run kubectl rollout restart deployment/my-app for low‑frequency changes.

Reloader Operator : Automatically watches ConfigMap/Secret updates and triggers Pod restarts; recommended for production.

In‑Application Watch : Application code detects file changes in the mounted volume and reloads configuration (common in Go or Spring Boot).

CI/CD Configuration Injection

Generate ConfigMaps or Secrets during deployment with GitLab CI or ArgoCD.

# .gitlab-ci.yml
deploy:
  stage: deploy
  script:
    - kubectl create configmap app-config --from-env-file=.env.production -o yaml --dry-run=client | kubectl apply -f -
    - kubectl rollout restart deployment/my-app

Practical Command Cheatsheet

# View files mounted from a ConfigMap
kubectl exec -it my-pod -- cat /etc/app-config/application.properties

# Find which Pods use a specific ConfigMap
kubectl get pod -o yaml | grep -A 3 "configMapRef" | grep app-config

# Decode a Secret and pretty‑print
kubectl get secret app-secret -o json | jq -r '.data | map_values(@base64d)'

# Watch ConfigMap changes in real time
kubectl get configmap app-config -w

Key Takeaways

Use ConfigMap for non‑sensitive data and Secret for sensitive data.

Avoid hard‑coding configuration inside container images.

Rotate Secrets regularly, especially database credentials and API keys.

Enable Encryption at Rest to prevent plaintext exposure in etcd.

Deploy the Reloader Operator for automatic configuration refresh.

Inject configuration automatically in CI/CD pipelines.

Integrate external secret managers such as HashiCorp Vault or SealedSecret for higher security.

In modern cloud‑native environments, “configuration as code” is the standard, and ConfigMap together with Secret lets you keep images stateless while managing configuration and credentials safely and automatically.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ci/cdKubernetesConfiguration ManagementConfigMapSecret
Ray's Galactic Tech
Written by

Ray's Galactic Tech

Practice together, never alone. We cover programming languages, development tools, learning methods, and pitfall notes. We simplify complex topics, guiding you from beginner to advanced. Weekly practical content—let's grow together!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.