Kubernetes est stateless par défaut. Pour faire tourner des applications configurables ou stateful, vous devez maîtriser ConfigMaps, Secrets et le stockage persistant. Ce module vous guide étape par étape.
Table of Contents
Objectifs
- Injecter de la configuration et des secrets dans vos Pods.
- Provisionner des volumes persistants dynamiques avec StorageClass/PVC.
- Déployer un StatefulSet avec persistance et vérifier la résilience.
1. ConfigMaps et Secrets
Utilisez un ConfigMap pour stocker des données non sensibles, un Secret pour le sensible (chiffré au repos selon votre solution).
apiVersion: v1
kind: ConfigMap
metadata:
name: web-cfg
namespace: staging
data:
APP_MODE: staging
FEATURE_FLAG_X: "true"
Secret en clair (Kubernetes se charge d’encoder en base64) :
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: staging
stringData:
username: reporting
password: S3cureP@ssw0rd
Injection dans le Pod :
envFrom:
- configMapRef:
name: web-cfg
- secretRef:
name: db-credentials
Ou montage en volume :
volumes:
- name: app-config
configMap:
name: web-cfg
containers:
- name: web
volumeMounts:
- name: app-config
mountPath: /app/config
2. Volumes éphémères vs persistants
- emptyDir : se vide si le Pod est recréé.
- hostPath : pointe vers le système de fichiers du nœud (à éviter en production).
- projected : combine ConfigMap + Secret + DownwardAPI.
3. PersistentVolume, PersistentVolumeClaim, StorageClass
Dans la plupart des clusters managés, la création d’un PVC déclenche automatiquement un PV grâce à une StorageClass.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
PersistentVolume (environnement de labo, stockage local) :
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-local
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
storageClassName: fast
hostPath:
path: /data/k8s-lab
Claim correspondant :
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-web
namespace: staging
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: fast
Vérifiez l’appairage :
kubectl get pv,pvc -n staging
4. StatefulSet avec volumes
Exemple PostgreSQL à deux réplicas :
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: data
spec:
serviceName: postgres
replicas: 2
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
env:
- name: POSTGRES_DB
value: analytics
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
storageClassName: fast
N’oubliez pas le Service headless :
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: data
spec:
clusterIP: None
selector:
app: postgres
ports:
- name: tcp
port: 5432
5. Lab guidé
- Créer le namespace
data, le ConfigMapweb-cfget le Secretdb-credentials. - Déployer le StatefulSet PostgreSQL + Service headless.
- Créer un Pod utilitaire :
kubectl run psql --image=postgres:15 -it --rm -- psql -h postgres-0.postgres.data.svc.cluster.local -U reporting analytics. - Insérer quelques lignes, supprimer le Pod
postgres-0et vérifier que les données persistent. - Monter le PVC en lecture seule dans un Job de backup :
apiVersion: batch/v1
kind: Job
metadata:
name: pg-backup
namespace: data
spec:
template:
spec:
restartPolicy: OnFailure
volumes:
- name: data
persistentVolumeClaim:
claimName: data-postgres-0
readOnly: true
containers:
- name: backup
image: bitnami/kubectl:1.29
command:
- /bin/sh
- -c
- |
tar czf /backup/postgres-$(date +%F).tgz -C /var/lib/postgresql/data .
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
Montez un PVC ou un emptyDir supplémentaire pour stocker l’archive.
Solution détaillée
- ConfigMap/Secret montés
kubectl exec deploy/webapp -n staging -- env | grep APP_MODE→ valeurstaging.
kubectl exec deploy/webapp -n staging -- cat /app/config/APP_MODErenvoie the same. - PVC appairé
kubectl get pvc data-web -n stagingdoit êtreBoundau PVpv-local. Vérifiezkubectl get pv pv-local -o jsonpath='{.spec.claimRef.name}'. - StatefulSet
kubectl get sts postgres -n data→ READY2/2.
kubectl get pods -n data -l app=postgres -o widemontrepostgres-0,postgres-1avec volumes montés. - Persistance
Dans le Pod utilitaire, créez une table et insérez une ligne. Supprimezpostgres-0, attendez le redémarrage : les données doivent toujours être présentes.kubectl delete pod postgres-0 -n data kubectl run -n data psql --rm -it --image=postgres:15 -- psql -h postgres-0.postgres.data.svc.cluster.local -U reporting analytics analytics=# SELECT * FROM demo; - Job de backup
kubectl get jobs -n data→pg-backupCompleted. Les logskubectl logs job/pg-backup -n dataconfirment la création du tar.
Archiver ces vérifications dans votre journal et conserver les manifestes (ConfigMap, Secret, PVC, StatefulSet) dans votre dépôt de formation.
Pièges fréquents
- Oublier la clé
storageClassName→ le PVC reste en Pending. - Ajouter des fichiers dans un volume monté sous
/etc/configalors que le Pod n’a pas les droits (pensez auxfsGroup). - Changer la taille d’un PVC sans que la StorageClass supporte l’expansion.
- Utiliser des Secrets en clair sans chiffrement de etcd (voir module 5 pour KMS).
Challenge avancé
- Activer la rotation automatique des Secrets via un CronJob.
- Tester un opérateur comme Zalando Postgres Operator pour gérer automatiquement les StatefulSets.
- Comparer Kustomize et Helm pour templater ConfigMaps/Secrets (ex.
helm upgrade --install web charts/web --set-file secretFiles.db=secrets.yaml).
Ressources
Checklist
- ✅ Vos Pods consomment ConfigMaps et Secrets correctement.
- ✅ Vous savez provisionner un volume persistant et vérifier son appairage.
- ✅ Vous avez déployé un StatefulSet et validé la persistance après redémarrage.


