Exercice 03 : ConfigMaps et variables d'environnement
🎯 Objectifs
À la fin de cet exercice, vous serez capable de :
- ✅ Créer un ConfigMap avec
kubectl create configmapet en YAML - ✅ Injecter des ConfigMaps via
env,envFrometvolumeMount - ✅ Monter un ConfigMap comme fichier de config dans un pod
- ✅ Modifier une configuration et observer son impact
Durée estimée : 25 minutes
Difficulté : ⭐⭐☆☆☆ (Intermédiaire)
Prérequis : Exercice 01 complété, namespace intermediaire existant
📖 Contexte
Une application configurée uniquement via des variables d'environnement hardcodées dans le YAML du Deployment est non portable : la même image doit fonctionner en développement ET en production avec des configurations différentes.
Les ConfigMaps externalisent la configuration hors du code de l'application. L'image Docker reste identique quel que soit l'environnement ; seul le ConfigMap change.
📋 Énoncé
Configurez une application Nginx avec différentes méthodes d'injection de ConfigMaps.
🧭 Déroulement de l'exercice
Tâche 1 : Créer un ConfigMap
# Méthode 1 : via kubectl (clé=valeur)
kubectl create configmap app-config \
--from-literal=NODE_ENV=production \
--from-literal=LOG_LEVEL=info \
--from-literal=MAX_CONNECTIONS=100 \
--from-literal=API_TIMEOUT=30s \
-n intermediaire
# Voir le ConfigMap créé
kubectl get configmap app-config -n intermediaire -o yaml# Méthode 2 : via YAML (préférée pour le versionning)
cat > app-configmap.yaml << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: app-env
namespace: intermediaire
data:
# Variables simples
NODE_ENV: "production"
LOG_LEVEL: "info"
DATABASE_HOST: "postgres.intermediaire.svc.cluster.local"
DATABASE_PORT: "5432"
# Fichier de configuration complet (clé = nom du fichier)
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /health {
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
EOF
kubectl apply -f app-configmap.yaml
kubectl get configmaps -n intermediaireTâche 2 : Injecter des variables d'environnement
cat > env-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: env-demo
namespace: intermediaire
spec:
replicas: 1
selector:
matchLabels:
app: env-demo
template:
metadata:
labels:
app: env-demo
spec:
containers:
- name: app
image: busybox:latest
command: ["/bin/sh", "-c"]
args:
- |
echo "NODE_ENV = $NODE_ENV"
echo "LOG_LEVEL = $LOG_LEVEL"
echo "DB_HOST = $DATABASE_HOST"
echo "API_TIMEOUT = $API_TIMEOUT"
echo "---Variables individuelles---"
sleep 3600
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 50m
memory: 64Mi
env:
# Variable individuelle depuis ConfigMap
- name: API_TIMEOUT
valueFrom:
configMapKeyRef:
name: app-config
key: API_TIMEOUT
# Injecter TOUTES les clés d'un ConfigMap comme variables
envFrom:
- configMapRef:
name: app-env
EOF
kubectl apply -f env-deployment.yaml
# Voir les variables dans le pod
POD=$(kubectl get pods -n intermediaire -l app=env-demo -o jsonpath='{.items[0].metadata.name}')
kubectl logs "$POD" -n intermediaireVérification : Les logs doivent afficher les valeurs du ConfigMap.
Tâche 3 : Monter un ConfigMap comme fichier
cat > volume-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-custom
namespace: intermediaire
spec:
replicas: 1
selector:
matchLabels:
app: nginx-custom
template:
metadata:
labels:
app: nginx-custom
spec:
volumes:
# Volume basé sur le ConfigMap
- name: nginx-config
configMap:
name: app-env
items:
# Monter seulement la clé "nginx.conf"
- key: nginx.conf
path: default.conf # Nom du fichier dans le pod
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
volumeMounts:
# Monter dans /etc/nginx/conf.d/
- name: nginx-config
mountPath: /etc/nginx/conf.d/
readOnly: true
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
EOF
kubectl apply -f volume-deployment.yaml
# Vérifier que le fichier est monté
POD=$(kubectl get pods -n intermediaire -l app=nginx-custom -o jsonpath='{.items[0].metadata.name}')
kubectl exec "$POD" -n intermediaire -- cat /etc/nginx/conf.d/default.conf
# Tester le endpoint /health
kubectl port-forward "$POD" 8080:80 -n intermediaire &
sleep 1
curl http://localhost:8080/health
kill %1Tâche 4 : Modifier la configuration sans redéployer
# Modifier le ConfigMap (changer le log level)
kubectl patch configmap app-env -n intermediaire \
--type=merge \
-p '{"data":{"LOG_LEVEL":"debug"}}'
# Vérifier la modification
kubectl get configmap app-env -n intermediaire -o jsonpath='{.data.LOG_LEVEL}'
# → debug
# Les fichiers montés en volume sont mis à jour automatiquement (30s max)
# Les variables d'environnement NE SONT PAS mises à jour sans redémarrage
# Il faut forcer un redéploiement pour les env vars :
kubectl rollout restart deployment/env-demo -n intermediaireIndice : Les ConfigMaps montés en volume (Tâche 3) sont mis à jour automatiquement dans les pods existants. Les ConfigMaps injectés en variables d'environnement (Tâche 2) nécessitent un redémarrage des pods pour être pris en compte.
✅ Vérification du résultat
kubectl get configmaps -n intermediairelisteapp-configetapp-envkubectl logsdu podenv-demoaffiche les valeurs du ConfigMap- Le fichier
default.confest présent dans/etc/nginx/conf.d/du pod curl localhost:8080/healthretourneOK
💡 À retenir
3 façons d'injecter un ConfigMap :
| Méthode | Quand utiliser |
|---|---|
env[].valueFrom.configMapKeyRef | Une seule clé spécifique |
envFrom[].configMapRef | Toutes les clés comme variables d'env |
volumeMounts | Fichiers de configuration (nginx.conf, etc.) |
ConfigMap vs Secret :
- ConfigMap : données non sensibles (URL, ports, feature flags)
- Secret : données sensibles (mots de passe, clés API) - voir module Avancé
✨ Solution Complète
# Injection en variables d'environnement
envFrom:
- configMapRef:
name: mon-configmap
# Montage en fichier
volumes:
- name: config
configMap:
name: mon-configmap
containers:
- volumeMounts:
- name: config
mountPath: /etc/app/config