Module 2 — Kubernetes : un vrai cluster, une vraie application déployée
Bonne lecture et bon apprentissage ! Junior TSAFACK – 12/09/2026 Temps de lecture estimé : 12 minutes
Comment ce module a été démontré sans cluster cloud
Section titled “Comment ce module a été démontré sans cluster cloud”Docker Compose (vu au module précédent) orchestre plusieurs conteneurs sur une seule machine. Kubernetes résout un problème plus large : orchestrer des conteneurs sur plusieurs machines, avec auto-guérison (un conteneur qui plante est relancé automatiquement), montée en charge, et bien plus. Un vrai cluster de production tourne généralement sur plusieurs nœuds cloud — indisponibles dans cet environnement d’exécution. Ce module utilise donc k3s (une distribution Kubernetes légère mais 100 % conforme à l’API Kubernetes standard, éditée par Rancher/SUSE), démarré dans un unique conteneur Docker. Tout ce qui suit — kubectl, les manifestes, les commandes — est identique à ce qu’on utiliserait sur un vrai cluster EKS/GKE/AKS ; seule la façon dont le cluster lui-même a été mis en place diffère.
$ kubectl get nodes -o wideNAME STATUS ROLES VERSION CONTAINER-RUNTIMEfaf9dc6a1f25 Ready control-plane,master v1.30.6+k3s1 containerd://1.7.22-k3s1Namespace : isoler l’application
Section titled “Namespace : isoler l’application”apiVersion: v1kind: Namespacemetadata: name: demo-appUn namespace cloisonne un ensemble de ressources — utile pour séparer plusieurs équipes ou environnements (staging, production) sur un même cluster physique, avec des quotas et des permissions RBAC indépendants.
ConfigMap et Secret : séparer la configuration du code
Section titled “ConfigMap et Secret : séparer la configuration du code”apiVersion: v1kind: ConfigMapmetadata: name: app-config namespace: demo-appdata: REDIS_HOST: "redis" LOG_LEVEL: "info"---apiVersion: v1kind: Secretmetadata: name: app-secret namespace: demo-apptype: OpaquestringData: API_TOKEN: "demo-token-non-sensible"La différence entre les deux n’est pas une histoire de chiffrement fort par défaut (un Secret Kubernetes standard n’est encodé qu’en base64, pas chiffré, sauf configuration additionnelle du cluster) — c’est une différence d’intention et de contrôle d’accès : les RBAC Kubernetes peuvent restreindre la lecture des Secrets plus strictement que celle des ConfigMaps, et de nombreux outils (scanners de sécurité, tableaux de bord) masquent automatiquement le contenu des Secrets à l’affichage.
Deployment et Service
Section titled “Deployment et Service”apiVersion: apps/v1kind: Deploymentmetadata: name: demo-app namespace: demo-appspec: replicas: 2 selector: matchLabels: { app: demo-app } template: metadata: labels: { app: demo-app } spec: containers: - name: demo-app image: docker-avance-app:latest envFrom: - configMapRef: { name: app-config } - secretRef: { name: app-secret } resources: requests: { cpu: "50m", memory: "64Mi" } limits: { cpu: "200m", memory: "128Mi" }---apiVersion: v1kind: Servicemetadata: name: demo-app namespace: demo-appspec: selector: { app: demo-app } ports: [{ port: 80, targetPort: 5000 }]Appliqué réellement :
$ kubectl apply -f namespace.yaml -f configmap-secret.yaml -f redis.yaml -f app.yamlnamespace/demo-app createdconfigmap/app-config createdsecret/app-secret createddeployment.apps/redis createdservice/redis createddeployment.apps/demo-app createdservice/demo-app created
$ kubectl get pods -n demo-appNAME READY STATUS AGEdemo-app-7759558c7d-2vn2s 1/1 Running 93sdemo-app-7759558c7d-zn8m4 1/1 Running 93sredis-79d9b8c76d-wn29j 1/1 Running 93sVérification que ConfigMap et Secret sont bien injectés comme variables d’environnement dans le conteneur réel :
$ kubectl exec -n demo-app demo-app-7759558c7d-2vn2s -- printenv REDIS_HOST LOG_LEVEL API_TOKENredisinfodemo-token-non-sensibleLe Service : accès interne sans connaître les IP de pods
Section titled “Le Service : accès interne sans connaître les IP de pods”Les IP de pods changent à chaque redémarrage — un Service fournit une adresse stable et fait le load-balancing entre les pods qui correspondent à son selector. Test réel depuis un pod éphémère, via le DNS interne du cluster (<service>.<namespace>.svc.cluster.local) :
$ kubectl run curltest -n demo-app --rm -i --restart=Never --image=curlimages/curl \ -- curl -s http://demo-app.demo-app.svc.cluster.local/{"message":"Bonjour depuis le conteneur applicatif","visites":2}Montée en charge (scaling)
Section titled “Montée en charge (scaling)”$ kubectl scale deployment demo-app -n demo-app --replicas=4deployment.apps/demo-app scaled
$ kubectl get pods -n demo-app -l app=demo-appNAME READY STATUS AGEdemo-app-7759558c7d-2vn2s 1/1 Running 2m42sdemo-app-7759558c7d-4d7kk 1/1 Running 6sdemo-app-7759558c7d-vhmxm 1/1 Running 6sdemo-app-7759558c7d-zn8m4 1/1 Running 2m42sDeux nouveaux pods créés en quelques secondes, automatiquement répartis par le Service existant — aucune reconfiguration nécessaire, le selector du Service les prend en compte dès qu’ils portent le label app: demo-app.
Rollout : déployer un changement sans interruption
Section titled “Rollout : déployer un changement sans interruption”$ kubectl set env deployment/demo-app -n demo-app APP_VERSION=v2deployment.apps/demo-app env updateddeployment "demo-app" successfully rolled out
$ kubectl rollout history deployment/demo-app -n demo-appREVISION CHANGE-CAUSE1 <none>2 <none>Tout changement de spécification du Deployment (nouvelle image, nouvelle variable d’environnement…) déclenche un rolling update : Kubernetes crée les nouveaux pods et ne termine les anciens qu’une fois les nouveaux prêts, garantissant qu’il y a toujours des pods disponibles pour servir le trafic. kubectl rollout undo permettrait de revenir à la révision précédente en cas de problème — la même logique de sécurité qu’un git revert, appliquée à un déploiement en cours.
Prochaine étape
Section titled “Prochaine étape”Module 3 : Helm — packager et versionner un déploiement Kubernetes