Chapter 5.1 - ConfigMaps
Learning Objectives
By the end of this chapter, you will be able to:
- Understand what a ConfigMap is and why to use it
- Create ConfigMaps in different ways
- Use ConfigMaps in your Pods
- Separate configuration from application code
- Apply best practices for ConfigMaps
Introduction
In application development, configuration often changes depending on the environment (development, staging, production). Hardcoding configuration in code or Docker images is not a good practice.
ConfigMaps allow you to separate configuration from application code.
What is a ConfigMap?
A ConfigMap is a Kubernetes object that stores non-sensitive configuration data as key-value pairs. This data can be used by Pods as environment variables, command arguments, or configuration files.
Why Use ConfigMaps?
Problems Without ConfigMaps
Problems:
- Configuration hardcoded in the code
- Need to rebuild the image to change config
- Difficult to manage different environments
- No separation of concerns
Advantages With ConfigMaps
Advantages:
- Configuration separated from code
- No need to rebuild the image
- Easy to manage multiple environments
- Reusable across multiple Pods
Creating ConfigMaps
Method 1: From Literals
kubectl create configmap app-config \
--from-literal=database_url=postgresql://localhost:5432/mydb \
--from-literal=log_level=info \
--from-literal=max_connections=100
Method 2: From a File
Create a config.properties file:
database_url=postgresql://localhost:5432/mydb
log_level=info
max_connections=100
kubectl create configmap app-config --from-file=config.properties
Method 3: From a YAML File
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
database_url: "postgresql://localhost:5432/mydb"
log_level: "info"
max_connections: "100"
# Complete file
application.properties: |
server.port=8080
server.host=0.0.0.0
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
Usage in Pods
Method 1: Environment Variables (Single Key)
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: database_url
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log_level
Method 2: All Keys (envFrom)
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
envFrom:
- configMapRef:
name: app-config
Result: All ConfigMap keys become environment variables.
Method 3: As a Volume (Files)
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
volumeMounts:
- name: config
mountPath: /etc/config
readOnly: true
volumes:
- name: config
configMap:
name: app-config
Result: Each key becomes a file in /etc/config/ with the value as its content.
Complete Example
Step 1: Create the ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: webapp-config
data:
# Simple variables
APP_NAME: "My Web Application"
APP_VERSION: "1.0.0"
ENVIRONMENT: "production"
# Configuration file
nginx.conf: |
server {
listen 80;
server_name example.com;
root /usr/share/nginx/html;
index index.html;
}
Step 2: Use in a Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:1.20
env:
- name: APP_NAME
valueFrom:
configMapKeyRef:
name: webapp-config
key: APP_NAME
- name: ENVIRONMENT
valueFrom:
configMapKeyRef:
name: webapp-config
key: ENVIRONMENT
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
readOnly: true
volumes:
- name: nginx-config
configMap:
name: webapp-config
items:
- key: nginx.conf
path: default.conf
Use Cases
1. Application Configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: app-settings
data:
database_host: "db.example.com"
database_port: "5432"
cache_ttl: "3600"
feature_flags: "feature1,feature2"
2. Configuration Files
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx.conf: |
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
}
3. Scripts
apiVersion: v1
kind: ConfigMap
metadata:
name: init-scripts
data:
init.sh: |
#!/bin/bash
echo "Initializing application..."
/app/setup.sh
exec /app/start.sh
Best Practices
1. Organization by Environment
Create separate ConfigMaps for each environment:
# Development
kubectl create configmap app-config-dev --from-file=config-dev.properties
# Production
kubectl create configmap app-config-prod --from-file=config-prod.properties
2. Versioning
Use labels for versioning:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
labels:
version: v1
environment: production
data:
# ...
3. Do Not Store Sensitive Data
Never put the following in a ConfigMap:
- Passwords
- API tokens
- Private keys
- Certificates
Use Secrets instead.
Useful Commands
View a ConfigMap
kubectl get configmap app-config
kubectl describe configmap app-config
kubectl get configmap app-config -o yaml
Modify a ConfigMap
kubectl edit configmap app-config
Note: Existing Pods will not see the changes immediately. They need to be restarted.
Delete a ConfigMap
kubectl delete configmap app-config
Limitations
Maximum Size
- 1 MiB per entry in a ConfigMap
- Total limited by etcd (typically ~1.5 MiB per object)
Updates
- Environment variables: Do not change without restarting the Pod
- Volumes: Updated periodically (delay of a few seconds)
Summary
In this chapter, you learned:
ConfigMap: Kubernetes object to store non-sensitive configuration
Creation: kubectl create, YAML, from files
Usage: Environment variables (env/envFrom) or volumes
Advantages: Config/code separation, flexibility, reusability
Best practices: Organization by environment, versioning, no secrets
Limitations: Maximum size, update requires restart for env vars
Next Steps
Chapter 5.2: Secrets - Managing sensitive data
Lab 5.1: Creating and Using ConfigMaps
Chapter created: December 2024