What is the Difference Between ConfigMap and Secret?
For regular settings:
Junior Level
Simple Explanation
ConfigMap and Secret are Kubernetes objects for storing application settings separately from code. The difference is that ConfigMap is for regular settings, while Secret is for passwords and sensitive data.
Simple Analogy
- ConfigMap — like a sticky note on the monitor with settings (server address, port)
- Secret — like a safe with passwords and keys
ConfigMap
For regular settings:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DB_HOST: "postgres.default.svc.cluster.local"
DB_PORT: "5432"
APP_ENV: "production"
Secret
For passwords and keys:
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
DB_PASSWORD: cGFzc3dvcmQxMjM= # base64 of "password123"
API_KEY: c2VjcmV0LWtleQ== # base64 of "secret-key"
Important: base64 is not encryption! It is just encoding. Anyone can decode it.
How to Use in a Pod?
As environment variables:
containers:
- name: app
image: myapp
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: DB_PASSWORD
As files (volume):
volumes:
- name: config-volume
configMap:
name: app-config
- name: secret-volume
secret:
secretName: app-secret
Comparison
| ConfigMap | Secret | |
|---|---|---|
| Data | Plain text | Base64 |
| Purpose | Settings | Passwords, keys |
| Security | Low | Medium (needs RBAC) |
What a Junior Developer Should Remember
- ConfigMap — for regular settings, Secret — for passwords
- Secrets are stored in base64 (this is not encryption!)
- Both can be used as environment variables or as files
- Files from ConfigMap/Secret are updated without Pod restart
- Do not store secrets in git — use external secrets
When NOT to Use ConfigMap/Secret
Do NOT store in ConfigMap: large files (>1MB limit), binary files. Do NOT store in Secret: external system secrets (third-party API keys) — use Vault instead.
Middle Level
Data Storage
ConfigMap:
- Data in plain text in etcd
- Size limit: 1 MB (etcd limitation)
Secret:
- Data in base64 (NOT encryption! base64 is easily decoded). For encryption, use EncryptionConfiguration or external solution (Vault, Sealed Secrets).
- Secrets are stored in etcd in plain text (unless EncryptionConfiguration is enabled). Access to etcd = access to all Secrets.
- For real protection, you need to enable Encryption at Rest in etcd
Two Ways to Use
1. Environment Variables
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
Pro: simple Con: not updated “on the fly” without Pod restart
2. Volumes (file mounting)
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
Pro: updated automatically (Kubelet updates files) Con: application must be able to re-read config
Immutable ConfigMap/Secret
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
immutable: true # Cannot be modified after creation
Advantages:
- Protection from accidental changes
- Reduces load on kube-apiserver
- Kubelet doesn’t monitor for changes
External Secrets
For large projects, use External Secrets Operator:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: db-credentials-secret
data:
- secretKey: DB_PASSWORD
remoteRef:
key: prod/db/password
Synchronizes secrets from HashiCorp Vault, AWS Secrets Manager, Azure Key Vault.
What a Middle Developer Should Remember
- Secret in base64 ≠ encryption. Needs additional configuration.
- Env vars are not updated, volumes — updated automatically
- Immutable objects protect from accidental changes
- External Secrets Operator — production standard
- RBAC: restrict access to Secrets
Senior Level
Secret Storage Architecture
Without Encryption at Rest:
etcd stores: DB_PASSWORD: cGFzc3dvcmQxMjM=
Anyone with access to etcd can decode.
With Encryption at Rest:
# kube-apiserver configuration
encryption-provider-config:
kind: EncryptionConfiguration
resources:
- resources: ["secrets"]
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-key>
- identity: {}
Now secrets are encrypted in etcd.
Security: Deep Analysis
| Level | Protection | Description |
|---|---|---|
| Base64 only | None | Anyone with etcd/API access can read |
| RBAC | Partial | Restricts API access |
| Encryption at Rest | Good | Encrypts data in etcd |
| External KMS | Best | Encryption keys outside the cluster |
RBAC for Secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
resourceNames: ["app-secret"] # only specific secret
Comparison: Env vs Volume
| Aspect | Env Vars | Volumes |
|---|---|---|
| Update | Requires Pod restart | Automatic |
| Size | Good for simple values | Good for files |
| Security | Visible in kubectl describe pod |
Only via exec into container |
| Hot reload | No | Yes (application must re-read) |
Spring Boot + ConfigMap/Secret
ConfigMap as application.properties:
apiVersion: v1
kind: ConfigMap
metadata:
name: spring-config
data:
application.properties: |
spring.datasource.url=jdbc:postgresql://db:5432/mydb
spring.jpa.hibernate.ddl-auto=validate
volumeMounts:
- name: config
mountPath: /config
readOnly: true
env:
- name: SPRING_CONFIG_LOCATION
value: "file:/config/application.properties"
Secret Management: Evolution
Level 0: Secrets in git (anti-pattern)
Level 1: Kubernetes Secrets (base64)
Level 2: Secrets + Encryption at Rest
Level 3: External Secrets Operator + Vault/KMS
Level 4: Service Mesh (mTLS) + SPIFFE/SPIRE (identity)
Immutable Objects: When to Use
immutable: true
Use when:
- Configuration does not change between deployments
- You want additional protection from changes
- Reducing API server load (large ConfigMaps)
Do not use when:
- Settings change dynamically
- A/B testing with different configs
Troubleshooting
Secret not mounting:
kubectl describe pod myapp
# Warning: Couldn't find secret app-secret in namespace default
Causes:
- Secret not created
- Secret in a different namespace
- Typo in the name
ConfigMap updated but Pod doesn’t see changes:
- Volume update delay: Kubelet updates files with a delay (syncPeriod, default 1 min)
- Application doesn’t re-read the file — needs hot reload mechanism
Summary for Senior
- ConfigMap for configs, Secret — for passwords.
- Secret is not secure by default without Encryption at Rest or external KMS.
- Prefer file mounting for hot reload.
- External Secrets Operator + Vault/KMS — production standard.
- RBAC: restrict Secret access on the principle of least privilege.
- Immutable objects: protection from changes + reduced API server load.
- Spring Boot: mount ConfigMap as application.properties for dynamic configuration.
Interview Cheat Sheet
Must know:
- ConfigMap — regular settings (text), Secret — sensitive data (base64)
- Base64 ≠ encryption! Anyone can decode; needs Encryption at Rest
- Both can be used as env vars (not updated without restart) or volumes (auto-update)
- Size limit: 1 MB (etcd limitation)
- Immutable ConfigMap/Secret — protection from changes + reduced API server load
- External Secrets Operator + Vault/KMS — production standard
- RBAC: restrict Secret access on the principle of least privilege
Common follow-up questions:
- “Are Secrets stored securely?” — No by default (base64 in etcd); needs EncryptionConfiguration
- “Env vars vs volumes?” — Volumes are updated automatically, env vars require Pod restart
- “What is External Secrets Operator?” — Synchronizes secrets from Vault, AWS Secrets Manager, Azure Key Vault
- “When to use immutable?” — When config doesn’t change between deployments (protection + performance)
Red flags (DO NOT say):
- “Secrets are encrypted in K8s” (only base64; need to enable Encryption at Rest)
- “I store secrets in git in base64” (this is not encryption, anyone can decode)
- “ConfigMap for passwords” (use Secret)
- “Env vars are updated without restart” (only volumes auto-update)
Related topics:
- [[What is Kubernetes and why is it needed]] — K8s objects
- [[What is Ingress in Kubernetes]] — TLS secrets
- [[How to monitor applications in Kubernetes]] — configuration monitoring