Lab 05 : Configuration & Stockage Persistant (PV / PVC / PostgreSQL)¶
Objectifs Pédagogiques :¶
- Découpler la configuration du code applicatif à l'aide des ConfigMaps (par variables directes et injection globale
envFrom). - Sécuriser les mots de passe et identifiants sensibles avec les Secrets Kubernetes.
- Comprendre le cycle de vie du stockage persistant :
StorageClass,PersistentVolume(PV) etPersistentVolumeClaim(PVC). - Déployer une base de données relationnelle PostgreSQL avec stockage persistant.
- Connecter l'API Spring Boot
campus-backendà la base de données. - Réaliser un crash-test de persistance démontrant la survie des données après suppression du pod de base de données.
📌 Note Compatibilité OS :
Les commandes de création et d'application des manifests sont identiques. Seule la syntaxe de décodage base64 dans le terminal diffère entre PowerShell et Linux/macOS.💡 Modalités d'exécution (Au choix) :
* Option A (Recommandée - Confort DevOps Local) : Exécutez les commandes directement depuis votre machine locale avec votrekubectlet votrekubeconfig.
* Option B (Secours - PC d'entreprise verrouillé) : Connectez-vous en SSH surk8s-control: l'outillage et les manifests sont pré-installés dans~/labs/.
Contexte Métier¶
Dans les labs précédents, notre API backend fonctionnait avec des données mockées en mémoire vive. En production, elle doit impérativement stocker les candidatures des étudiants dans une base de données PostgreSQL sécurisée. Les mots de passe ne doivent jamais être écrits en clair dans les fichiers de code ou les dépôts Git, et les données de la base ne doivent jamais disparaître si le conteneur redémarre ou si le nœud physique tombe en panne.
Exercice 1 : Externaliser la Configuration avec un ConfigMap¶
1. Créer un ConfigMap avec des variables directes¶
Créez un ConfigMap nommé campus-config contenant les paramètres non sensibles de configuration de l'application :
* SPRING_PROFILES_ACTIVE : production
* SERVER_PORT : 8080
* LOGGING_LEVEL_COM_OKDLAB : INFO
kubectl create configmap campus-config \
--from-literal=SPRING_PROFILES_ACTIVE=production \
--from-literal=SERVER_PORT=8080 \
--from-literal=LOGGING_LEVEL_COM_OKDLAB=INFO \
--dry-run=client -o yaml > configmap.yaml
kubectl apply -f configmap.yaml
Inspectez le contenu enregistré dans etcd :
2. Créer un ConfigMap à partir d'un fichier de configuration¶
Il est également très fréquent d'injecter des fichiers de configuration entiers (application.properties, nginx.conf, etc.).
-
Créez un fichier local
extra-config.properties: -
Créez un second ConfigMap depuis ce fichier :
Constatez que le nom du fichier devient la clé, et son contenu devient la valeur !
Exercice 2 : Sécuriser les Identifiants avec un Secret¶
1. Créer un Secret pour PostgreSQL¶
Créez un Secret de type generic nommé campus-db-credentials contenant les identifiants d'accès à la base de données :
* POSTGRES_DB : campus
* POSTGRES_USER : campus
* POSTGRES_PASSWORD : CampusSecret2026!
kubectl create secret generic campus-db-credentials \
--from-literal=POSTGRES_DB=campus \
--from-literal=POSTGRES_USER=campus \
--from-literal=POSTGRES_PASSWORD=CampusSecret2026! \
--dry-run=client -o yaml > secret.yaml
kubectl apply -f secret.yaml
2. Observer l'encodage Base64¶
Affichez le Secret au format YAML :
Remarquez que les valeurs sont encodées en base64 pour éviter l'affichage accidentel en clair dans les logs ou les consoles.
3. Décoder une valeur du Secret¶
-
Sous Windows (PowerShell) :
-
Sous Linux (Ubuntu) / macOS (Bash) :
⚠️ Sécurité en Production : L'encodage Base64 n'est pas un chiffrement (n'importe qui peut le décoder). En production d'entreprise, les secrets doivent être chiffrés au repos dans etcd (Encryption at Rest) et gérés via des coffres-forts externes comme HashiCorp Vault ou AWS Secrets Manager via le pilote CSI Secrets Store.
Exercice 3 : Définir la Persistance avec un PersistentVolumeClaim (PVC)¶
Par défaut, le système de fichiers d'un conteneur est éphémère (stateless) : à la destruction du pod, toutes les modifications de disque sont perdues. Pour une base de données, nous devons réserver un volume persistant via un PersistentVolumeClaim (PVC).
1. Vérifier la StorageClass du cluster¶
Avant de créer une demande de volume, identifiez la classe de stockage par défaut de votre cluster :
Sur votre cluster AWS, vous observez la StorageClass configurée par défaut (ex.gp2 / gp3 ou provisionneur local).
2. Créer le PersistentVolumeClaim¶
Créez le fichier postgres-pvc.yaml :
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Appliquez le PVC :
3. Valider la liaison dynamique (Binding)¶
Surveillez l'état du PVC :
💡 Observation clé (
WaitForFirstConsumer) : Le PVC reste initialement à l'étatPendingtant qu'aucun Pod ne le réclame. En effet, la StorageClasslocal-pathutilise la politiquevolumeBindingMode: WaitForFirstConsumerpour différer la création du volume jusqu'à ce que le Scheduler détermine sur quel nœud worker le Pod PostgreSQL sera exécuté. Dès le déploiement du Pod à l'exercice 4, le volume sera créé sur le nœud assigné et le PVC passera automatiquement à l'étatBound!
Vous pouvez inspecter les volumes persistants physiques alloués :
4. Comprendre les modes d'accès aux volumes¶
| Mode d'accès | Signification | Cas d'usage type |
|---|---|---|
ReadWriteOnce (RWO) |
Lecture et écriture par un seul nœud à la fois. | Bases de données (PostgreSQL, MySQL, MongoDB). |
ReadOnlyMany (ROX) |
Lecture seule par de multiples nœuds simultanément. | Référentiel de binaires, contenu web statique. |
ReadWriteMany (RWX) |
Lecture et écriture partagée par plusieurs nœuds. | Serveur NFS, CMS WordPress (uploads partagés). |
Exercice 4 : Déployer PostgreSQL avec Volume et Secrets¶
1. Créer le manifest de déploiement PostgreSQL¶
Créez le fichier postgres-deployment.yaml qui lie ensemble le conteneur PostgreSQL officiel, le Secret pour les variables d'environnement, et le volume persistant monté sur /var/lib/postgresql/data :
apiVersion: apps/v1
kind: Deployment
metadata:
name: campus-postgres
spec:
replicas: 1
selector:
matchLabels:
app: campus-postgres
template:
metadata:
labels:
app: campus-postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: campus-db-credentials
key: POSTGRES_DB
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: campus-db-credentials
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: campus-db-credentials
key: POSTGRES_PASSWORD
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
2. Appliquer le déploiement et exposer le Service¶
Appliquez le fichier et créez le Service d'accès interne postgres sur le port 5432 :
kubectl apply -f postgres-deployment.yaml
kubectl expose deployment campus-postgres --name=postgres --port=5432 --type=ClusterIP
Attendez que le pod soit en cours d'exécution et vérifiez les logs d'initialisation de PostgreSQL :
kubectl wait --for=condition=ready pod -l app=campus-postgres --timeout=90s
kubectl logs -l app=campus-postgres --tail=20
database system is ready to accept connections.
Exercice 5 : Connexion Backend & Crash-Test de Persistance¶
1. Connecter le backend à la base de données¶
Mettons à jour le fichier deployment-backend.yaml pour injecter les variables de connexion PostgreSQL issues de notre Secret :
apiVersion: apps/v1
kind: Deployment
metadata:
name: campus-backend
spec:
replicas: 2
selector:
matchLabels:
app: campus-backend
template:
metadata:
labels:
app: campus-backend
spec:
containers:
- name: campus-backend
image: regaieg/campus:backend-1.0.0
ports:
- containerPort: 8080
env:
- name: SPRING_DATASOURCE_URL
value: "jdbc:postgresql://postgres:5432/campus"
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: campus-db-credentials
key: POSTGRES_USER
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: campus-db-credentials
key: POSTGRES_PASSWORD
envFrom:
- configMapRef:
name: campus-config
Appliquez le déploiement :
2. Écrire des données de test dans PostgreSQL¶
Connectez-vous directement en SQL au conteneur PostgreSQL :
Exécutez les commandes SQL suivantes :
CREATE TABLE test_candidats (
id SERIAL PRIMARY KEY,
nom VARCHAR(100),
filiere VARCHAR(100),
date_inscription TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO test_candidats (nom, filiere) VALUES ('Alice Dubois', 'Cloud DevOps Kubernetes');
INSERT INTO test_candidats (nom, filiere) VALUES ('Bob Martin', 'Architecte Microservices');
SELECT * FROM test_candidats;
\q
3. Crash-Test : Destruction brutale du Pod¶
Simulons une panne matérielle ou un redémarrage impromptu du serveur en supprimant immédiatement le pod PostgreSQL :
Observez le contrôleur Deployment recréer immédiatement un nouveau pod de remplacement :
4. Vérification de la survie des données¶
Dès que le nouveau pod est 1/1 Running, reconnectez-vous en SQL pour interroger la table :
kubectl exec -it deployment/campus-postgres -- psql -U campus -d campus -c "SELECT * FROM test_candidats;"
Résultat : Les données sont parfaitement conservées ! Le nouveau Pod a remonté le volume persistant postgres-pvc sans aucune perte d'information.
Critères de Validation (Checklist)¶
- Les paramètres non sensibles sont découplés dans le ConfigMap
campus-config. - Les mots de passe sont protégés dans le Secret
campus-db-credentialset décodés avec succès. - Le PVC
postgres-pvcest en statutBoundavec une StorageClass active. - Le service
postgresest exposé sur le port5432enClusterIP. - Le backend
campus-backendest configuré avec la chaîne JDBC pointant verspostgres:5432/campus. - Le test de destruction du pod confirme la persistance totale des données sur le volume.