Kubernetes ConfigMaps and Secrets
Advertisement
Kubernetes ConfigMaps and Secrets
ConfigMaps store configuration data while Secrets handle sensitive information. Learn best practices for both.
Introduction
Applications need configuration and secrets. Kubernetes provides ConfigMaps for non-sensitive configuration and Secrets for sensitive data.
- Kubernetes ConfigMaps and Secrets
- ConfigMaps
- Creating ConfigMaps
- ConfigMap in YAML
- Using ConfigMaps in Pods
- Environment Variables
- All ConfigMap as Environment
- Volume Mount
- Secrets
- Secret Types
- Creating Secrets
- Using Secrets in Pods
- Environment Variables
- Volume Mount
- Pull Private Images
- Best Practices
- Encryption at Rest
- Use Sealed Secrets
- RBAC for Secrets
- External Secret Management
- Using Vault
- AWS Secrets Manager
- Comparison
- FAQ
ConfigMaps
Store configuration data as key-value pairs.
Creating ConfigMaps
# From literal values
kubectl create configmap app-config \
--from-literal=DATABASE_HOST=postgres.example.com \
--from-literal=DATABASE_PORT=5432 \
--from-literal=LOG_LEVEL=info
# From file
kubectl create configmap app-config --from-file=config/app.conf
# From directory
kubectl create configmap app-config --from-file=config/
ConfigMap in YAML
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_HOST: postgres.example.com
DATABASE_PORT: "5432"
LOG_LEVEL: info
app.conf: |
server {
listen 80;
server_name localhost;
}
Using ConfigMaps in Pods
Environment Variables
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
- name: DATABASE_PORT
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_PORT
All ConfigMap as Environment
envFrom:
- configMapRef:
name: app-config
Volume Mount
apiVersion: v1
kind: Pod
metadata:
name: app-with-config
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: config
mountPath: /etc/config
readOnly: true
volumes:
- name: config
configMap:
name: app-config
Files available in /etc/config:
/etc/config/DATABASE_HOST
/etc/config/DATABASE_PORT
/etc/config/LOG_LEVEL
/etc/config/app.conf
Secrets
Store sensitive data securely.
Secret Types
Opaque (default): Base64-encoded arbitrary data
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: cG9zdGdyZXM= # base64-encoded 'postgres'
password: c2VjcmV0MTIz # base64-encoded 'secret123'
Docker Registry: Credentials for pulling images
apiVersion: v1
kind: Secret
metadata:
name: regcred
type: kubernetes.io/dockercfg
data:
.dockercfg: <base64-encoded-docker-config>
BasicAuth: Username and password
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
type: kubernetes.io/basic-auth
data:
username: YWRtaW4=
password: YWRtaW4xMjM=
Creating Secrets
# From literal values
kubectl create secret generic db-credentials \
--from-literal=username=postgres \
--from-literal=password=secretpassword
# From files
kubectl create secret generic api-keys \
--from-file=api-key.txt
# Docker registry secret
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass \
--docker-email=user@example.com
Using Secrets in Pods
Environment Variables
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
Volume Mount
apiVersion: v1
kind: Pod
metadata:
name: app-with-secrets
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: db-credentials
Files available:
/etc/secrets/username
/etc/secrets/password
Pull Private Images
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
imagePullSecrets:
- name: regcred
containers:
- name: app
image: registry.example.com/myapp:1.0
Best Practices
Encryption at Rest
Enable encryption for secrets:
# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {}
Start API server with flag:
--encryption-provider-config=/etc/kubernetes/encryption-config.yaml
Use Sealed Secrets
For GitOps, use sealed secrets:
# Install sealed-secrets controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.18.0/controller.yaml
# Seal a secret
echo -n mypassword | kubectl create secret generic mysecret --from-file=/dev/stdin --dry-run=client -o yaml | kubeseal -f -
# Save sealed secret to repo
# Unsealed only in cluster
RBAC for Secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
External Secret Management
Using Vault
apiVersion: v1
kind: Pod
metadata:
name: app-with-vault
spec:
serviceAccountName: myapp
initContainers:
- name: vault-init
image: vault:latest
env:
- name: VAULT_ADDR
value: http://vault:8200
command:
- sh
- -c
- |
vault kv get -field=password secret/database > /vault/secrets/db-password
volumeMounts:
- name: vault-token
mountPath: /vault/secrets
containers:
- name: app
image: myapp:1.0
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
volumes:
- name: vault-token
emptyDir: {}
AWS Secrets Manager
apiVersion: v1
kind: ServiceAccount
metadata:
name: myapp
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/MyAppRole
---
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
serviceAccountName: myapp
containers:
- name: app
image: myapp:1.0
env:
- name: DB_PASSWORD
value: /var/run/secrets/db-password
command:
- sh
- -c
- |
aws secretsmanager get-secret-value --secret-id db-password --query SecretString --output text > /var/run/secrets/db-password
node server.js
Comparison
| Aspect | ConfigMap | Secret |
|---|---|---|
| Use Case | Non-sensitive config | Sensitive data |
| Size Limit | 1 MB | 1 MB |
| Access Control | RBAC | RBAC + encryption |
| Encoding | Plain text | Base64 |
| Visibility | Less restricted | More restricted |
FAQ
Q: Are Secrets encrypted by default? A: Base64-encoded yes, encrypted no. Enable encryption at rest for production. Base64 is encoding, not encryption.
Q: Can I mix ConfigMaps and Secrets in one Pod? A: Yes. Use ConfigMaps for config, Secrets for passwords/keys. Both can be in same Pod.
Q: How do I rotate Secrets? A: Update the Secret, then restart Pods using it. Use rolling updates to minimize downtime.
Advertisement