TP matin — Kubernetes Développeur
Configurer des applications avec ConfigMaps, Secrets, Volumes et StatefulSets.
Durée : 1h30
Contexte
Vous êtes développeur dans une équipe qui déploie une stack applicative sur Kubernetes. Votre mission ce matin est de gérer correctement la configuration (ConfigMaps, Secrets), le stockage persistant (PVC), et de déployer une base de données Redis en mode StatefulSet avec persistance garantie.
Focus Kubernetes Dev
- ✅ ConfigMaps : Découplez la configuration de vos manifestes
- ✅ Secrets : Gérez les données sensibles sans les hardcoder
- ✅ Volumes emptyDir et PVC : Comprenez les deux cas de persistance
- ✅ StatefulSet : Déployez une application stateful avec identité stable
L'objectif n'est PAS de maîtriser Redis, mais d'apprendre à gérer la configuration et le stockage dans Kubernetes.
Objectif
À la fin de ce TP, vous devez avoir :
- ✅ Un ConfigMap monté comme fichier dans un pod Redis
- ✅ Un Secret utilisé comme variables d'environnement dans un pod Postgres
- ✅ Un PVC Longhorn avec un writer-pod et un reader-pod partageant les données
- ✅ Un StatefulSet Redis avec
volumeClaimTemplateset un Service associé
Étape 0 - Préparer le namespace
Objectif : Travailler dans un namespace dédié.
- Action : Créer le namespace
mynamespaceet définir le contexte Observation :kubectl config get-contextsmontre le namespace par défaut à jour
Indice
kubectl create namespace mynamespace
kubectl config set-context --current --namespace=mynamespace
Étape 1 - ConfigMap comme fichier de configuration
Objectif : Configurer Redis via un ConfigMap monté en volume.
- Action : Créer un ConfigMap nommé
redis-configavec le contenu suivant :
maxmemory 2mb
maxmemory-policy allkeys-lru
Observation : kubectl get configmap redis-config -o yaml affiche les données
Action : Créer un pod
redis-podavec l'imageredis:latestqui monte la ConfigMap dans/redis-masteret démarre avecredis-server /redis-master/redis.confObservation : Le pod est en étatRunningAction : Vérifier que la configuration est prise en compte :
kubectl exec -it redis-pod -- redis-cli config get maxmemoryObservation : La réponse indique
2097152(2mb en octets)
Indice
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
namespace: mynamespace
data:
redis.conf: |
maxmemory 2mb
maxmemory-policy allkeys-lru
---
apiVersion: v1
kind: Pod
metadata:
name: redis-pod
namespace: mynamespace
spec:
containers:
- name: redis
image: redis:latest
command: ["redis-server", "/redis-master/redis.conf"]
volumeMounts:
- name: config-volume
mountPath: /redis-master
volumes:
- name: config-volume
configMap:
name: redis-config
Étape 2 - Secret comme variables d'environnement
Objectif : Passer des credentials Postgres sans les hardcoder.
Action : Créer un Secret
postgres-secretavecPOSTGRES_USER=useretPOSTGRES_PASSWORD=passwordObservation :kubectl get secret postgres-secretaffiche le secret (valeurs encodées en base64)Action : Créer un pod
postgres-podavec l'imagepostgres:latestqui utilise ces variables viasecretKeyRefObservation : Le pod démarre correctementAction : Vérifier que les variables sont présentes :
kubectl exec -it postgres-pod -- env | grep POSTGRESObservation : Les deux variables apparaissent avec les bonnes valeurs
Indice
kubectl create secret generic postgres-secret \
--from-literal=POSTGRES_USER=user \
--from-literal=POSTGRES_PASSWORD=password \
-n mynamespace
apiVersion: v1
kind: Pod
metadata:
name: postgres-pod
namespace: mynamespace
spec:
containers:
- name: postgres
image: postgres:latest
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
Étape 3 - Volumes persistants : writer et reader
Objectif : Partager un volume persistant entre deux pods.
Action : Installer Longhorn (StorageClass nécessaire pour les PVC) :
sudo apt update && sudo apt install nfs-common -y
kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.6.0/deploy/longhorn.yamlObservation :
kubectl get storageclasslistelonghornAction : Créer un PVC
pv-claimde 1Gi avecstorageClassName: longhornetaccessModes: ReadWriteManyObservation :kubectl get pvcmontre le PVC en étatBoundAction : Créer un pod
writer-podqui écrit un timestamp toutes les 5 secondes dans/data/timestamp.txtObservation :kubectl exec writer-pod -- tail /data/timestamp.txtmontre des lignes qui s'accumulentAction : Créer un pod
reader-podavec la commandetail -f /data/timestamp.txtsur le même PVC Observation :kubectl logs reader-podaffiche les timestamps écrits par le writer
Indice
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-claim
namespace: mynamespace
spec:
storageClassName: longhorn
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: writer-pod
namespace: mynamespace
spec:
containers:
- name: writer
image: ubuntu:latest
command: ["/bin/sh", "-c", "while true; do echo $(date) >> /data/timestamp.txt; sleep 5; done"]
volumeMounts:
- name: data-volume
mountPath: /data
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: pv-claim
Pour le reader, utilisez la même spec avec tail -f /data/timestamp.txt comme commande.
Étape 4 - StatefulSet Redis avec VolumeClaimTemplate
Objectif : Déployer Redis en mode StatefulSet avec un PVC automatique par pod.
Action : Créer un StatefulSet
redis-setavec 2 replicas, unvolumeClaimTemplatesde 100Mi, et le port 6379 Observation :kubectl get podsmontreredis-set-0etredis-set-1qui démarrent dans l'ordreAction : Observer les PVCs créés automatiquement Observation :
kubectl get pvcmontreredis-data-redis-set-0etredis-data-redis-set-1Action : Créer un Service
redis-servicede typeClusterIPavec le selectorapp: redissur le port 6379 Observation :kubectl get svc redis-servicemontre le serviceAction : Modifier le selector du service pour cibler uniquement
redis-set-0avec le labelstatefulset.kubernetes.io/pod-name: redis-set-0Observation :kubectl get endpoints redis-servicemontre une seule IP (celle de redis-set-0)
Indice
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-set
namespace: mynamespace
spec:
serviceName: "redis"
replicas: 2
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:latest
ports:
- containerPort: 6379
volumeMounts:
- name: redis-data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Mi
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: mynamespace
spec:
selector:
statefulset.kubernetes.io/pod-name: redis-set-0
ports:
- protocol: TCP
port: 6379
targetPort: 6379
type: ClusterIP
Avancé
- PVC et sécurité : Que se passe-t-il si vous supprimez le StatefulSet ? Les PVCs sont-ils supprimés automatiquement ? Pourquoi ce comportement ?
- Secrets chiffrés : Les Secrets Kubernetes sont encodés en base64, pas chiffrés. Comment les chiffrer au repos dans etcd ? Que sont les "External Secrets" et quand les utiliser ?
- ReadWriteOnce vs ReadWriteMany : Pourquoi
ReadWriteOnceest le mode par défaut ? Quand a-t-on besoin deReadWriteMany?
Synthèse
Qu'est-ce qui a bien fonctionné ?
- La ConfigMap a-t-elle bien été prise en compte par Redis ?
- Le Secret a-t-il bien fourni les variables au pod Postgres ?
Quels sont les problèmes rencontrés ?
- Le PVC est-il passé en état
Boundrapidement ? - Le StatefulSet a-t-il bien créé les PVCs automatiquement ?
Quelles compétences avez-vous développées ?
- ✅ Créer et utiliser des ConfigMaps comme fichiers de configuration
- ✅ Gérer des credentials avec des Secrets Kubernetes
- ✅ Comprendre la différence entre emptyDir et PVC
- ✅ Déployer une application stateful avec des identités stables
Prochaine étape : Cet après-midi, vous exposerez des applications avec Services, Ingress, et vous packagerz des déploiements avec Kustomize et Helm.