Home/Kubernetes
Laboratorio · Manuale di Kubernetes

Kubernetes

Il timoniere della flotta digitale.

28 esercizi6 Parti4 appendici
Il codice colore indica il livello:FondamentaleIntermedioAvanzatoCloud Architect
scarica gli esercizi
git clone --filter=blob:none --sparse https://github.com/calmict/book_labs.git
cd book_labs
git sparse-checkout set kubernetes/ed1
calm@calmict:~$ cat kubernetes/argomenti
Parte 1

Le fondamenta Linux

  • 01Un container è solo un processo (verificalo con i tuoi occhi)Fondamentale
  • 02Un container a mano, senza DockerFondamentale
  • 03Limitare CPU e RAM a manoFondamentale
  • 04Smonta un'immagine a mano (anatomia di un container)Fondamentale
  • 05Risali la catena dei runtime (e lancia un container con il solo runc)Fondamentale
  • 06Collega due network namespace a mano (veth, bridge e un ping)Fondamentale
Parte 2

Architettura del Control Plane

  • 07Il primo contatto: uccidi un Pod e guarda chi lo resuscitaFondamentale
  • 08Uccidi il leader: quorum ed elezioni in etcdFondamentale
  • 09Bussa alle quattro porte (l'API server a mani nude)Fondamentale
  • 10Scrivi il tuo controller in venti righe (e scopri perché ne serve uno solo)Fondamentale
  • 11Guida lo scheduler (e poi scavalcalo)Fondamentale
  • 12Il medico di bordo: probe, riavvii e il pod che resuscita da soloFondamentale
Parte 3

Gli oggetti core

  • 13L'indagine: chi ha toccato il mio Pod?Intermedio
  • 14Il condominio Pod: due coinquilini, un portiere invisibileIntermedio
  • 15Il rilascio, il disastro e il ritorno (rollout e rollback)Intermedio
  • 16L'anagrafe: nomi, ordine e dischi che sopravvivonoIntermedio
  • 17I tre mestieri: uno per nodo, fino in fondo, a orarioIntermedio
Parte 4

Rete e storage

  • 18L'indirizzo che non esiste (Service e kube-proxy)Intermedio
  • 19Il portone e il portiere (Ingress e Ingress Controller)Intermedio
  • 20Il matrimonio combinato (PV, PVC, StorageClass)Intermedio
Parte 5

Sicurezza

  • 21La stagista e il robot (autenticazione e RBAC)Avanzato
  • 22La cassaforte e il corridoio (NetworkPolicy e zero-trust)Avanzato
  • 23Il re di cartone (sicurezza del container)Avanzato
Parte 6

Ecosistema e produzione

  • 24Lo stampo e le colate (Helm, il package manager)Cloud Architect
  • 25Il lettore dei contatori (Prometheus e Grafana)Cloud Architect
  • 26Il libro mastro e il revisore (ArgoCD e GitOps)Cloud Architect
  • 27La scorta (Istio e il service mesh)Cloud Architect
  • 28Il passaporto del portiere (Ingress-Nginx e Cert-Manager)Cloud Architect
calm@calmict:~$ ls kubernetes/esercizi/
01Un container è solo un processo (verificalo con i tuoi occhi)Fondamentale

Cosa costruisci

> Esercizio del Capitolo 1 — Il problema che i container risolvono del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • distinguere cosa isola davvero un container rispetto a una macchina virtuale;
  • osservare un processo "containerizzato" contemporaneamente dall'host e dall'interno del container, per toccare con mano che si tratta dello stesso processo Linux visto da due angolazioni diverse;
  • collegare l'osservazione pratica al concetto teorico del capitolo: isolamento di processi vs virtualizzazione dell'hardware.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap01/solution
./run.sh

Esito atteso

  • [ ] Hai il PID del processo così come appare sull'host e così come appare dentro il container, e sono numeri diversi.
  • [ ] Il file answers.md contiene una spiegazione (anche breve, 4-6 righe) del perché lo stesso processo ha due PID diversi, collegandola al concetto di "processo Linux visto attraverso una finestra diversa" piuttosto che "macchina separata".
  • [ ] Hai verificato che l'hostname visto da dentro il container è diverso da quello dell'host.
  • [ ] Il container di laboratorio è stato rimosso a fine esercizio.
02Un container a mano, senza DockerFondamentale

Cosa costruisci

> Esercizio del Capitolo 2 — Linux Namespaces: l'arte dell'illusione del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • costruire un "container" funzionante usando solo strumenti Linux di base (unshare, chroot), senza alcun container runtime;
  • riconoscere i namespace come il vero ingrediente dell'illusione: PID 1, hostname privato, rete isolata;
  • leggere e confrontare i file di /proc/[pid]/ns per dimostrare, inode alla mano, che due processi vivono in namespace diversi.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap02/solution
./run.sh

Esito atteso

  • [ ] Dentro il container ps aux mostra la tua shell come PID 1 e un elenco processi quasi vuoto.
  • [ ] L'hostname dentro è "container-a-mano" e quello dell'host è rimasto intatto.
  • [ ] Hai il confronto degli inode di /proc/[pid]/ns: pid, uts e net diversi tra container e host. E hai notato il caso di user: uguale nella variante sudo (non l'abbiamo isolato), diverso nella variante rootless (è il namespace che rende possibili tutti gli altri senza root).
  • [ ] Il file answers.md risponde alle tre domande del passo 6.
  • [ ] La cartella di laboratorio è stata rimossa.
03Limitare CPU e RAM a manoFondamentale

Cosa costruisci

> Esercizio del Capitolo 3 — Cgroups: il contabile delle risorse del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • creare un cgroup v2 a mano e leggerne/scriverne i file di controllo, senza alcun runtime;
  • mettere in gabbia un processo in esecuzione e osservare i due destini opposti: la CPU che viene rallentata (throttling) e la memoria che uccide (OOM kill);
  • collegare cpu.max e memory.max a ciò che Kubernetes chiama requests/limits, e capire da dove nasce lo stato OOMKilled.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap03/solution
./run.sh

Esito atteso

  • [ ] Hai visto lo stesso loop prima vicino al 100% di un core e poi inchiodato al 20%, con nr_throttled in crescita in cpu.stat.
  • [ ] Il processo goloso è stato ucciso (Killed / exit 137) e memory.events registra oom_kill 1, con memory.peak fermo poco sopra i 64M.
  • [ ] Il file answers.md risponde alle tre domande del passo 6.
  • [ ] La gabbia è stata rimossa con rmdir e non restano processi di laboratorio in giro.
04Smonta un'immagine a mano (anatomia di un container)Fondamentale

Cosa costruisci

> Esercizio del Capitolo 4 — Anatomia di un container del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • aprire un'immagine OCI e riconoscerne i tre ingredienti: manifest, config e layer (che sono semplici tarball di filesystem);
  • montare un OverlayFS a mano e osservare il copy-on-write: dove finiscono le modifiche, come muore un file (whiteout), perché il layer di un container è usa-e-getta;
  • dimostrare che root nel container non è root sull'host (capabilities) e che il kernel è uno solo, condiviso.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap04/solution
./run.sh

Esito atteso

  • [ ] Hai individuato nel manifest il percorso della config e quello del layer, e dentro il layer estratto c'è un filesystem radice completo.
  • [ ] La modifica del passo 4 esiste solo in upper, la cancellazione ha prodotto un whiteout, e il layer originale è rimasto intatto.
  • [ ] Hai le due maschere CapEff (diverse) e il fallimento di date -s nel container.
  • [ ] uname -r dentro e fuori coincidono, e answers.md risponde alle tre domande.
  • [ ] Overlay smontato e cartella di laboratorio rimossa.
05Risali la catena dei runtime (e lancia un container con il solo runc)Fondamentale

Cosa costruisci

> Esercizio del Capitolo 5 — La guerra dei runtime: Docker, containerd, CRI-O del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • risalire la catena reale dei processi di un container in esecuzione e scoprire chi c'è davvero (e chi NON c'è) tra lui e init;
  • interrogare containerd direttamente, scavalcando Docker, per toccare con mano che il comando docker è solo un client;
  • leggere un bundle OCI (il config.json che containerd prepara per runc) e riconoscervi namespaces, cgroups e capabilities dei capitoli 2-4;
  • avviare un container con il solo runc: niente demoni, niente API, solo la spec e un rootfs.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap05/solution
./run.sh

Esito atteso

  • [ ] Hai la catena dei padri annotata: processo → containerd-shim → PID 1, con dockerd e containerd vivi ma fuori dalla catena.
  • [ ] Hai visto il tuo container elencato da ctr nel namespace moby, senza passare da docker.
  • [ ] Nel config.json hai individuato le sezioni namespaces, resources (cgroup) e capabilities.
  • [ ] Il container lanciato con runc run è partito, ci sei entrato (PID 1) e l'hai chiuso con exit.
  • [ ] answers.md risponde alle tre domande e il laboratorio è smontato.
06Collega due network namespace a mano (veth, bridge e un ping)Fondamentale

Cosa costruisci

> Esercizio del Capitolo 6 — Networking Linux dalle fondamenta del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • creare network namespace, cavi virtuali (veth) e uno switch virtuale (bridge), e cablarli come farebbe un container runtime;
  • seguire un ping che attraversa il tuo switch e leggerne le prove (tabella ARP, inoltro del bridge);
  • riconoscere in docker0 lo stesso identico schema che hai appena costruito a mano.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap06/solution
./run.sh

Esito atteso

  • [ ] Il ping da blue a red risponde attraverso il bridge.
  • [ ] ip neigh dentro blue mostra il MAC di red, e la fdb di br-lab mostra su quali porte ha imparato gli indirizzi.
  • [ ] Hai riconosciuto lo schema bridge+veth in docker0 (o hai fatto tutto nella variante rootless).
  • [ ] answers.md risponde alle tre domande.
  • [ ] Namespace e bridge rimossi, nessuna interfaccia veth orfana (ip link | grep veth non mostra le tue).
07Il primo contatto: uccidi un Pod e guarda chi lo resuscitaFondamentale

Cosa costruisci

> Esercizio del Capitolo 7 — Visione d'insieme dell'architettura del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • avviare un cluster locale e riconoscere a vista i componenti del control plane (il cervello) e cosa gira sui worker (le braccia);
  • toccare con mano il modello dichiarativo: tu dichiari lo stato desiderato, il reconciliation loop lo insegue — anche contro i tuoi sabotaggi;
  • leggere un oggetto Kubernetes come lo vede l'API: spec (desiderato) contro status (osservato), e scoprire che davvero tutto è una risorsa.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap07/solution
./run.sh

Esito atteso

  • [ ] kubectl get nodes risponde e hai identificato i 4 componenti del cervello in kube-system.
  • [ ] Hai visto nel watch il Pod cancellato e il sostituto nascere con un altro nome, senza alcun tuo intervento.
  • [ ] Sai indicare nel YAML del Deployment dove sta il desiderio (spec) e dove la realtà (status).
  • [ ] answers.md risponde alle tre domande.
  • [ ] Il Deployment di laboratorio è stato rimosso.
08Uccidi il leader: quorum ed elezioni in etcdFondamentale

Cosa costruisci

> Esercizio del Capitolo 8 — Etcd e il consenso distribuito del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • avviare un cluster con 3 control-plane e interrogare i 3 membri etcd che ne custodiscono la memoria;
  • vedere che ogni oggetto Kubernetes è letteralmente una chiave dentro etcd (/registry/...);
  • assassinare il leader e assistere all'elezione del successore, col cluster che non perde un colpo;
  • rompere il quorum e toccare con mano cosa significa "il cluster è congelato" — e poi riportarlo in vita.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap08/solution
./run.sh

Esito atteso

  • [ ] Hai visto 3 membri etcd con un solo IS LEADER=true e annotato chi era.
  • [ ] Hai trovato il namespace raft-lab come chiave /registry/... dentro etcd.
  • [ ] Dopo la pausa del leader hai visto un nuovo leader e kubectl ancora funzionante.
  • [ ] Con 2 nodi congelati hai ottenuto l'errore da quorum perso, e dopo l'unpause il cluster è tornato integro con raft-lab al suo posto.
  • [ ] answers.md risponde alle tre domande e il cluster book-labs-ha è stato cancellato.
09Bussa alle quattro porte (l'API server a mani nude)Fondamentale

Cosa costruisci

> Esercizio del Capitolo 9 — API Server: l'unico punto di verità del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • parlare con l'API server senza kubectl, con un semplice curl, e riconoscere gruppi, versioni e risorse dell'API REST;
  • attraversare consapevolmente le porte di una richiesta: respinto all'autenticazione (401), respinto all'autorizzazione (403), respinto dall'admission (quota) e infine accolto;
  • usare un watch per vedere in streaming gli eventi con cui il cluster resta sincronizzato.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap09/solution
./run.sh

Esito atteso

  • [ ] Hai esplorato /api e /apis via curl e riconosciuto gruppi e versioni.
  • [ ] Hai collezionato la sequenza completa: respinto da anonimo → 200 coi certificati → Forbidden impersonando → exceeded quota.
  • [ ] Hai visto nello stream del watch gli eventi ADDED e DELETED di watch-lab.
  • [ ] answers.md risponde alle tre domande.
  • [ ] Namespace quota-lab rimosso, certificati estratti cancellati, proxy chiuso.
10Scrivi il tuo controller in venti righe (e scopri perché ne serve uno solo)Fondamentale

Cosa costruisci

> Esercizio del Capitolo 10 — Controller Manager e il reconciliation loop del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • riconoscere il battito del cuore dei controller veri: le Lease della leader election in kube-system;
  • scrivere in prima persona un controller funzionante (observe–diff–act in venti righe di shell) e vederlo riparare i tuoi sabotaggi;
  • scoprirne i due difetti strutturali — il polling e il duello tra copie — e capire perché client-go risponde con informer e leader election.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap10/solution
./run.sh

Esito atteso

  • [ ] Hai visto il renewTime della lease del controller-manager avanzare.
  • [ ] Il tuo minictl.sh ricrea il pod cancellato senza intervento umano e pota gli eccessi.
  • [ ] Hai provocato e descritto il duello tra due copie.
  • [ ] answers.md risponde alle tre domande.
  • [ ] Nessun pod app=minictl residuo e script fermati.
11Guida lo scheduler (e poi scavalcalo)Fondamentale

Cosa costruisci

> Esercizio del Capitolo 11 — Lo Scheduler del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • dimostrare cosa fa davvero lo scheduler (sceglie e scrive il nodo) e cosa non fa — al punto da scavalcarlo del tutto con un Pod che non lo incontra mai;
  • vedere il filtering in azione: un Pod respinto da tutti i nodi resta Pending, e il motivo è scritto negli eventi;
  • guidare le scelte con nodeSelector e anti-affinity, e capire i taint come respingimento (con la toleration che riapre la porta).

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap11/solution
./run.sh

Esito atteso

  • [ ] Hai l'evento Scheduled firmato default-scheduler per witness, e la sua assenza per bypass.
  • [ ] Hai visto picky Pending con il motivo del filtro, e poi Running sul nodo etichettato.
  • [ ] Le 2 repliche spread stanno su worker diversi, e la terza è passata da Pending al control-plane grazie alla toleration.
  • [ ] answers.md risponde alle tre domande.
  • [ ] Il cluster book-labs-sched è stato cancellato.
12Il medico di bordo: probe, riavvii e il pod che resuscita da soloFondamentale

Cosa costruisci

> Esercizio del Capitolo 12 — I componenti del nodo Worker del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • vedere il kubelet fare il medico: una liveness probe che fallisce e il container riavviato, con il conto dei riavvii e il back-off che cresce;
  • distinguere i due destini: liveness (riavvio) contro readiness (fuori dal giro del traffico, senza riavvio) — osservando gli endpoint di un Service svuotarsi e ripopolarsi;
  • dimostrare che il kubelet non ha bisogno di nessuno: uno static pod creato mettendo un file sul nodo, che risorge perfino se lo cancelli dall'API.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap12/solution
./run.sh

Esito atteso

  • [ ] RESTARTS di liar è salito almeno due volte e negli eventi hai Unhealthy, Killing e il Back-off.
  • [ ] Gli endpoint di moody si sono svuotati e ripopolati senza alcun riavvio del pod.
  • [ ] hello-static è comparso senza apply, è risorto dopo il delete, ed è sparito rimuovendo il file dal nodo.
  • [ ] answers.md risponde alle tre domande.
  • [ ] Pod e Service di laboratorio rimossi.
13L'indagine: chi ha toccato il mio Pod?Intermedio

Cosa costruisci

> Esercizio del Capitolo 13 — La vita di un Pod: da kubectl apply al container attivo del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • ricostruire l'intera staffetta di un kubectl apply dalle prove: quattro firme diverse sugli eventi (deployment-controller, replicaset-controller, default-scheduler, kubelet);
  • seguire la catena di proprietà Deployment → ReplicaSet → Pod scritta negli ownerReferences, e scendere sotto l'API fino al processo Linux — ritrovando namespace e cgroup delle Fasi 1-2;
  • distinguere le due guarigioni: il kubelet che riavvia un container morto (stesso Pod, RESTARTS che sale) e il controller che rimpiazza un Pod cancellato (nome nuovo).

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap13/solution
./run.sh

Esito atteso

  • [ ] Hai la timeline con le quattro firme e l'ordine logico ricostruito.
  • [ ] Hai la catena Pod → ReplicaSet → Deployment letta dagli ownerReferences.
  • [ ] Hai trovato il PID sul nodo e il suo cgroup kubepods con la QoS class nel percorso.
  • [ ] Hai osservato entrambe le guarigioni: RESTARTS a 1 dopo il kill -9, nome nuovo dopo il delete.
  • [ ] answers.md risponde alle tre domande e il Deployment è stato rimosso.
14Il condominio Pod: due coinquilini, un portiere invisibileIntermedio

Cosa costruisci

> Esercizio del Capitolo 14 — Il Pod in profondità del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • dimostrare perché l'unità è il Pod e non il container: due container che si parlano via localhost e si passano file su un volume condiviso;
  • smascherare il pause container: prima dagli inode dei namespace sul nodo, poi — rendendo il condominio "di vetro" — vedendolo comparire come PID 1 dentro il Pod;
  • osservare un init container fare il portiere (la fase Init:0/1 dal vivo) e leggere la classe QoS di tre Pod dalle loro resources — ritrovandola nella gerarchia cgroup del cap. 3.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap14/solution
./run.sh

Esito atteso

  • [ ] Il wget dal writer restituisce la data scritta dall'altro container (localhost + volume condivisi).
  • [ ] Hai gli inode: net identico tra i due container, pid diversi, e hai trovato il processo /pause sul nodo.
  • [ ] In condo-glass hai visto /pause come PID 1 da dentro il Pod.
  • [ ] Hai osservato la fase Init:0/1 e i tre verdetti QoS (BestEffort, Burstable, Guaranteed).
  • [ ] answers.md risponde alle tre domande e i sei Pod sono stati rimossi.
15Il rilascio, il disastro e il ritorno (rollout e rollback)Intermedio

Cosa costruisci

> Esercizio del Capitolo 15 — ReplicaSet e Deployment del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • leggere la divisione dei compiti: il ReplicaSet guardiano del numero, il Deployment orchestratore dei ReplicaSet — e i vecchi ReplicaSet a zero repliche come memoria storica;
  • eseguire un rolling update senza downtime e osservarlo pod per pod (maxSurge 1, maxUnavailable 0);
  • sopravvivere a un rilascio rotto: il rollout si blocca ma il servizio resta su, e kubectl rollout undo riporta indietro in un istante — capendo che non è magia, è ancora il reconciliation loop.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap15/solution
./run.sh

Esito atteso

  • [ ] Hai visto il rolling update pod per pod, mai sotto 3 attivi.
  • [ ] Dopo il rilascio hai due ReplicaSet (3 e 0) e la history con le change-cause.
  • [ ] Nel disastro: rollout bloccato in ImagePullBackOff ma i 3 pod della versione precedente Running.
  • [ ] Dopo l'undo l'immagine è tornata alpine:3.20 e la revisione è rinata con numero nuovo.
  • [ ] answers.md risponde alle tre domande e il Deployment è stato rimosso.
16L'anagrafe: nomi, ordine e dischi che sopravvivonoIntermedio

Cosa costruisci

> Esercizio del Capitolo 16 — StatefulSet e la gestione dello stato del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • toccare la differenza tra Pod fungibili e Pod con identità: la folla rinasce con nomi casuali, diary-1 rinasce diary-1;
  • osservare l'ordinamento rigoroso (0 → 1 → 2 in salita, inverso in discesa) e il DNS prevedibile via headless Service;
  • dimostrare che con volumeClaimTemplates ogni replica ha il SUO disco, e che il disco sopravvive al Pod — e perfino alla cancellazione dell'intero StatefulSet.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap16/solution
./run.sh

Esito atteso

  • [ ] Hai il confronto dei nomi: casuali nella folla, diary-N nell'anagrafe, con la nascita in ordine 0→1→2.
  • [ ] diary-1 è rinato come diary-1 e il suo diario aveva la riga della vita precedente.
  • [ ] Hai visto i 3 PVC personali, ancora vivi dopo la cancellazione dello StatefulSet, e il diario completo dopo la ricreazione.
  • [ ] La nslookup del nome stabile risolve dall'interno.
  • [ ] answers.md risponde alle tre domande e la pulizia include i PVC.
17I tre mestieri: uno per nodo, fino in fondo, a orarioIntermedio

Cosa costruisci

> Esercizio del Capitolo 17 — DaemonSet, Job e CronJob del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • leggere il DaemonSet come contratto geografico: nessun campo replicas — il numero lo decide il cluster, un guardiano per nodo (e la toleration del cap. 11 per coprire anche il control-plane);
  • incontrare il primo oggetto che vuole finire: il Job, con la differenza tra riavviare un container e riprovare un Pod (backoffLimit), e il fallimento onesto di un Job che non ce la fa;
  • vedere un CronJob timbrare il cartellino: la catena CronJob → Job → Pod, un minuto dopo l'apply.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap17/solution
./run.sh

Esito atteso

  • [ ] watchman: 2 guardiani prima della toleration, 3 dopo, e la rinascita sullo stesso nodo.
  • [ ] countdown Completed con i log della conta; flaky Failed con BackoffLimitExceeded dopo 3 pod.
  • [ ] Il primo timbro del CronJob: un Job tick-<timestamp> coi log della data.
  • [ ] answers.md risponde alle tre domande (tabella dei mestieri inclusa).
  • [ ] Il cluster book-labs-crew è stato cancellato.
18L'indirizzo che non esiste (Service e kube-proxy)Intermedio

Cosa costruisci

> Esercizio del Capitolo 18 — I Servizi e la magia di kube-proxy del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • toccare il problema che i Service risolvono: Pod effimeri, IP che cambiano a ogni rinascita;
  • usare un ClusterIP stabile e bilanciato — e poi smascherarlo: non esiste su nessuna interfaccia, è un trucco di iptables (DNAT più una moneta di netfilter, il cap. 6 in grande stile);
  • seguire la catena che tiene aggiornata la lista: EndpointSlice che si accorge di ogni nascita e morte, e CoreDNS che dà al tutto l'unico nome davvero stabile.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap18/solution
./run.sh

Esito atteso

  • [ ] Hai provato sulla tua pelle la morte del numero diretto (IP del pod cambiato dopo la rinascita).
  • [ ] Il centralino risponde con entrambe le voci (bilanciamento visto con wget ripetuti).
  • [ ] Hai la prova che il ClusterIP non esiste su nessuna interfaccia, e le regole KUBE-SVC/KUBE-SEP con probability e DNAT.
  • [ ] Hai visto gli EndpointSlice inseguire lo scale, e il DNS risolvere il nome sul ClusterIP.
  • [ ] answers.md risponde alle tre domande e il laboratorio è smontato.
19Il portone e il portiere (Ingress e Ingress Controller)Intermedio

Cosa costruisci

> Esercizio del Capitolo 19 — Ingress e Ingress Controller del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • capire perché i Service (L4) non bastano: l'Ingress legge ciò che loro non vedono — host e path;
  • toccare la separazione dei ruoli con un esperimento: le regole Ingress applicate SENZA controller non fanno nulla — l'oggetto è la richiesta scritta, il controller è chi la esegue;
  • installare ingress-nginx su kind e vedere il routing L7 dal vivo: due host sullo stesso IP e porta, ognuno alla sua app, e il default backend per gli sconosciuti.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap19/solution
./run.sh

Esito atteso

  • [ ] Con le regole applicate ma senza controller: curl rifiutato e ADDRESS vuota.
  • [ ] Dopo l'installazione: uno.labs.local → app-uno, due.labs.local → app-due, host ignoto → 404.
  • [ ] Hai riconosciuto le tue richieste nei log del controller.
  • [ ] answers.md risponde alle tre domande.
  • [ ] Il cluster book-labs-ingress è stato cancellato.
20Il matrimonio combinato (PV, PVC, StorageClass)Intermedio

Cosa costruisci

> Esercizio del Capitolo 20 — Storage: PV, PVC, StorageClass e CSI del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • combinare un matrimonio statico: un PV creato a mano, un PVC che lo chiede, il binding 1:1 — e la zitella che resta Pending quando i PV finiscono;
  • scatenare il provisioning dinamico: un PVC con la StorageClass e un PV che nasce dal nulla, firmato dal provisioner;
  • leggere le reclaim policy nei fatti: il PV dinamico che muore col suo claim (Delete) e quello manuale che resta vedovo ma custodisce la dote (Retain, stato Released).

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap20/solution
./run.sh

Esito atteso

  • [ ] bride Bound a manual-pv, writer Running, spinster Pending per sempre.
  • [ ] cloud Bound a un PV pvc-<uid> nato dal provisioner, con RECLAIM POLICY Delete contro il Retain del manuale.
  • [ ] Dopo la strage dei claim: PV dinamico sparito, manual-pv Released, e la dote ancora leggibile sul nodo.
  • [ ] answers.md risponde alle tre domande.
  • [ ] PV Released e cartella sul nodo rimossi a mano.
21La stagista e il robot (autenticazione e RBAC)Avanzato

Cosa costruisci

> Esercizio del Capitolo 21 — Autenticazione e RBAC del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • assumere un utente vero: chiave privata, CertificateSigningRequest firmata dalla CA del cluster, kubeconfig dedicato — e scoprire che gli utenti umani non sono oggetti dell'API: esistono solo nei certificati (CN = nome, O = gruppi);
  • applicare il minimo privilegio con Role e RoleBinding, verificandone i confini: la stagista legge i pod di default e nient'altro — non li crea, non vede i secret, non esce dal namespace;
  • dare un'identità a un Pod (ServiceAccount) e usarla dall'interno: il token montato, la chiamata all'API dal container, il 403 che diventa 200 con il binding giusto.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap21/solution
./run.sh

Esito atteso

  • [ ] La CSR è stata approvata e whoami riconosce la stagista (gruppo tirocinanti) dal suo kubeconfig.
  • [ ] Prima del Role: Forbidden su tutto; dopo: get pods sì, create/secrets/kube-system ancora Forbidden.
  • [ ] Il robot ha preso il 403 senza binding e la PodList col binding, usando il token montato.
  • [ ] answers.md risponde alle tre domande.
  • [ ] CSR, oggetti RBAC, robot e file locali rimossi.
22La cassaforte e il corridoio (NetworkPolicy e zero-trust)Avanzato

Cosa costruisci

> Esercizio del Capitolo 22 — NetworkPolicy e l'approccio zero-trust del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • toccare il problema del default allow: nel condominio Kubernetes ogni pod raggiunge ogni pod, cassaforte inclusa;
  • invertire la regola con un default deny di tre righe, e poi riaprire SOLO la porta giusta: label come regole firewall, porte come contratto;
  • chiudere anche l'uscita (egress): la cassaforte che riceve ma non telefona — e scoprire chi realizza davvero le policy (il CNI), con il test di enforcement come abitudine igienica.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap22/solution
./run.sh

Esito atteso

  • [ ] Prima delle policy: gioielli per tutti (default allow toccato con mano).
  • [ ] Col deny-all: timeout per tutti — e il test di enforcement superato.
  • [ ] Con allow-app: app dentro, guest fuori; con no-exfiltration: la cassaforte non chiama.
  • [ ] answers.md risponde alle tre domande.
  • [ ] Il namespace vault è stato cancellato.
23Il re di cartone (sicurezza del container)Avanzato

Cosa costruisci

> Esercizio del Capitolo 23 — Sicurezza del container del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • toccare con mano perché root dentro un container è un re di cartone: uid 0 sì, ma il potere reale sta nelle capabilities, nei privilegi e nel filesystem — e nel kernel condiviso con l'host;
  • blindare un pod col SecurityContext: utente non-root, niente escalation, filesystem in sola lettura, tutte le capabilities cadute, seccomp attivo — e verificare ogni difesa dall'interno;
  • passare dalla difesa pod-per-pod alla difesa su scala con i Pod Security Standards: un'etichetta sul namespace e l'admission rifiuta i pod non conformi prima ancora che nascano.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap23/solution
./run.sh

Esito atteso

  • [ ] Il re nudo: uid 0, CapEff a80425fb, Seccomp 0, radice scrivibile — visto con i tuoi occhi.
  • [ ] Il re spogliato: uid non-root, CapEff a zero, Seccomp 2, scrittura rifiutata.
  • [ ] Sotto restricted: l'intruso root rifiutato in admission, il pod blindato ammesso.
  • [ ] answers.md risponde alle tre domande.
  • [ ] Il namespace throne è stato cancellato.
24Lo stampo e le colate (Helm, il package manager)Cloud Architect

Cosa costruisci

> Esercizio del Capitolo 24 — Helm, il package manager di Kubernetes del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • sentire il problema che Helm risolve: gestire a mano decine di manifest quasi identici, che cambiano per due righe — il crampo del copia-incolla;
  • costruire un chart locale: uno stampo (i template) più una scheda di regolazioni (values), e vedere lo stesso stampo colare manifest diversi al variare dei valori;
  • gestire le release come colate numerate: installare, aggiornare con nuovi valori, leggere la storia e tornare indietro con un rollback — e capire perché un cambio di sola configurazione non fa ripartire i pod.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap24/solution
./run.sh

Esito atteso

  • [ ] I template completati: helm lint pulito e helm template rende manifest con i tuoi valori.
  • [ ] Revisione 1 installata: una replica, "revision one" servito.
  • [ ] Revisione 2 dopo l'upgrade: tre repliche e "revision two" (i pod sono ripartiti).
  • [ ] Rollback: la storia ha tre righe e la ConfigMap è tornata a "revision one".
  • [ ] answers.md risponde alle tre domande; release e namespace rimossi.
25Il lettore dei contatori (Prometheus e Grafana)Cloud Architect

Cosa costruisci

> Esercizio del Capitolo 25 — Prometheus e Grafana: gli occhi sul cluster del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • capire il modello pull: Prometheus non aspetta che gli mandino i dati, va lui a bussare alla porta /metrics di ogni bersaglio, come un lettore dei contatori che passa di casa in casa;
  • montare i contatori (node-exporter), scrivere il giro del lettore (lo scrape config) e verificare con la metrica up che a ogni porta abbia risposto qualcuno;
  • interrogare il registro delle letture con PromQL via l'API di Prometheus, capire cosa distingue un gauge da un counter (e perché serve rate), e riconoscere che un alert è solo una query che supera una soglia — e dove entra Grafana.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap25/solution
./run.sh

Esito atteso

  • [ ] Vista la faccia del contatore: le metriche di node-exporter in chiaro su HTTP.
  • [ ] Completato il giro: up vale 1 sia per prometheus sia per node.
  • [ ] Interrogato il registro: count(up==1), un gauge di nodo e un rate su counter.
  • [ ] answers.md risponde alle tre domande.
  • [ ] Il namespace monitoring è stato cancellato.
26Il libro mastro e il revisore (ArgoCD e GitOps)Cloud Architect

Cosa costruisci

> Esercizio del Capitolo 26 — ArgoCD e il GitOps del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • capire il principio GitOps: Git è il libro mastro, l'unica fonte di verità su cosa deve esistere nel cluster; nessuno tocca il mondo a mano, si scrive nel libro;
  • dare l'incarico a un revisore instancabile (ArgoCD) con l'oggetto Application, e vederlo rendere il cluster identico al libro (sync), accorgersi di ogni divergenza (drift) e correggerla da solo (self-heal);
  • fare rollback nel modo dichiarativo: non si aggiusta il mondo, si corregge il libro con git revert, e il revisore propaga la correzione.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap26/solution
./run.sh

Esito atteso

  • [ ] ArgoCD installato e il git server (libro mastro) in esecuzione sul cluster dedicato.
  • [ ] Application completata: web Synced e Healthy, 1 replica, creato da ArgoCD.
  • [ ] Drift e self-heal: lo scale manuale a 3 viene annullato, torna a 1.
  • [ ] git revert: il commit sbagliato porta il mondo a 5, il revert lo riporta a 1.
  • [ ] answers.md risponde alle tre domande; il cluster dedicato è stato cancellato.
27La scorta (Istio e il service mesh)Cloud Architect

Cosa costruisci

> Esercizio del Capitolo 27 — Istio e il service mesh del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • capire il problema che risolve un service mesh: cifratura, retry, routing e tracce oggi vivono dentro ogni applicazione, riscritti in ogni linguaggio; il mesh li sfila fuori e li affida a una scorta;
  • vedere la scorta attaccarsi da sola a ogni pod (sidecar injection): il data plane sono tutte le scorte (Envoy), il control plane (istiod) è la centrale che le istruisce;
  • accendere mTLS automatico (identità e cifratura senza toccare l'app né gestire un certificato) e comandare il traffico dall'alto: un canary 80/20 tra due versioni, deciso per decreto.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap27/solution
./run.sh

Esito atteso

  • [ ] Injection: ogni pod del namespace mesh ha due container (app + istio-proxy).
  • [ ] mTLS STRICT: il client di outside è rifiutato, quello interno passa.
  • [ ] Canary: circa 80/20 tra v1 e v2 su una trentina di richieste.
  • [ ] answers.md risponde alle tre domande; il cluster dedicato è stato cancellato.
28Il passaporto del portiere (Ingress-Nginx e Cert-Manager)Cloud Architect

Cosa costruisci

> Esercizio del Capitolo 28 — Ingress-Nginx e Cert-Manager: TLS automatico del > *Manuale di Kubernetes* (collana Calm ICT — [calmict.com](https://calmict.com)).

Obiettivi

  • inquadrare il problema dei certificati TLS: il portiere (Ingress-Nginx del cap. 19) deve provare l'identità del palazzo a ogni visitatore via HTTPS, ma i certificati si generano, si installano e — soprattutto — scadono;
  • montare una fabbrica di passaporti automatica con Cert-Manager: un'autorità (CA), e certificati emessi e rinnovati da soli;
  • ottenere HTTPS end-to-end con una sola annotazione sull'Ingress, e verificare il certificato contro la tua CA — capendo dove, in produzione, entrerebbe Let's Encrypt via ACME.

Come testarlo

Completa i TODO nei file di partenza, poi lancia il test della soluzione:

cd kubernetes/ed1/cap28/solution
./run.sh

Esito atteso

  • [ ] ingress-nginx e cert-manager in esecuzione; la catena issuer pronta (CA Ready).
  • [ ] L'Ingress completato fa emettere a Cert-Manager il Secret shop-tls da solo.
  • [ ] curl HTTPS validato contro la CA locale risponde secure shop; il certificato ha la SAN dell'host.
  • [ ] answers.md risponde alle tre domande; il cluster dedicato è stato cancellato.