Kubernetes Configuration Management
ConfigMap Patterns
Basic ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
# Simple key-value pairs
database.host: "postgres-service.database.svc.cluster.local"
database.port: "5432"
database.name: "appdb"
# Multi-line configuration
app.properties: |
server.port=8080
logging.level=INFO
cache.enabled=true
cache.ttl=3600
# JSON configuration
features.json: |
{
"featureA": true,
"featureB": false,
"maxConnections": 100
}
# YAML configuration
config.yaml: |
server:
port: 8080
timeout: 30s
database:
pool_size: 20
max_connections: 100
ConfigMap from Files
# Create from literal values
kubectl create configmap app-config \
--from-literal=database.host=postgres \
--from-literal=database.port=5432
# Create from file
kubectl create configmap nginx-config \
--from-file=nginx.conf
# Create from directory
kubectl create configmap app-configs \
--from-file=configs/
Secret Patterns
Opaque Secret (Generic)
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
namespace: production
type: Opaque
stringData:
# Plain text (will be base64 encoded)
db-password: "MySecurePassword123!"
api-key: "sk-1234567890abcdef"
jwt-secret: "super-secret-jwt-key"
data:
# Already base64 encoded
tls.crt: LS0tLS1CRUdJTi...
tls.key: LS0tLS1CRUdJTi...
TLS Secret
apiVersion: v1
kind: Secret
metadata:
name: example-tls
namespace: production
type: kubernetes.io/tls
stringData:
tls.crt: |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKZ...
-----END CERTIFICATE-----
tls.key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0B...
-----END PRIVATE KEY-----
Docker Registry Secret
apiVersion: v1
kind: Secret
metadata:
name: registry-credentials
namespace: production
type: kubernetes.io/dockerconfigjson
stringData:
.dockerconfigjson: |
{
"auths": {
"myregistry.io": {
"username": "myuser",
"password": "mypassword",
"email": "[email protected]",
"auth": "bXl1c2VyOm15cGFzc3dvcmQ="
}
}
}
Basic Auth Secret
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
namespace: production
type: kubernetes.io/basic-auth
stringData:
username: admin
password: super-secret-password
SSH Auth Secret
apiVersion: v1
kind: Secret
metadata:
name: ssh-key
namespace: production
type: kubernetes.io/ssh-auth
stringData:
ssh-privatekey: |
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUA...
-----END OPENSSH PRIVATE KEY-----
Using ConfigMaps and Secrets
Environment Variables
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:latest
env:
# Single value from ConfigMap
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database.host
# Single value from Secret
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: db-password
# All keys from ConfigMap as env vars
envFrom:
- configMapRef:
name: app-config
prefix: CONFIG_
# All keys from Secret as env vars
- secretRef:
name: app-secrets
prefix: SECRET_
Volume Mounts
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
# Mount entire ConfigMap as directory
- name: config-volume
mountPath: /etc/config
readOnly: true
# Mount specific key as file
- name: app-properties
mountPath: /etc/app/app.properties
subPath: app.properties
readOnly: true
# Mount Secret as files
- name: secrets-volume
mountPath: /etc/secrets
readOnly: true
# Mount TLS certificates
- name: tls-certs
mountPath: /etc/tls
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config
- name: app-properties
configMap:
name: app-config
items:
- key: app.properties
path: app.properties
- name: secrets-volume
secret:
secretName: app-secrets
defaultMode: 0400 # Read-only for owner
- name: tls-certs
secret:
secretName: example-tls
Immutable ConfigMaps and Secrets
apiVersion: v1
kind: ConfigMap
metadata:
name: immutable-config
namespace: production
immutable: true
data:
key: value
---
apiVersion: v1
kind: Secret
metadata:
name: immutable-secret
namespace: production
type: Opaque
immutable: true
stringData:
password: "MyPassword123"
External Secrets Operator
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-secrets
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: app-secrets
creationPolicy: Owner
data:
- secretKey: db-password
remoteRef:
key: prod/database/password
- secretKey: api-key
remoteRef:
key: prod/api/key
---
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secrets-manager
namespace: production
spec:
provider:
aws:
service: SecretsManager
region: us-east-1
auth:
jwt:
serviceAccountRef:
name: external-secrets-sa
Sealed Secrets (GitOps)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: app-secrets
namespace: production
spec:
encryptedData:
db-password: AgBj8xK5...encrypted...base64
api-key: AgCY9mL2...encrypted...base64
template:
metadata:
name: app-secrets
namespace: production
type: Opaque
Environment Variable Best Practices
Structured Environment Variables
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp:latest
env:
# Application settings
- name: APP_NAME
value: "my-application"
- name: APP_ENV
value: "production"
- name: APP_VERSION
value: "v1.2.0"
# Database configuration
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: app-config
key: database.port
- name: DB_NAME
valueFrom:
configMapKeyRef:
name: app-config
key: database.name
- name: DB_USER
valueFrom:
secretKeyRef:
name: app-secrets
key: db-username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: db-password
# Kubernetes metadata
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
# Resource limits
- name: MEMORY_LIMIT
valueFrom:
resourceFieldRef:
containerName: app
resource: limits.memory
- name: CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: app
resource: requests.cpu
Dynamic Configuration Updates
apiVersion: v1
kind: Deployment
metadata:
name: app
spec:
template:
metadata:
annotations:
# Force pod restart on config change
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: config
mountPath: /etc/config
readOnly: true
volumes:
- name: config
configMap:
name: app-config
Best Practices
- Separation: Use ConfigMaps for non-sensitive data, Secrets for credentials
- Immutability: Mark production configs as immutable for safety
- Versioning: Include version in ConfigMap/Secret names for updates
- Least Privilege: Mount secrets as files with restrictive permissions (0400)
- External Secrets: Use External Secrets Operator for cloud secret managers
- No Hardcoding: Never hardcode secrets in container images
- Encryption: Enable encryption at rest for Secrets in etcd
- GitOps: Use Sealed Secrets for safe GitOps workflows
- Rotation: Implement secret rotation strategies
- Validation: Validate configuration before deployment