Kubernetes DevOps AutomationDevOps GuidesDevSecOpsKubernetes Guide

Article & Tutorial

Kubernetes ConfigMaps and Secrets Explained: YAML, Mounts, Security and Best Practices

Learn Kubernetes ConfigMaps and Secrets with YAML, environment variables, file mounts, update behavior, immutable objects, Secret types, RBAC, encryption,…

Kubernetes ConfigMaps and Secrets configuration workflow
Kubernetes ConfigMaps and Secrets configuration workflow

Kubernetes ConfigMaps and Secrets Explained ConfigMaps and Secrets separate runtime configuration from container images. ConfigMaps hold non-sensitive settings, while Secrets hold credentials, tokens, certificates and other sensitive values that require tighter protection. Learning path: This is Chapter 9 of the Kubernetes Learning Path. Read the Pods, Deployments and Services chapters first for the smoothest learning sequence. Why externalize application configuration? Hard-coding configuration into a Docker image forces you to rebuild the image whenever an environment, URL, feature flag or credential changes. Kubernetes lets the same image run in development, staging and production while receiving different configuration at runtime. ConfigMap Stores non-sensitive key-value pairs, configuration files and feature settings. Secret Stores sensitive values such as passwords, API tokens, SSH keys and TLS certificates. Environment variables Expose individual keys or complete objects to the application process. Mounted files Present configuration or secrets as files inside the container filesystem. ConfigMap versus Secret Feature ConfigMap Secret Purpose Non-sensitive configuration Sensitive information Typical values URLs, log levels, feature flags, config files Passwords, tokens, certificates, private keys Storage format Plain key-value data Base64-encoded data or stringData input Security Normal API object protections Requires strict RBAC, encryption at rest and careful handling Important: Base64 is encoding, not encryption. Anyone who can read a Kubernetes Secret through the API can decode its contents. Create a ConfigMap with YAML apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: demo data: APP_ENV: production LOG_LEVEL: info API_URL

https://api.example.com

FEATURE_PAYMENTS: "true" ConfigMap values are strings. Quote values such as booleans and numbers when you want predictable string behavior. Create a ConfigMap from the command line kubectl create configmap app-config \ --from-literal=APP_ENV=production \ --from-literal=LOG_LEVEL=info \ -n demo Create a ConfigMap from a file kubectl create configmap nginx-config \ --from-file=nginx.conf \ -n demo The file name becomes the key unless you provide a different key: kubectl create configmap nginx-config \ --from-file=custom.conf=nginx.conf \ -n demo Use individual ConfigMap keys as environment variables apiVersion: apps/v1 kind: Deployment metadata: name: demo-app namespace: demo spec: replicas: 2 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: app image: nginx:1.27 env: - name: APP_ENV valueFrom: configMapKeyRef: name: app-config key: APP_ENV - name: API_URL valueFrom: configMapKeyRef: name: app-config key: API_URL Load all ConfigMap keys with envFrom envFrom: - configMapRef: name: app-config Design tip: Use explicit env entries when you want stronger control and clearer documentation. Use envFrom when many keys must be imported together. Mount a ConfigMap as files apiVersion: v1 kind: Pod metadata: name: config-demo namespace: demo spec: containers: - name: app image: nginx:1.27 volumeMounts: - name: config-volume mountPath: /etc/app-config readOnly: true volumes: - name: config-volume configMap: name: app-config Each key becomes a file under /etc/app-config . For example, the LOG_LEVEL key appears as /etc/app-config/LOG_LEVEL . Mount only selected keys volumes: - name: nginx-config configMap: name: nginx-config items: - key: custom.conf path: nginx.conf Create an Opaque Secret with stringData apiVersion: v1 kind: Secret metadata: name: database-secret namespace: demo type: Opaque stringData: DB_USERNAME: app_user DB_PASSWORD: replace-with-secure-value stringData accepts plain text during creation. Kubernetes converts it to the base64-encoded data field when the object is stored. Create a Secret from the command line kubectl create secret generic database-secret \ --from-literal=DB_USERNAME=app_user \ --from-literal=DB_PASSWORD='replace-with-secure-value' \ -n demo Reference individual Secret keys env: - name: DB_USERNAME valueFrom: secretKeyRef: name: database-secret key: DB_USERNAME - name: DB_PASSWORD valueFrom: secretKeyRef: name: database-secret key: DB_PASSWORD Mount a Secret as files volumeMounts: - name: secret-volume mountPath: /etc/secrets readOnly: true volumes: - name: secret-volume secret: secretName: database-secret defaultMode: 0400 File-based mounts are often safer than environment variables because environment variables may appear in process inspection, debug dumps or accidental logs. Common Kubernetes Secret types Type Purpose Opaque General-purpose credentials and application secrets. kubernetes.io/tls TLS certificate and private key. kubernetes.io/dockerconfigjson Private container registry credentials. kubernetes.io/basic-auth Username and password credentials. kubernetes.io/ssh-auth SSH private key data. bootstrap.kubernetes.io/token Cluster bootstrap token data. Create a TLS Secret kubectl create secret tls app-tls \ --cert=tls.crt \ --key=tls.key \ -n demo Create an image pull Secret kubectl create secret docker-registry registry-credentials \ --docker-server=registry.example.com \ --docker-username=app-user \ --docker-password='replace-with-token' \ -n demo Reference it from a Pod specification: spec: imagePullSecrets: - name: registry-credentials How updates reach running Pods Consumption method Update behavior Environment variable The running process does not automatically receive the new value. Restart or roll out the workload. Mounted ConfigMap or Secret volume Kubernetes eventually updates the projected files, but the application must reload them. subPath volume mount Does not receive automatic ConfigMap or Secret updates. Restart a Deployment after configuration changes kubectl rollout restart deployment/demo-app -n demo kubectl rollout status deployment/demo-app -n demo Many teams automate this by adding a configuration checksum annotation to the Pod template. When the checksum changes, the Deployment creates new Pods. Immutable ConfigMaps and Secrets apiVersion: v1 kind: ConfigMap metadata: name: app-config-v1 immutable: true data: LOG_LEVEL: info Immutable objects prevent accidental edits and can reduce API-server load in large clusters. To change the values, create a new object name and update the workload reference. Namespace behavior A Pod can normally reference only ConfigMaps and Secrets in the same namespace. This keeps application configuration scoped to its workload environment. Deployment or Pod → ConfigMap / Secret → Environment Variables or Mounted Files Secret security model Protecting Secrets requires several layers: Authentication: Verify the user or workload identity. RBAC: Allow only required identities to read specific Secrets. Encryption at rest: Encrypt Secret data stored in etcd. Transport encryption: Use TLS for Kubernetes API communication. Audit logging: Record Secret access and administrative changes. Rotation: Replace credentials regularly and after suspected exposure. Least-privilege RBAC for one Secret apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: database-secret-reader namespace: demo rules: - apiGroups: [""] resources: ["secrets"] resourceNames: ["database-secret"] verbs: ["get"] Avoid granting broad list or watch access to Secrets unless the workload genuinely requires it. External secret management Production platforms often store the source of truth outside Kubernetes in systems such as cloud secret managers, HashiCorp Vault or hardware-backed key management services. A controller or CSI driver then delivers the values to workloads. External Secrets Operator Synchronizes values from an external provider into Kubernetes Secrets. Secrets Store CSI Driver Mounts external provider data into Pods, often without permanently storing it as a Kubernetes Secret. GitOps encryption Tools such as SOPS or Sealed Secrets help store encrypted secret manifests in Git. Secret rotation pattern Create or generate the new credential in the source system. Update the Kubernetes Secret or external-secret reference. Restart workloads that consume the Secret through environment variables. Verify new Pods connect successfully. Revoke the old credential only after the rollout is healthy. Review logs and audit events for failed or unexpected access. Useful kubectl commands kubectl get configmaps,secrets -n demo kubectl describe configmap app-config -n demo kubectl get configmap app-config -n demo -o yaml kubectl get secret database-secret -n demo -o json kubectl get secret database-secret -n demo \ -o jsonpath='{.data.DB_USERNAME}' | base64 --decode kubectl auth can-i get secrets -n demo kubectl auth can-i get secret/database-secret -n demo kubectl rollout restart deployment/demo-app -n demo kubectl get events -n demo --sort-by=.metadata.creationTimestamp Operational warning: Avoid printing production Secret values in terminal history, CI logs, tickets or chat messages. Even diagnostic commands can leak sensitive data. Common errors and troubleshooting Symptom Likely cause What to check configmap not found Wrong name or namespace Run kubectl get configmap -n NAMESPACE . secret not found Secret missing or in another namespace Confirm Pod namespace and Secret name. couldn't find key Referenced key does not exist Inspect object keys and YAML capitalization. Application still uses old value Environment variable was not refreshed Restart or roll out the Deployment. Mounted file does not update Application caches the file or mount uses subPath Review mount method and application reload behavior. Forbidden when reading Secret RBAC does not allow access Use kubectl auth can-i for the exact ServiceAccount. ImagePullBackOff Bad registry Secret or wrong imagePullSecrets name Describe the Pod and verify registry credentials. Common mistakes Putting passwords or tokens in ConfigMaps. Committing unencrypted Secret manifests to Git. Assuming base64 protects sensitive values. Giving developers or ServiceAccounts broad Secret read access. Using the default ServiceAccount for every workload. Printing secrets in application or CI/CD logs. Expecting environment variables to refresh automatically. Using one shared Secret for unrelated applications and teams. Failing to rotate credentials after employee, vendor or system changes. Production best practices Use ConfigMaps only for non-sensitive configuration. Use dedicated Secrets per application and environment. Restrict Secret access with least-privilege RBAC and dedicated ServiceAccounts. Enable encryption at rest for Secret data in etcd. Use an external secret manager where appropriate. Use immutable objects for stable versioned configuration. Automate rotation and workload restart safely. Keep configuration changes in Git, but encrypt sensitive material. Audit Secret access and remove stale permissions. Never treat Kubernetes Secrets as a complete secrets-management strategy by themselves. Hands-on practice lab kubectl create namespace config-lab kubectl create configmap app-config \ --from-literal=APP_ENV=lab \ --from-literal=LOG_LEVEL=debug \ -n config-lab kubectl create secret generic app-secret \ --from-literal=API_TOKEN='lab-token' \ -n config-lab kubectl run config-demo \ --image=busybox:1.36 \ --restart=Never \ -n config-lab \

Did this help?

Yes No

Join the discussion

0 Comments

Ask questions, add context, or share what worked.

Sign in to join the discussion

No comments yet. Start the discussion.

More from Melochip Editorial

Related articles

Stay in the loop. Get new Melochip articles

Receive Melochip article updates when new articles are available. Explicit opt-in only.

No pre-checked boxes. Unsubscribe support is part of the subscriber foundation.