Esegui kubectl run nginx --image=nginx:1.27 e Kubernetes crea esattamente un Pod di nome nginx. Cancellalo con kubectl delete pod nginx e sparisce per sempre — nessuno se ne accorge, nessuno lo sostituisce. Un Pod è l’unità minima distribuibile in Kubernetes: uno o più container che condividono un namespace di rete e un insieme di volumi, schedulati insieme su un singolo nodo.

Quel Pod isolato è un vicolo cieco in produzione. Se il container al suo interno crasha, il kubelet lo riavvia sul posto. Se il nodo si riavvia, o qualcuno cancella il Pod, nulla lo ricrea. Di un Pod nudo, nessuno si ricorda che dovrebbe esistere.

Cosa aggiunge un Deployment rispetto a un Pod

Un Deployment è un oggetto Kubernetes che stabilisce quante copie di un Pod devono esistere e come distribuire gli aggiornamenti su di esse. Smetti di gestire i Pod direttamente e descrivi lo stato desiderato: un control loop si occupa di realizzarlo. È lo stesso modello di riconciliazione dietro tutto il resto in Kubernetes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web-app
          image: nginx:1.27
          ports:
            - containerPort: 80
1
2
kubectl apply -f web-app-deployment.yaml
kubectl get pods
1
2
3
4
NAME                       READY   STATUS    RESTARTS   AGE
web-app-7d9f8c7b86-4kxqz   1/1     Running   0          8s
web-app-7d9f8c7b86-9wj2p   1/1     Running   0          8s
web-app-7d9f8c7b86-x2p6t   1/1     Running   0          8s

Tre Pod, non uno, e nessuno si chiama web-app. Quello schema di naming (web-app-7d9f8c7b86-4kxqz) è il primo segnale che qualcos’altro li sta gestendo.

replicas: 3 è la stessa istruzione che dai con docker compose up --scale web=3 in Docker Compose. La differenza è che qui un controller continua a far rispettare quel numero ben oltre l’esecuzione del comando.

Come un Deployment crea davvero i Pod: il ReplicaSet in mezzo

Un Deployment non crea i Pod direttamente. Crea un ReplicaSet, ed è il ReplicaSet a creare i Pod. Puoi vedere l’intera catena:

1
2
3
kubectl get deployment web-app
kubectl get replicaset -l app=web-app
kubectl get pods -l app=web-app
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
web-app   3/3     3            3           2m

NAME                 DESIRED   CURRENT   READY   AGE
web-app-7d9f8c7b86   3         3         3       2m

NAME                       READY   STATUS    RESTARTS   AGE
web-app-7d9f8c7b86-4kxqz   1/1     Running   0          2m
web-app-7d9f8c7b86-9wj2p   1/1     Running   0          2m
web-app-7d9f8c7b86-x2p6t   1/1     Running   0          2m

Il nome del ReplicaSet è il nome del Deployment più un hash del template del Pod (7d9f8c7b86); il nome di ogni Pod è il nome del ReplicaSet più un suffisso casuale. kubectl describe pod web-app-7d9f8c7b86-4kxqz mostra la relazione direttamente, nel campo Controlled By: ReplicaSet/web-app-7d9f8c7b86.

Cancella uno di quei Pod e il conteggio scende a 2. Nel giro di secondi compare un sostituto. È il ReplicaSet che nota il vuoto e crea un nuovo Pod dallo stesso template, non il Deployment che agisce direttamente. Il ReplicaSet fa da guardiano. Il Deployment esiste per l’unica cosa che un ReplicaSet non può fare da solo: sostituire un template di Pod in modo graduale invece che tutto insieme.

Cosa fa un rollout ai ReplicaSet

Cambia l’immagine e applica:

1
2
kubectl set image deployment/web-app web-app=nginx:1.27.1
kubectl rollout status deployment/web-app
1
2
3
Waiting for deployment "web-app" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "web-app" rollout to finish: 2 out of 3 new replicas have been updated...
deployment "web-app" successfully rolled out

Dietro quella riga di stato, il Deployment ha creato un secondo ReplicaSet per il nuovo template di Pod, aumentandone le repliche mentre riduceva quelle del vecchio. Con la strategia predefinita RollingUpdate su 3 repliche, il risultato è un Pod alla volta:

1
kubectl get replicaset -l app=web-app
1
2
3
NAME                 DESIRED   CURRENT   READY   AGE
web-app-7d9f8c7b86   0         0         0       6m
web-app-6b8f6d9c4d   3         3         3       40s

Il vecchio ReplicaSet non viene cancellato. Resta a zero repliche, conservando il precedente template di Pod come riferimento storico. È questo che rende il rollback veloce:

1
kubectl rollout undo deployment/web-app

Kubernetes riporta il vecchio ReplicaSet al numero di repliche originario e azzera il nuovo — nessuna ricostruzione, nessun nuovo pull di un’immagine vecchia se è ancora in cache sul nodo. kubectl rollout history deployment/web-app --revision=1 mostra ancora esattamente quale immagine eseguiva quella revisione.

Quando un Pod nudo è la scelta giusta

Un Pod nudo non è un errore in ogni contesto, solo nella maggior parte:

  1. Un container diagnostico usa e getta che cancellerai tra cinque minuti: kubectl run debug --image=busybox -it --rm -- sh.
  2. Un Job o un CronJob, che crea Pod tramite il proprio controller perché il lavoro deve arrivare a completamento invece di restare attivo.
  3. Ispezionare o studiare la spec del Pod stessa, prima di incapsularla in qualcosa che la gestisca.

Tutto ciò che deve sopravvivere a un crash, a un guasto del nodo o a un aggiornamento passa da un Deployment. Oppure da uno StatefulSet, per i Pod che hanno bisogno di un’identità stabile e di storage proprio — un problema diverso, e un oggetto diverso. Scrivi il manifest del Deployment di default e scendi a un Pod nudo solo nei tre casi sopra.

Pod, ReplicaSet e Deployment a confronto

PodReplicaSetDeployment
Cosa gestisceContainerPodReplicaSet
Sostituisce un’istanza cancellataNoSì, tramite il suo ReplicaSet
Scala a N replicheNo
Rolling updateNoNo
Rollback a una versione precedenteNoNo
Lo crei direttamenteRaramenteQuasi maiNormalmente

Verifica se i tuoi Pod hanno un Deployment dietro

Esegui questo comando su quello che hai già nel cluster:

1
kubectl get deployment,replicaset,pod -l app=<tuo-label>

Se tornano solo righe di Pod, quelli sono Pod nudi. È il vuoto da colmare prima che il prossimo drain di un nodo si porti via l’app con loro.

Articoli correlati