Skip to content

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 wide
NAME STATUS ROLES VERSION CONTAINER-RUNTIME
faf9dc6a1f25 Ready control-plane,master v1.30.6+k3s1 containerd://1.7.22-k3s1
namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: demo-app

Un 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”
configmap-secret.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: demo-app
data:
REDIS_HOST: "redis"
LOG_LEVEL: "info"
---
apiVersion: v1
kind: Secret
metadata:
name: app-secret
namespace: demo-app
type: Opaque
stringData:
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.

app.yaml (extrait)
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app
namespace: demo-app
spec:
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: v1
kind: Service
metadata:
name: demo-app
namespace: demo-app
spec:
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.yaml
namespace/demo-app created
configmap/app-config created
secret/app-secret created
deployment.apps/redis created
service/redis created
deployment.apps/demo-app created
service/demo-app created
$ kubectl get pods -n demo-app
NAME READY STATUS AGE
demo-app-7759558c7d-2vn2s 1/1 Running 93s
demo-app-7759558c7d-zn8m4 1/1 Running 93s
redis-79d9b8c76d-wn29j 1/1 Running 93s

Vé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_TOKEN
redis
info
demo-token-non-sensible

Le 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}
$ kubectl scale deployment demo-app -n demo-app --replicas=4
deployment.apps/demo-app scaled
$ kubectl get pods -n demo-app -l app=demo-app
NAME READY STATUS AGE
demo-app-7759558c7d-2vn2s 1/1 Running 2m42s
demo-app-7759558c7d-4d7kk 1/1 Running 6s
demo-app-7759558c7d-vhmxm 1/1 Running 6s
demo-app-7759558c7d-zn8m4 1/1 Running 2m42s

Deux 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=v2
deployment.apps/demo-app env updated
deployment "demo-app" successfully rolled out
$ kubectl rollout history deployment/demo-app -n demo-app
REVISION CHANGE-CAUSE
1 <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.

Module 3 : Helm — packager et versionner un déploiement Kubernetes