ReplicaSet
Dans l’article précédent sur les Deployments (Lien vers la page), nous avons créé un deployment pour lancer 3 replicas d’un même pod. Je vous ai dit que c’est le deployment qui se chargeait d’avoir toujours 3 pods qui tournaient en même temps. J’ai menti. Ou plutôt, je n’ai pas été assez précis.
Ce n’est pas le Deployment qui se charge du nombre de replicas des pods, c’est un autre type de ressources qui s’appelle un ReplicaSet. Le Deployment est une ressource de plus haut niveau qui contrôle les ReplicaSets.
Si on revient à notre Deployment de l’article précédent :
$ kubectl -n ns-nginx get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 3 3 5m4s
Ce Deployment a créé en vérité un ReplicaSet :
$ kubectl -n ns-nginx get replicaset
NAME DESIRED CURRENT READY AGE
nginx-deploy-65bdccd7c7 3 3 3 5m13s
Le nom du Deployment est suffixé par une chaîne de caractères aléatoire pour identifier le ReplicaSet.
Et si on essaye de voir les pods :
$ kubectl -n ns-nginx get pods
NAME READY STATUS RESTARTS AGE
nginx-deploy-65bdccd7c7-ckf95 1/1 Running 0 5m22s
nginx-deploy-65bdccd7c7-mjtjj 1/1 Running 0 5m22s
nginx-deploy-65bdccd7c7-pgzpm 1/1 Running 0 5m22s
Le nom du ReplicaSet est encore suffixé par une chaîne de caractères aléatoire pour identifier chaque pod. On peut comprendre que c’est donc bien le ReplicaSet qui gère directement le pod.
Pourquoi utiliser un Deployment en plus d’un ReplicaSet ?
Un ReplicaSet gère les pods, mais il ne gère pas la mise à jour des pods si on a besoin d’aller vers une nouvelle version de l’image par exemple. Pour cela, il faudra un nouveau ReplicaSet avec la nouvelle image des pods. Donc il faudra aller créer un nouveau ReplicaSet avec la nouvelle image avec les trois replicas souhaités par exemple, et enlever l’ancien ReplicaSet avec l’ancienne image. Ça s’appelle une stratégie de RollingUpdate. C’est ce que fait un Deployment.
Mettre à jour le nombre de replicas
Avant de voir comment marche le RollingUpdate d’un deployment, nous allons d’abord augmenter le nombre de replicas dans notre deployment de 3 à 5 pods. Pour cela, on peut utiliser la commande :
$ kubectl -n ns-nginx scale deployment nginx-deploy --replicas=5
deployment.apps/nginx-deploy scaled
Si nous regardons assez vite le rollout du deployment, nous pouvons voir qu’il est en train de passer de 3 à 5 pods :
$ kubectl -n ns-nginx rollout status deployment nginx-deploy
Waiting for deployment "nginx-deploy" rollout to finish: 4 of 5 updated replicas are available...
deployment "nginx-deploy" successfully rolled out
Une fois le rollout fini, nous pouvons voir que le deployment est passé à 5 pods.
$ kubectl -n ns-nginx get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 5/5 5 5 6m
Et en réalité, le deployment a fait passer le ReplicaSet sous-jacent à 5 replicas, et le ReplicaSet a mis à jour le nombre de pods à 5, comme nous pouvons le voir ici :
$ kubectl -n ns-nginx get replicaset
NAME DESIRED CURRENT READY AGE
nginx-deploy-65bdccd7c7 5 5 5 6m
$ kubectl -n ns-nginx get pods
NAME READY STATUS RESTARTS AGE
nginx-deploy-65bdccd7c7-ckf95 1/1 Running 0 6m
nginx-deploy-65bdccd7c7-mjtjj 1/1 Running 0 6m
nginx-deploy-65bdccd7c7-pgzpm 1/1 Running 0 6m
nginx-deploy-65bdccd7c7-pjkf7 1/1 Running 0 30s
nginx-deploy-65bdccd7c7-xbbfl 1/1 Running 0 30s
RollingUpdate - mettre à jour l’image du pod
Nous allons maintenant mettre à jour l’image de nginx dans le deployment de la version 1.22 à 1.23.
Pour cela, on peut changer le tag de l’image dans le fichier YAML, ou on peut éditer le deployment directement avec la commande suivante :
$ kubectl -n ns-nginx edit deployment/nginx-deploy
...
spec:
containers:
- image: nginx:1.23
imagePullPolicy: IfNotPresent
...
deployment.apps/nginx-deploy edited
On peut vérifier l’état des ReplicaSets :
$ kubectl -n ns-nginx get replicaset
NAME DESIRED CURRENT READY AGE
nginx-deploy-65bdccd7c7 0 0 0 7m
nginx-deploy-697fb99c54 5 5 5 6s
On voit que le Deployment a créé un nouveau ReplicaSet avec 5 replicas, et que l’ancien ReplicaSet est passé à 0. Le nombre de ReplicaSet qui sont conservés dans l’historique est déterminé par une option qui s’appelle revisionHistoryLimit dans la spec du deployment. Par défaut, elle est à 10.
On peut voir les pods déployés par le nouveau ReplicaSet
$ kubectl -n ns-nginx get pods
NAME READY STATUS RESTARTS AGE
nginx-deploy-697fb99c54-fzd6k 1/1 Running 0 15s
nginx-deploy-697fb99c54-hlmrc 1/1 Running 0 15s
nginx-deploy-697fb99c54-tgmjh 1/1 Running 0 12s
nginx-deploy-697fb99c54-x5p68 1/1 Running 0 12s
nginx-deploy-697fb99c54-zfr26 1/1 Running 0 15s
Si on essaye de voir l’image utilisée par les nouveaux pods, on voit bien que c’est la 1.23 qu’on a demandée :
$ kubectl -n ns-nginx get pods nginx-deploy-697fb99c54-zfr26 -o jsonpath='{.spec.containers[0].image}'
nginx:1.23
On peut voir l’historique des changements du Deployment :
$ kubectl -n ns-nginx rollout history deployment nginx-deploy
deployment.apps/nginx-deploy
REVISION CHANGE-CAUSE
1 <none>
2 <none>
On voit bien qu’il y a eu deux révisions. La première est celle avec l’image 1.22, la seconde avec l’image 1.23. Pour information, le champ CHANGE-CAUSE est vide car nous n’avons pas lancé le déploiement avec l’option —record=true qui n’est pas par défaut. Si on l’avait activée, on aurait vu dans le champ en question quelle commande est à l’origine de la révision. Vous pouvez faire le test avec la commande qui lance de deployment :
$ kubectl apply -f nginx-deploy.yaml --record=true
Revenir à l’ancienne version de l’image
Si jamais la nouvelle version de l’application cause des problèmes, la ressource Deployment nous permet de revenir à l’ancienne version de l’image qui marchait avant la mise à jour. Pour cela, on peut faire :
$ kubectl -n ns-nginx rollout undo deployment nginx-deploy
deployment.apps/nginx-deploy rolled back
On voit que le Deployment a remis l’ancien ReplicaSet à 5 replicas et mis le nouveau ReplicaSet à 0.
$ kubectl -n ns-nginx get replicaset
NAME DESIRED CURRENT READY AGE
nginx-deploy-65bdccd7c7 5 5 5 7m
nginx-deploy-697fb99c54 0 0 0 42s
On peut voir que l’ancien ReplicaSet a lancé les 5 pods :
$ kubectl -n ns-nginx get pods
NAME READY STATUS RESTARTS AGE
nginx-deploy-65bdccd7c7-2n55g 1/1 Running 0 12s
nginx-deploy-65bdccd7c7-9cx45 1/1 Running 0 12s
nginx-deploy-65bdccd7c7-b4x6q 1/1 Running 0 10s
nginx-deploy-65bdccd7c7-p7jkc 1/1 Running 0 12s
nginx-deploy-65bdccd7c7-spgqr 1/1 Running 0 10s
Et si on vérifie l’image utilisée par un de ces pods, on voit bien que c’est la 1.22, donc l’ancienne :
$ kubectl -n ns-nginx get pods nginx-deploy-65bdccd7c7-9cx45 -o jsonpath='{.spec.containers[0].image}'
nginx:1.22
Conclusion
J’espère que vous comprenez maintenant comment marchent les Deployments avec les ReplicaSets, et comment les premiers utilisent les seconds pour gérer le nombre de replicas d’un pod ou la version de l’image déployée par exemple.