Abbiamo visto sinora che il Deployment è una delle componenti più centrali nel lavoro di Kubernetes. Quando sviluppiamo le nostre applicazioni identifichiamo le immagini container di cui abbiamo bisogno (create da noi o recuperate da Registry altrui) ed utilizziamo il Deployment per gestire queste unità operative.
Sempre tramite Deployment possiamo gestire il ciclo di vita dell'applicazione occupandoci del rollout delle versioni: anche per questo vengono messi a disposizione specifici comandi con cui possiamo fornire l'aggiornamento dei Pod che rappresentano l'applicazione in produzione.
Scopriamo però che una delle capacità principali di Kubernetes è quella di tenere in vita un certo numero di repliche dei singoli Pod in base alle nostre configurazioni. Questo permetterà di scalare la capacità di determinate funzionalità dell'applicazione che stiamo eseguendo. La componente che si occupa di ciò è il ReplicaSet i cui servizi vengono però spesso attivati congiuntamente ai Deployment grazie alla parola chiave di configurazione replicas
: proprio questa è la modalità in cui vedremo Kubernetes in azione nella gestione delle repliche.
Repliche di Pod
Partiamo dal Deployment che abbiamo visto nella lezione dedicata e aggiungiamoci la richiesta del numero di repliche dei Pod che desideriamo per fare in modo che tale funzionalità sia ridondata. Questo è il nostro file della configurazione che chiameremo repliche.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nostro-server
labels:
server: web
spec:
replicas: 3
selector:
matchLabels:
server: web
template:
metadata:
labels:
server: web
spec:
containers:
- name: server-web
image: nginx
In aggiunta al codice della lezione sui Deployment, abbiamo inserito una sola riga, replicas: 3
, la quale specifica che del server NGINX non vogliamo un solo Pod bensì tre. L'aspetto più significativo è che Kubernetes si impegnerà a mantenere sempre tre repliche, qualunque cosa accada. Attiviamo la componente e osserviamo il suo stato:
$ kubectl apply -f repliche.yaml
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nostro-server 3/3 3 3 38s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nostro-server-6569f9989c-8wfbd 1/1 Running 0 60s
nostro-server-6569f9989c-gtj7n 1/1 Running 0 60s
nostro-server-6569f9989c-n58tj 1/1 Running 0 60s
Osservando l'output ricevuto notiamo che il nostro Deployment è partito ed ha attivato esattamente tre repliche. Esiste anche un'ulteriore componente, un ReplicaSet, individuabile così:
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nostro-server-6569f9989c 3 3 3 2m27s
Notiamo che il codice di questo ReplicaSet (6569f9989c
), specializzato esplicitamente nel mantenere le repliche al numero desiderato, è lo stesso che si trova nei nomi dei Pod. Ognuno di questi ultimi, tra l'altro, sarà collegato in maniera dinamica al ReplicaSet grazie ad una speciale label che gli viene assegnata in automatico e che possiamo scoprire così:
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nostro-server-6569f9989c-8wfbd 1/1 Running 0 4m58s pod-template-hash=6569f9989c,server=web
nostro-server-6569f9989c-gtj7n 1/1 Running 0 4m58s pod-template-hash=6569f9989c,server=web
nostro-server-6569f9989c-n58tj 1/1 Running 0 4m58s pod-template-hash=6569f9989c,server=web
L'etichetta pod-template-hash=6569f9989c
riporterà ancora quel codice onnipresente che costituirà il collante tra tutte le componenti: Pod, ReplicaSet e Deployment.
Gestione delle repliche
Vediamo ora quanto Kubernetes sarà bravo a conservare le repliche. Proviamo a distruggere una di esse:
$ kubectl delete pods/nostro-server-6569f9989c-8wfbd
pod "nostro-server-6569f9989c-8wfbd" deleted
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nostro-server-6569f9989c-gtj7n 1/1 Running 0 7m41s
nostro-server-6569f9989c-n58tj 1/1 Running 0 7m41s
nostro-server-6569f9989c-xjj54 1/1 Running 0 7s
Abbiamo cancellato un Pod forzatamente ma, come si vede più in basso, questi sono ancora tre. Eppure dei tre Pod due esistono da 7 minuti e 41 secondi, un altro solo da 7 secondi: il motivo è che noi abbiamo cancellato un Pod e Kubernetes l'ha ricostruito per conservare le tre repliche. Tutto questo viene riportato nella storia che il ReplicaSet conserva:
$ kubectl describe rs/nostro-server-6569f9989c
...
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 9m59s replicaset-controller Created pod: nostro-server-6569f9989c-8wfbd
Normal SuccessfulCreate 9m59s replicaset-controller Created pod: nostro-server-6569f9989c-n58tj
Normal SuccessfulCreate 9m59s replicaset-controller Created pod: nostro-server-6569f9989c-gtj7n
Normal SuccessfulCreate 2m25s replicaset-controller Created pod: nostro-server-6569f9989c-xjj54
Alla fine dell'output del suo describe
, esiste una sezione Events
in cui è registrata la creazione dei primi tre Pod e la ricostruzione del quarto che sostituisce quello distrutto da noi: la distruzione non è contemplata semplicemente perché non è un evento indotto da Kubernetes ma è stata opera nostra.
E se aggiungessimo una replica? Stessa cosa. Creando un Pod con le stesse etichette del gruppo di repliche, Kubernetes se ne accorge e lo cancella subito. Infatti nell'output sottostante non ne troviamo traccia ma rinveniamo un evento di cancellazione di un Pod nei log di describe rs
:
$ kubectl run server-web --image=nginx --labels pod-template-hash=6569f9989c,server=web
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nostro-server-6569f9989c-gtj7n 1/1 Running 0 18m
nostro-server-6569f9989c-n58tj 1/1 Running 0 18m
nostro-server-6569f9989c-xjj54 1/1 Running 0 10m
$ kubectl describe rs nostro-server-6569f9989c
...
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 18m replicaset-controller Created pod: nostro-server-6569f9989c-8wfbd
Normal SuccessfulCreate 18m replicaset-controller Created pod: nostro-server-6569f9989c-n58tj
Normal SuccessfulCreate 18m replicaset-controller Created pod: nostro-server-6569f9989c-gtj7n
Normal SuccessfulCreate 11m replicaset-controller Created pod: nostro-server-6569f9989c-xjj54
Normal SuccessfulDelete 73s replicaset-controller Deleted pod: server-web
Poniamo molta attenzione su questa capacità che rappresenta una pietra miliare del funzionamento di Kubernetes!