Avec Docker et Compose, vous savez lancer des conteneurs sur une machine. Kubernetes répond à la question suivante : comment faire tourner des dizaines de conteneurs sur plusieurs machines, les redémarrer quand ils tombent, les mettre à jour sans coupure et les répartir selon les ressources disponibles ? Dans ce cours, on part d’images déjà construites et publiées dans un registre (voir le cours Docker) : on ne réécrit pas de Dockerfile.
L’architecture d’un cluster
Un cluster Kubernetes se compose de deux parties.
- Le plan de contrôle (control plane) prend les décisions : l’API server reçoit toutes les demandes (y compris celles de
kubectl), etcd stocke l’état du cluster, le scheduler choisit sur quel nœud placer chaque pod, le controller manager fait tourner les contrôleurs qui corrigent les écarts. - Les nœuds (nodes) exécutent les conteneurs : sur chacun, le kubelet lance les pods demandés via un moteur de conteneurs (containerd le plus souvent) et kube-proxy gère le réseau des services.
Sur un service managé (GKE, EKS, AKS…), le fournisseur opère le plan de contrôle pour vous. En local, minikube ou kind créent un cluster complet sur votre poste :
minikube start # ou : kind create cluster --name atelier
kubectl get nodes # un nœud doit être Ready
kubectl cluster-info
L’état désiré et la réconciliation
On ne dit pas à Kubernetes « lance trois conteneurs ». On lui décrit l’état désiré : « je veux trois répliques de cette image ». Des contrôleurs comparent sans cesse cet état à la réalité et corrigent l’écart. Si un nœud tombe, les pods manquants sont recréés ailleurs ; si vous supprimez un pod, il revient. C’est la boucle de réconciliation.
Le pod, plus petite unité
Un pod regroupe un ou plusieurs conteneurs qui partagent une adresse IP et peuvent partager des volumes. Dans la grande majorité des cas, un pod contient un seul conteneur applicatif. Un pod est éphémère : son IP change à chaque recréation, et un pod créé seul n’est pas recréé s’il disparaît. On ne crée donc pas de pods directement : on passe par un Deployment.
Un manifeste Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: notes-api
labels:
app: notes-api
spec:
replicas: 3
selector:
matchLabels:
app: notes-api # doit correspondre aux labels du template
template:
metadata:
labels:
app: notes-api
spec:
containers:
- name: notes-api
image: hashicorp/http-echo:0.2.3
args: ["-text=notes-api v1"]
ports:
- containerPort: 5678
Chaque objet a la même structure : apiVersion et kind (le type d’objet), metadata (nom, labels), spec (l’état désiré). Les labels sont des étiquettes clé-valeur ; le sélecteur est la requête qui retrouve les objets portant ces étiquettes. Le Deployment crée un ReplicaSet qui, lui, maintient le bon nombre de pods.
kubectl apply -f deployment.yaml
kubectl get deploy notes-api # READY 3/3
kubectl get rs,pods -l app=notes-api # le ReplicaSet et ses trois pods
kubectl delete pod <un-des-pods> # il est aussitôt remplacé
L’approche déclarative (kubectl apply -f sur des fichiers versionnés dans Git) est la norme : on modifie le fichier, on le réapplique, et l’historique Git documente chaque changement. Les commandes impératives (kubectl create, kubectl edit) dépannent mais créent un écart entre le dépôt et le cluster.
Mettre à jour sans coupure : le rolling update
Modifier le template (par exemple l’image ou ses arguments) crée un nouveau ReplicaSet. Kubernetes remplace alors les pods progressivement : par défaut, il peut créer jusqu’à 25 % de pods en plus (maxSurge) et en rendre indisponibles au plus 25 % (maxUnavailable) pendant la bascule.
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0 # jamais moins de 3 pods prêts
kubectl set image deploy/web nginx=nginx:1.27 # ou modifier le fichier puis apply
kubectl rollout status deploy/web # suit la progression
kubectl rollout history deploy/web # révisions connues
kubectl rollout undo deploy/web # retour à la révision précédente
L’ancien ReplicaSet est conservé (mis à zéro réplique) : c’est lui qui rend le retour arrière immédiat. Comme avec Docker, utilisez des tags immuables : avec latest, impossible de savoir quelle version tourne ni de revenir en arrière de façon fiable.
Exercices
Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.
Premier Deployment à trois répliques
Travaillez sur un cluster local :
minikube start(oukind create cluster). Vérifiez aveckubectl get nodesqu’un nœud estReadyavant de commencer.Créez le fichier
deployment.yamlde la leçon (Deploymentnotes-api, 3 répliques, imagehashicorp/http-echo:0.2.3, argument-text=notes-api v1, labelapp: notes-api), appliquez-le, puis supprimez un des pods et observez le résultat.- `kubectl apply -f deployment.yaml` affiche `deployment.apps/notes-api created`
- `kubectl get deploy notes-api` affiche READY `3/3`
- `kubectl get pods -l app=notes-api` liste exactement 3 pods en statut `Running`
- Après `kubectl delete pod <nom>`, une nouvelle commande `kubectl get pods -l app=notes-api` liste de nouveau 3 pods, dont un avec un AGE de quelques secondes
Mise à jour puis retour arrière
Créez un Deployment
webà 2 répliques avec l’imagenginx:1.26(nom du conteneur :nginx). Mettez-le à jour versnginx:1.27, suivez le déploiement, puis revenez à la version précédente.- `kubectl rollout status deploy/web` affiche `deployment "web" successfully rolled out` après la mise à jour
- `kubectl rollout history deploy/web` affiche au moins 2 révisions
- Après `kubectl rollout undo deploy/web`, `kubectl get deploy web -o jsonpath='{.spec.template.spec.containers[0].image}'` affiche `nginx:1.26`
- `kubectl get rs -l app=web` montre deux ReplicaSets, dont un à 0 réplique
Le rôle du sélecteur
Dans un Deployment, à quoi sert
spec.selector.matchLabels?- À choisir le nœud sur lequel placer les pods
- À indiquer quels pods appartiennent à ce Deployment, en les retrouvant par leurs labels
- À nommer l'image à télécharger
- À définir le nombre de répliques
Quiz de fin de leçon
Que se passe-t-il si vous supprimez un pod géré par un Deployment ?
- Le Deployment est supprimé aussi
- Le ReplicaSet recrée un pod pour revenir au nombre de répliques désiré
- Rien, il faut le recréer à la main
Quel composant choisit le nœud sur lequel un pod va s’exécuter ?
- Le kubelet
- Le scheduler
- etcd
Quelle commande revient à la version précédente d’un Deployment ?
- kubectl rollout undo deploy/web
- kubectl delete deploy/web
- kubectl rollback web
La suite du cours
- Services et Ingress : exposer une application18 min
- Configuration, secrets et namespaces18 min
- Mise à l'échelle et résilience20 min
- Observabilité et dépannage20 min