Aller au contenu
English
Conteneurs & Orchestration medium

ReplicaSet Kubernetes : comprendre ce que crée un Deployment

35 min de lecture

logo kubernetes

Un ReplicaSet garantit qu'un nombre défini de Pods reste toujours actif. Si un Pod disparaît, le ReplicaSet le recrée automatiquement. En pratique, vous ne créez jamais de ReplicaSet directement : c'est le Deployment qui s'en charge, et qui y ajoute les mises à jour progressives et les rollbacks.

Ce guide sert donc à comprendre ce qui se passe sous le capot de vos Deployments : quel objet crée réellement vos Pods, comment il les reconnaît, et pourquoi il peut en adopter un que vous avez créé vous-même.

Un ReplicaSet maintient un nombre donné de Pods en fonctionnement. Un Deployment ajoute par-dessus la gestion des versions, des rolling updates et des rollbacks. En pratique, on manipule surtout des Deployments, qui créent et pilotent les ReplicaSets automatiquement.

RessourceRôle principal
ReplicaSetMaintenir un nombre donné de Pods
DeploymentGérer les versions, mises à jour et rollbacks via des ReplicaSets
  • Comprendre le rôle du ReplicaSet dans l'architecture Kubernetes
  • Observer les ReplicaSets créés automatiquement par vos Deployments
  • Distinguer ce que fait le ReplicaSet de ce que fait le Deployment
  • Diagnostiquer un problème au niveau du ReplicaSet

Un ReplicaSet est un contrôleur Kubernetes avec une mission simple : maintenir N Pods identiques en fonctionnement.

Son rôle :

  1. Surveiller les Pods qui correspondent à son sélecteur de labels
  2. Compter combien tournent réellement à cet instant
  3. Créer ou supprimer des Pods jusqu'à atteindre le nombre déclaré dans replicas

Quand vous créez un Deployment, Kubernetes crée automatiquement un ReplicaSet. Vérifiez-le :

Fenêtre de terminal
kubectl get deployments
kubectl get rs

Exemple de sortie :

NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 3 3 5m
NAME DESIRED CURRENT READY AGE
nginx-deploy-7c4bbb5456 3 3 3 5m

Le nom nginx-deploy-7c4bbb5456 combine le nom du Deployment et un hash du template de Pod. C'est ce hash qui explique la suite : changez le template, vous obtenez un autre hash, donc un autre ReplicaSet.

Chaque objet sait qui l'a créé, et cette information vit dans son champ ownerReferences. Kubernetes s'en sert pour savoir quoi supprimer quand vous supprimez un parent. Les deux commandes ci-dessous remontent la chaîne d'un cran chacune.

Chaîne de propriété Kubernetes : Deployment crée ReplicaSet qui maintient les Pods

Vérifiez le propriétaire d'un ReplicaSet :

Fenêtre de terminal
kubectl get rs nginx-deploy-7c4bbb5456 -o jsonpath='{.metadata.ownerReferences[0].kind}'
# Résultat : Deployment

Et le propriétaire d'un Pod :

Fenêtre de terminal
kubectl get pods -l app=nginx-deploy -o jsonpath='{.items[0].metadata.ownerReferences[0].kind}'
# Résultat : ReplicaSet

Retenez cette chaîne Deployment vers ReplicaSet vers Pod : elle explique pourquoi supprimer un Deployment emporte tout le reste.

Pourquoi un Deployment crée un nouveau ReplicaSet à chaque mise à jour

Section intitulée « Pourquoi un Deployment crée un nouveau ReplicaSet à chaque mise à jour »

Quand vous changez l'image d'un Deployment, Kubernetes crée un nouveau ReplicaSet au lieu de modifier l'existant :

Fenêtre de terminal
kubectl set image deployment/nginx-deploy \
nginx=nginx:1.30@sha256:d5792f71a9496b833bc08ea834a758c46e2b6a6306c10f4be926f38a656cdc1c
kubectl get rs -l app=nginx-deploy

Résultat :

NAME DESIRED CURRENT READY AGE
nginx-deploy-6dcbfb4f85 3 3 3 2s
nginx-deploy-7c4bbb5456 0 0 0 3s

Pourquoi ? Le Deployment garde l'ancien ReplicaSet, ramené à 0 replicas, pour permettre un rollback instantané. Un ReplicaSet à zéro ne coûte rien : il ne reste qu'une définition, prête à remonter si vous revenez en arrière.

Un ReplicaSet contient 3 éléments essentiels :

ChampDescriptionExemple
replicasNombre de Pods à maintenir3
selectorLabels pour identifier les Pods gérésapp: echo
templateModèle de Pod à créerImage, ports, etc.
replicaset-demo.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: echo-rs
spec:
replicas: 3
selector:
matchLabels:
app: echo
template:
metadata:
labels:
app: echo # DOIT correspondre au selector
spec:
containers:
- name: echo
image: nginx:1.29-alpine@sha256:5616878291a2eed594aee8db4dade5878cf7edcb475e59193904b198d9b830de

Le commentaire sur les labels n'est pas une recommandation : l'API refuse le manifeste si template.metadata.labels ne correspond pas à selector.matchLabels.

The ReplicaSet "rs-labels-faux" is invalid: spec.template.metadata.labels:
Invalid value: {"app":"different"}: `selector` does not match template `labels`

La raison est logique. Un ReplicaSet qui créerait des Pods qu'il ne sait pas retrouver n'en verrait jamais aucun, et en créerait indéfiniment sans jamais atteindre son compte.

Cas particulier : créer un ReplicaSet manuellement

Section intitulée « Cas particulier : créer un ReplicaSet manuellement »

Dans la pratique, ce cas est rare. Il sert aux démonstrations, aux tests, et à comprendre ce qu'un Deployment fait en dessous. C'est ce manifeste que le reste du guide manipule.

Fenêtre de terminal
kubectl apply -f replicaset-demo.yaml
kubectl get rs echo-rs
Sortie
replicaset.apps/echo-rs created
NAME DESIRED CURRENT READY AGE
echo-rs 3 3 3 1s

Le selector : comment le ReplicaSet trouve ses Pods

Section intitulée « Le selector : comment le ReplicaSet trouve ses Pods »

Le selector est la règle qui définit quels Pods appartiennent au ReplicaSet. Le ReplicaSet surveille uniquement les Pods qui ont les labels correspondants.

selector:
matchLabels:
app: nginx
environment: production

Équivalent à : "sélectionne les Pods où app=nginx ET environment=production".

Quand l'égalité stricte ne suffit pas, Kubernetes propose quatre opérateurs : In et NotIn comparent le label à une liste de valeurs, Exists et DoesNotExist ne regardent que sa présence, sans se soucier de la valeur.

selector:
matchExpressions:
- key: environment
operator: In
values: ["production", "staging"]

Ce selector retient les Pods de production et de staging. Sur un Deployment classique, vous n'en aurez pas besoin : matchLabels couvre la quasi-totalité des cas.

Le selector d'un ReplicaSet existant ne peut pas être changé. Ce n'est pas une bonne pratique, c'est un refus de l'API. Tentez le patch, vous recevez deux erreurs d'un coup :

Fenêtre de terminal
kubectl patch rs echo-rs --type=merge \
-p '{"spec":{"selector":{"matchLabels":{"app":"modifie"}}}}'
Sortie
The ReplicaSet "echo-rs" is invalid:
* spec.template.metadata.labels: Invalid value: {"app":"echo"}: `selector` does not match template `labels`
* spec.selector: Invalid value: {"matchLabels":{"app":"modifie"}}: field is immutable

Les deux lignes se comprennent ensemble. En changeant le selector seul, vous cassez la correspondance avec le template, d'où la première. Et le champ est de toute façon immuable, d'où la seconde.

Pour changer la sélection, il faut supprimer et recréer le ReplicaSet. C'est exactement ce qu'un Deployment fait à votre place à chaque mise à jour, et c'est pourquoi il crée un nouveau ReplicaSet au lieu de modifier l'ancien.

Le ReplicaSet ne possède pas ses Pods, il les revendique

Section intitulée « Le ReplicaSet ne possède pas ses Pods, il les revendique »

Voici le point qui surprend, et qui explique tout le reste. Un ReplicaSet ne tient aucune liste des Pods qu'il a créés. À chaque instant, il compte les Pods qui portent les labels de son selector, dans son namespace, et compare ce nombre à replicas. D'où viennent ces Pods ne l'intéresse pas.

La démonstration tient en une expérience. Créez d'abord un Pod seul portant le label app=echo, puis appliquez un ReplicaSet qui demande 3 replicas sur ce même label :

Fenêtre de terminal
kubectl run solitaire --labels='app=echo' \
--image=nginx:1.29-alpine@sha256:5616878291a2eed594aee8db4dade5878cf7edcb475e59193904b198d9b830de
kubectl apply -f replicaset-demo.yaml
kubectl describe rs echo-rs | sed -n '/Events:/,$p'
Sortie
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 8s replicaset-controller Created pod: echo-rs-hg5pk
Normal SuccessfulCreate 8s replicaset-controller Created pod: echo-rs-mhrbs

Deux créations pour trois replicas. Le troisième Pod, le ReplicaSet l'a simplement compté : il existait déjà, il porte le bon label, il fait l'affaire. Retenez-en la conséquence pratique, qui suffit à ce stade : deux contrôleurs ne doivent jamais partager un selector, sous peine de se disputer les mêmes Pods.

Ce contrôleur est volontairement limité, et c'est ce qui le rend prévisible. Les deux tableaux ci-dessous séparent ce qu'il prend en charge de ce qu'il laisse au Deployment.

Le ReplicaSet a une seule obsession : ramener le nombre de Pods vivants à la valeur replicas. Les trois lignes ci-dessous décrivent les seules situations où il agit, et elles réagissent toutes au même signal, un écart entre l'état observé et l'état souhaité. C'est ce qui explique qu'un Pod supprimé à la main réapparaisse aussitôt.

ActionComportement
Pod supprimé ou absentCrée un nouveau Pod pour revenir à l'état souhaité
Scale up demandéCrée les Pods manquants
Scale down demandéSupprime les Pods excédentaires

Ses limites tiennent toutes à la même cause : le ReplicaSet regarde combien de Pods tournent, jamais lesquels. Un Pod qui tourne avec une vieille image lui convient parfaitement.

LimitationConséquence
Mise à jour des PodsModifier le template n'affecte pas les Pods existants
Rolling updatePas de mise à jour progressive
RollbackPas d'historique des versions

Démonstration : partez des trois Pods en nginx:1.29-alpine et changez l'image du ReplicaSet.

Fenêtre de terminal
kubectl set image rs/echo-rs \
echo=nginx:1.30@sha256:d5792f71a9496b833bc08ea834a758c46e2b6a6306c10f4be926f38a656cdc1c
kubectl get pods -l app=echo \
-o custom-columns='POD:.metadata.name,IMAGE:.spec.containers[0].image' | cut -d@ -f1
Sortie
POD IMAGE
echo-rs-n7xgp nginx:1.29-alpine
echo-rs-n9rsq nginx:1.29-alpine
echo-rs-tp2h4 nginx:1.29-alpine

Le cut -d@ -f1 coupe l'affichage au digest pour garder la sortie lisible ; les images restent bien épinglées.

Rien n'a bougé. Le template du ReplicaSet, lui, a bien changé :

Fenêtre de terminal
kubectl get rs echo-rs -o jsonpath='{.spec.template.spec.containers[0].image}' | cut -d@ -f1
# nginx:1.30

Les Pods existants gardent donc l'ancienne image, et seuls les nouveaux prendront la nouvelle. Vérifiez-le en supprimant un Pod : le ReplicaSet le recrée aussitôt, à partir du template à jour.

Fenêtre de terminal
kubectl delete pod echo-rs-n7xgp
kubectl get pods -l app=echo \
-o custom-columns='POD:.metadata.name,IMAGE:.spec.containers[0].image' | cut -d@ -f1
Sortie
POD IMAGE
echo-rs-bnzfn nginx:1.30
echo-rs-n9rsq nginx:1.29-alpine
echo-rs-tp2h4 nginx:1.29-alpine

Un Pod sur trois a changé de version, les deux autres tournent encore en 1.29. Votre application sert donc deux versions différentes pour une durée indéterminée. C'est exactement ce qu'un rolling update évite : il remplace les Pods un par un, à un rythme contrôlé, et sait quand s'arrêter.

Modifier directement un ReplicaSet sert à comprendre son comportement, pas à travailler.

Deux commandes couvrent l'essentiel du diagnostic. kubectl get rs répond en une ligne à la question « est-ce que ça va », et kubectl describe rs dit pourquoi quand la réponse est non.

kubectl get rs est le premier réflexe de diagnostic. La comparaison qui compte tient en trois colonnes : si READY est inférieur à DESIRED, des Pods ne démarrent pas et il faut creuser. Tant que les trois chiffres sont égaux, le ReplicaSet va bien.

Fenêtre de terminal
kubectl get rs
NAME DESIRED CURRENT READY AGE
echo-rs 3 3 3 2m
ColonneSignification
DESIREDNombre de Pods demandé (replicas)
CURRENTNombre de Pods créés
READYNombre de Pods prêts (passant les probes)

Un écart entre CURRENT et READY a un sens précis : les Pods existent mais ne répondent pas encore. Cherchez alors du côté de l'application, pas du ReplicaSet.

kubectl describe rs affiche le selector, le template complet et surtout les événements, qui racontent ce que le contrôleur a fait et quand. C'est là que se lisent les créations, les suppressions et les échecs.

Fenêtre de terminal
kubectl describe rs echo-rs
Extrait de sortie
Name: echo-rs
Namespace: demo
Selector: app=echo
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 18s replicaset-controller Created pod: echo-rs-6t29p

La ligne Pods Status est la plus utile en incident : elle ventile les Pods par état et dit immédiatement si le problème est un démarrage bloqué, Waiting, ou un plantage, Failed.

Le nombre de replicas se change sans recréer l'objet, et l'effet est immédiat :

Fenêtre de terminal
kubectl scale rs echo-rs --replicas=5

Sur un ReplicaSet géré par un Deployment, la manipulation ne tient pas. Le Deployment réimpose sa propre valeur, et la course est visible si vous interrogez tout de suite après :

Fenêtre de terminal
kubectl scale rs web-6ccc87495d --replicas=5
kubectl get rs web-6ccc87495d
Sortie
replicaset.apps/web-6ccc87495d scaled
NAME DESIRED CURRENT READY AGE
web-6ccc87495d 2 5 2 1s

DESIRED est déjà revenu à 2 alors que 5 Pods venaient d'être créés. Dix secondes plus tard, les trois surnuméraires ont disparu. Pour changer durablement le nombre de Pods, visez le Deployment : kubectl scale deployment/web --replicas=5.

Un ReplicaSet qui ne tient pas son compte a presque toujours un problème en dessous de lui, au niveau des Pods. La démarche consiste donc à descendre la chaîne, un cran à la fois.

  1. Vérifier l'état du ReplicaSet

    Fenêtre de terminal
    kubectl get rs

    Si READY < DESIRED, des Pods ne démarrent pas.

  2. Lister les Pods associés

    Fenêtre de terminal
    kubectl get pods -l app=echo

    Identifiez les Pods en Pending, CrashLoopBackOff ou Error.

  3. Inspecter les événements du ReplicaSet

    Fenêtre de terminal
    kubectl describe rs echo-rs | grep -A 20 Events
  4. Diagnostiquer un Pod spécifique

    Fenêtre de terminal
    kubectl describe pod <nom-du-pod>
    kubectl logs <nom-du-pod>

Quand un ReplicaSet ne tient pas son compte de Pods, la cause est presque toujours en dehors de lui : ressources insuffisantes, nœud saturé, image qui plante, ou labels qui ne correspondent pas. Le tableau relie chaque symptôme observable à sa cause la plus fréquente et à la commande qui confirme le diagnostic.

SymptômeCause probableSolution
CURRENT < DESIREDQuota de ressources atteintVérifier kubectl describe ns <namespace>
Pods en PendingPas de node disponiblekubectl get nodes, libérer des ressources
Pods en CrashLoopBackOffErreur applicativeVérifier les logs du Pod
selector ne match pasLabels incohérentsComparer selector et template.labels
Un Pod inconnu dans le lotUn autre objet partage le selectorkubectl get pods -l app=echo -o wide

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent sur la relation Deployment / ReplicaSet / Pod, la façon dont le selector revendique les Pods, et ce que le ReplicaSet ne gère pas.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

7 questions
5 min.
80% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  1. Un ReplicaSet maintient N Pods identiques, mais ne gère pas les mises à jour
  2. Un Deployment crée et gère les ReplicaSets automatiquement
  3. À chaque mise à jour, le Deployment crée un nouveau ReplicaSet (rollback possible)
  4. Le ReplicaSet ne connaît pas ses Pods : il compte ceux qui portent les labels de son selector
  5. Il peut donc adopter un Pod préexistant qui porte les bons labels, d'où la règle : deux contrôleurs ne partagent jamais un selector
  6. Le selector est immuable : pour le changer, il faut recréer l'objet
  7. En pratique, vous n'interagissez pas directement avec les ReplicaSets
  • Les StatefulSets : Le contrôleur équivalent pour les Pods qui exigent une identité stable.
  • Les DaemonSets : Le contrôleur qui raisonne par nœud plutôt que par nombre de réplicas.
  • Horizontal Pod Autoscaler : Le composant qui fait varier ce nombre de réplicas automatiquement.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn