Readiness e liveness probe su Kubernetes: i default pericolosi su un pod PHP-FPM
Valori di default di Kubernetes per i probe, perché causano riavvii in loop su PHP-FPM e come impostarli in YAML, con comando kubectl per verificare lo stato dopo il deploy.
Redazione UptimeMag · 14 ottobre 2026 · 4 minuti di lettura

Un pod PHP-FPM che si riavvia da solo ogni due minuti, senza errori applicativi evidenti, quasi sempre nasconde un probe configurato male. Il sintomo tipico è CrashLoopBackOff nell'output di kubectl get pods, con il container che torna su, prova a rispondere, fallisce il controllo di salute e viene ucciso di nuovo. Il colpevole, nella maggior parte dei casi, sono i valori di default dei probe lasciati così come sono, mai pensati per un pool PHP-FPM che deve caricare l'opcache o aprire connessioni al database prima di poter rispondere.
I default di Kubernetes
Secondo la documentazione ufficiale di Kubernetes, i campi di configurazione dei probe hanno questi valori quando non vengono specificati: initialDelaySeconds è di 0 secondi di default, mentre per periodSeconds il default è 10 secondi. Il timeout di ogni singolo controllo è di 1 secondo e il numero di fallimenti consecutivi tollerati prima che scatti l'azione, il failureThreshold, conta i fallimenti consecutivi prima che Kubernetes agisca, e di default vale 3.
In pratica, con i soli default un liveness probe HTTP comincia a controllare il container 0 secondi dopo l'avvio, ogni 10 secondi, e dopo 3 fallimenti consecutivi (quindi al massimo 30 secondi dopo che qualcosa è andato storto) il kubelet uccide il container. Dopo failureThreshold fallimenti consecutivi (default 3), il kubelet uccide il container e il restartPolicy del pod decide se torna su, e i riavvii ripetuti fanno salire il contatore fino a CrashLoopBackOff.
Per PHP-FPM questo è un problema concreto: se l'immagine deve scaricare configurazioni, scaldare l'opcache o aspettare che il database risponda, un initialDelaySeconds a 0 e un periodo di 10 secondi danno al container solo 30 secondi prima di essere considerato morto. Se l'avvio reale richiede 40-50 secondi, il pod entra in loop di riavvio prima ancora di essere mai stato davvero pronto.
YAML di partenza per un pod PHP-FPM
Un punto di partenza ragionevole, da adattare ai tempi di avvio reali della propria applicazione, separa readiness e liveness e aggiunge uno startupProbe che assorbe l'avvio lento:
spec:
containers:
- name: php-fpm
image: registry.example.com/myapp-php:1.0
ports:
- containerPort: 9000
startupProbe:
exec:
command:
- sh
- -c
- SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
periodSeconds: 5
failureThreshold: 24
readinessProbe:
exec:
command:
- sh
- -c
- SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
exec:
command:
- sh
- -c
- SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 5
Il probe usa l'endpoint di ping integrato in PHP-FPM, che si abilita nel pool con ping.path = /ping e ping.response = pong. Con lo startupProbe attivo, il kubelet non esegue readiness e liveness finché lo startup non va a buon fine: se un startup probe è definito, i ritardi di liveness e readiness probe non iniziano finché lo startup probe non ha avuto successo. Qui periodSeconds: 5 e failureThreshold: 24 danno fino a 120 secondi perché PHP-FPM sia pronto, senza toccare i tempi di liveness a regime.
Il failureThreshold più alto sulla liveness (5 invece di 3) è intenzionale: un pool PHP-FPM sotto carico può rispondere più lentamente senza essere realmente bloccato, e un threshold troppo basso sulla liveness rischia di uccidere pod sani solo perché momentaneamente occupati. Il pattern raccomandato dalla documentazione ufficiale va in questa direzione: i campi di configurazione dei probe permettono di controllare con più precisione il comportamento dei controlli di startup, liveness e readiness, usando soglie diverse per readiness (più severa, per togliere traffico subito) e liveness (più permissiva, per non riavviare container che sono solo lenti).
Quando serve davvero uno startupProbe
La documentazione ufficiale dà una regola precisa per decidere se serve uno startup probe: se il container di solito parte in più tempo di initialDelaySeconds + failureThreshold × periodSeconds, bisogna specificare un probe di startup che controlli lo stesso endpoint del liveness probe. Per un pod PHP-FPM con dipendenze esterne (sessioni Redis, connessione al database applicativo) questa condizione si verifica quasi sempre al primo deploy su un cluster nuovo, dove le immagini vanno scaricate e gli init container impiegano secondi preziosi prima che il container principale parta.
Verificare lo stato dopo il deploy
Dopo aver applicato il manifest, il comando per vedere se i probe stanno fallendo è:
kubectl describe pod <nome-pod>
Nella sezione Events compare la sequenza reale di quello che succede. Un esempio tipico quando un liveness probe fallisce e il container viene ucciso:
Warning Unhealthy 10s (x3 over 20s) kubelet Liveness probe failed: ...
Normal Killing 10s kubelet Container php-fpm failed liveness probe, will be restarted
Questa sequenza, documentata nella guida ufficiale alla configurazione dei probe, è il primo posto dove guardare quando un pod si riavvia senza motivo apparente: se negli eventi compare Unhealthy seguito a ruota da Killing, il problema non è nell'applicazione ma nei tempi del probe. Per contare quante volte è già successo:
kubectl get pod <nome-pod>
La colonna RESTARTS si incrementa ogni volta che un container ucciso dal probe torna in stato Running: il contatore RESTARTS si incrementa non appena un container fallito torna in stato di esecuzione. Un numero che cresce nel tempo, abbinato a eventi Unhealthy/Killing ravvicinati, conferma che la causa è la configurazione del probe e non un crash applicativo vero.
Un'alternativa: controllare la coda invece del semplice ping
Per ambienti dove il pool PHP-FPM può saturarsi sotto carico, esiste un controllo più granulare che verifica anche la lunghezza della coda di richieste in attesa, non solo se il processo risponde. È un'opzione da valutare quando il solo ping risulta troppo permissivo e il readiness probe continua a dare luce verde anche con il pool pieno e le richieste in coda.
Testo redatto con il supporto dell'intelligenza artificiale e verificato dalla redazione (AI Act, art. 50).