Un déploiement est un objet K8s qui définit un état souhaité pour un ReplicaSet (un ensemble de Pods répliqués). Le contrôleur de déploiement cherche à maintenir l'état souhaité (3 réplicas par exemple) en créant, supprimant et remplaçant les pods par de nouvelles configurations.
Les déploiements incluent :
Il existe plusieurs cas d'utilisations d'un déploiement :
Nous allons faire un déploiement de 3 pods nginx. Pour se faire :
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3 # Nombre de réplicas
selector:
matchLabels:
app: my-deployment # Label à matcher par le déploiement
template:
metadata:
labels:
app: my-deployment # Label des pods
spec:
containers:
- name: nginx
image: nginx:1.19.1
ports:
- containerPort: 80 # Expose le port 80 du container
On va maintenant afficher les déploiements :
$ kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
my-deployment 3/3 3 3 4d6h
En listant les pods on voit que les 3 pods ont bien été créés :
$ kubectl get pods -l app=my-deployment
NAME READY STATUS RESTARTS AGE
my-deployment-cbff8c8b5-2zhjk 1/1 Running 0 4m12s
my-deployment-cbff8c8b5-hbr4q 1/1 Running 0 4m14s
my-deployment-cbff8c8b5-nbvcf 1/1 Running 0 4m11s
Si j'essaie de supprimer un pod, le déploiement va automatiquement recréer un pod :
$ kubectl delete pod my-deployment-cbff8c8b5-2zhjk
pod "my-deployment-cbff8c8b5-2zhjk" deleted
$ kubectl get pods -l app=my-deployment
NAME READY STATUS RESTARTS AGE
my-deployment-cbff8c8b5-hbr4q 1/1 Running 0 5m23s
my-deployment-cbff8c8b5-lb4ht 1/1 Running 0 3s
my-deployment-cbff8c8b5-nbvcf 1/1 Running 0 5m20s
On voit que le pod my-deployment-cbff8c8b5-lb4ht
a été recrée immédiatement. Il faudra donc supprimer le déploiement si l'on veut se débarasser des pods.
Scaling permet d'allouer plus ou moins de ressources à une application.
Si le nombre de réplicas est changé, des pods vont être ajoutés/supprimés afin de satisfaire la modification.
On peut changer le nombre de réplicas directement dans le yaml en utilisant kubectl apply ou kubectl edit ou via la commande :
$ kubectl scale deployment my-deployment --replicas=5
deployment.apps/my-deployment scaled
$ kubectl get replicasets
NAME DESIRED CURRENT READY AGE
my-deployment-5f85c44867 0 0 0 4d6h
my-deployment-cbff8c8b5 5 5 3 13m
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
my-deployment 5/5 5 5 4d6h
$ kubectl get replicasets
NAME DESIRED CURRENT READY AGE
my-deployment-5f85c44867 0 0 0 4d6h
my-deployment-cbff8c8b5 5 5 5 13m
On voit donc que le ReplicaSet a bien augmenté le nombre de pods du Déploiement.
Le système est le même si l'on veut supprimer des pods.
Un rolling update va permettre de faire des changements de version des pods d'un déploiement à une débit contrôlé, en remplaçant petit à petit les anciens pods par les nouveaux. Cela permet de mettre à jour les pods sans downtime.
On peut aussi Rollback une mise à jour. Le fonctionnement est le même qu'un rolling update, les pods seront enlevés et remis progressivement.
On va faire un changement de version sur le déploiement fait auparavant :
$ kubectl edit deployment my-deployment
# Dans la section spec.template :
template:
metadata:
creationTimestamp: null
labels:
app: my-deployment
spec:
containers:
- image: nginx:1.19.2
Une fois validé (:wq) on peut voir qu'un nouveau ReplicaSet a été crée afin de procéder à la mise à jour :
cloud_user@k8s-control:~$ kubectl get pod
NAME READY STATUS RESTARTS AGE
my-deployment-7d655f6776-4z6c9 0/1 ContainerCreating 0 4s
my-deployment-7d655f6776-bs7pc 0/1 ContainerCreating 0 5s
my-deployment-7d655f6776-fdqkp 0/1 ContainerCreating 0 5s
my-deployment-7d655f6776-km5qh 0/1 ContainerCreating 0 5s
my-deployment-7d655f6776-vzj2z 0/1 ContainerCreating 0 5s
my-deployment-cbff8c8b5-2825j 0/1 Terminating 0 26s
my-deployment-cbff8c8b5-2c562 1/1 Running 0 26s
my-deployment-cbff8c8b5-9bb84 1/1 Running 0 26s
my-deployment-cbff8c8b5-hbr4q 1/1 Running 0 26m
my-deployment-cbff8c8b5-jbgd9 1/1 Running 0 26s
my-deployment-cbff8c8b5-lb4ht 1/1 Running 0 20m
my-deployment-cbff8c8b5-n4nvp 0/1 Terminating 0 26s
my-deployment-cbff8c8b5-n6sgx 1/1 Running 0 26s
my-deployment-cbff8c8b5-pqzgf 1/1 Running 0 26s
my-deployment-cbff8c8b5-xw8sq 1/1 Running 0 26s
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
my-deployment-7d655f6776 9 9 4 10s
my-deployment-cbff8c8b5 4 4 4 26m
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
my-deployment-7d655f6776 10 10 10 16s
my-deployment-cbff8c8b5 0 0 0 26m
Progressivement (mais rapidement) l'ancien ReplicaSet terminera des pods, le nouveau en créera afin d'atteindre son DesiredState de 10 avec la nouvelle MAJ nginx.
On pourrait aussi mettre à jour l'image nginx via la commande :
$ kubectl set image deployment my-deployment nginx=nginx:mauvaiseimage --record
deployment.apps/my-deployment image updated
Mince... La version nginx:mauvaiseimage nginx n'existe pas, on va donc rollback :
# On vérifie le statut de la MAJ :
$ kubectl rollout status deployment my-deployment
Waiting for deployment "my-deployment" rollout to finish: 5 out of 10 new replicas have been updated...
$ kubectl get pod -l app=my-deployment
NAME READY STATUS RESTARTS AGE
...
my-deployment-7d655f6776-4z6c9 1/1 Running 0 9m40s
my-deployment-7d655f6776-vzj2z 1/1 Running 0 9m41s
...
my-deployment-f7fbc4dcf-tbgk9 0/1 ErrImagePull 0 75s
my-deployment-f7fbc4dcf-zh9vb 0/1 ImagePullBackOff 0 75s
On voit ici que l'image n'arrive pas à être pull. Cependant des pods nginx tourne toujours. Notre application est donc toujours accessible. On va vérifier l'historique de MAJ :
$ kubectl rollout history deployment my-deployment
deployment.apps/my-deployment
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
4 kubectl set image deployment my-deployment nginx=nginx:mauvaiseimage --record=true
--record nous a permis de garder une trace de la dernière commande avant le rolling update.
On va maintenant rollback au niveau du 3 :
$ kubectl rollout undo deployment my-deployment
deployment.apps/my-deployment rolled back
Le ReplicaSet va se charger de remettre 10 pods sur la version précédente. On peut préciser la révision grace au paramètre --to-revision=3.