Nota di traduzione.: L'ingegnere principale di Zalando, Henning Jacobs, ha notato più volte che gli utenti di Kubernetes hanno problemi a comprendere lo scopo delle probe di liveness (e readiness) e il loro corretto utilizzo. Pertanto, ha raccolto i suoi pensieri in questa nota concisa, che diventerà parte della documentazione K8s nel tempo.

Le verifiche di stato, note in Kubernetes come liveness probes (cioè, letteralmente, "test di vitalità" — nota del traduttore), possono essere piuttosto pericolose. Consiglio di evitarle quando possibile: le uniche eccezioni sono i casi in cui sono veramente necessarie e si è completamente consapevoli della specificità e delle conseguenze del loro utilizzo. In questo articolo si parlerà delle verifiche di liveness e readiness e si dirà in quali casi è opportuno e non vale la pena utilizzarle.
Il mio collega Sandor ha recentemente condiviso su Twitter gli errori più comuni che incontra, inclusi quelli relativi all'uso delle probe di readiness/liveness:
Una livenessProbe impostata in modo errato può aggravare le situazioni di alta carico (disattivazione a valanga + avvio potenzialmente lungo del contenitore/applicazione) e portare ad altre conseguenze negative come il crollo delle dipendenze (vedi anche sulla limitazione del numero di richieste nella combo K3s+ACME). È ancora peggio quando una liveness probe è combinata con un controllo di salute di una dipendenza (health check), in cui si trova un database esterno: un singolo malfunzionamento del database riavvierà tutti i tuoi contenitori!
Il messaggio principale "Non utilizzare le liveness probes" in questo caso aiuta poco, quindi vediamo a cosa servono le verifiche di readiness e liveness.
Nota: la maggior parte del test sottostante è stata originariamente inclusa nella documentazione interna per gli sviluppatori di Zalando.
Le verifiche di Readiness e Liveness
Kubernetes fornisce due meccanismi importanti, chiamati . Essi eseguono periodicamente un'azione, ad esempio inviano una richiesta HTTP, aprono una connessione TCP o eseguono un comando nel contenitore, per confermare che l'applicazione funzioni correttamente.
Kubernetes utilizza readiness probes, per capire quando il contenitore è pronto a ricevere traffico. Un pod è considerato pronto a funzionare se tutti i suoi contenitori sono pronti. Una delle applicazioni di questo meccanismo è controllare quali pod vengono utilizzati come backend per i servizi Kubernetes (e in particolare per l'Ingress).
Le sonde di liveness aiutano Kubernetes a capire quando è il momento di riavviare il contenitore. Ad esempio, un controllo di questo tipo può intercettare un deadlock, quando un'applicazione 'si blocca' in un punto. Riavviare il contenitore in questo stato aiuta a far ripartire l'applicazione da un punto morto, nonostante gli errori, ma può anche portare a fallimenti a cascata (vedi sotto).
Se provi a distribuire un aggiornamento dell'applicazione che non supera i controlli di liveness/readiness, la distribuzione si fermerà, poiché Kubernetes attenderà lo stato Pronto da tutti i pod.
Esempio
Ecco un esempio di readiness probe che controlla il percorso /health tramite HTTP con impostazioni predefinite (intervallo: 10 secondi, timeout: 1 secondo, soglia di successo: 1, soglia di errore: 3):
# часть общего описания deployment'а/стека
podTemplate:
spec:
containers:
- name: my-container
# ...
readinessProbe:
httpGet:
path: /health
port: 8080Raccomandazioni
- Per microservizi con endpoint HTTP (REST, ecc.) definisci sempre una readiness probe, che verifica se l'applicazione (pod) è pronta a ricevere traffico.
- Assicurati che la readiness probe verifichi la prontezza della porta effettiva del server web:
- utilizzando porte per esigenze amministrative, denominate 'admin' o 'management' (ad esempio, 9090), per
readinessProbe, assicurati che l'endpoint restituisca OK solo se la porta HTTP principale (tipo 8080) è pronta a ricevere traffico*;* Sono a conoscenza di almeno un caso in Zalando in cui ciò non è avvenuto, ovvero
readinessProbeha controllato la porta 'management', ma il server non è mai partito a causa di problemi di caricamento della cache. - aggiornare la readiness probe su una porta separata può portare al fatto che il sovraccarico sulla porta principale non venga riflesso nel controllo di salute (cioè il pool di thread sul server è pieno, ma il controllo di salute continua a mostrare che tutto va bene).
- utilizzando porte per esigenze amministrative, denominate 'admin' o 'management' (ad esempio, 9090), per
- Assicurati che la readiness probe includa l'inizializzazione/migrazione del database;
- il modo più semplice per farlo è chiamare il server HTTP solo dopo che l'inizializzazione è completata (ad esempio, la migrazione del DB con ecc.); cioè, invece di modificare lo stato del controllo di salute, non avviare semplicemente il server web fino al completamento della migrazione del DB*.
* È possibile anche eseguire migrazioni del database da contenitori init al di fuori del pod. Rimango un sostenitore delle applicazioni indipendenti, ovvero quelle in cui il contenitore dell'applicazione sa come portare il database nello stato desiderato senza coordinamento esterno.
- il modo più semplice per farlo è chiamare il server HTTP solo dopo che l'inizializzazione è completata (ad esempio, la migrazione del DB con ecc.); cioè, invece di modificare lo stato del controllo di salute, non avviare semplicemente il server web fino al completamento della migrazione del DB*.
- Usa
httpGetper i controlli di readiness tramite endpoint tipici dei health check (ad esempio,/health). - Familiarizzate con i parametri di controllo predefiniti (
interval: 10s,timeout: 1s,successThreshold: 1,failureThreshold: 3):- i parametri predefiniti significano che il pod diventerà not-ready dopo circa 30 secondi (3 controlli di salute non riusciti).
- Utilizzare una porta separata per «admin» o «management», se il stack tecnologico (ad esempio, Java/Spring) lo consente, per separare la gestione della «salute» e delle metriche dal traffico normale:
- ma non dimenticate il punto 2.
- Se necessario, il readiness probe può essere utilizzato per il preriscaldamento/caricamento della cache e restituire il codice di stato 503 finché il contenitore non è «pronto»:
- consiglio anche di prendere visione del nuovo controllo
startupProbe, (ne abbiamo parlato in russo — nota del traduttore.).
- consiglio anche di prendere visione del nuovo controllo
Avvertenze
- Non fare affidamento su dipendenze esterne (come i database) durante i test di readiness/liveness — questo potrebbe causare fallimenti a cascata:
- prendiamo come esempio un servizio stateful REST con 10 pod che dipendono da un singolo database Postgres: quando il controllo dipende da una connessione funzionante al database, tutti e 10 i pod possono cadere se si verifica un ritardo nella rete/o sul lato del database — di solito tutto ciò finisce peggio di quanto potrebbe;
- si noti che Spring Data controlla la connessione al database per impostazione predefinita*;
* Questo è il comportamento predefinito di Spring Data Redis (almeno era così quando ho controllato l'ultima volta), che ha portato a un «fallimento catastrofico»: quando Redis è stato momentaneamente non disponibile, tutti i pod sono «caduti».
- «esterno» in questo senso può anche significare altri pod della stessa applicazione, ovvero idealmente il controllo non dovrebbe dipendere dallo stato di altri pod dello stesso cluster per prevenire cadute a cascata:
- i risultati possono variare per applicazioni con stato distribuito (ad esempio, caching in memoria nei pod).
- Non utilizzare il liveness probe per i pod (fanno eccezione i casi in cui sono realmente necessari e sei completamente consapevole delle specifiche e delle conseguenze del loro utilizzo):
- il liveness probe può aiutare a ripristinare i contenitori "bloccati", ma, poiché hai il controllo totale sulla tua applicazione, cose come i processi "bloccati" e i deadlock non dovrebbero idealmente verificarsi: la migliore alternativa è un arresto intenzionale dell'applicazione e il suo ripristino a uno stato stabile precedente;
- un liveness probe fallito porterà al riavvio del contenitore, potenzialmente aggravando le conseguenze degli errori legati al caricamento: il riavvio del contenitore comporterà un'interruzione (almeno durante il tempo di avvio dell'applicazione, diciamo, per più di 30 secondi), causando nuovi errori, aumentando il carico su altri contenitori e aumentando la probabilità che anche questi vadano in errore, ecc.;
- i liveness probe abbinati a una dipendenza esterna costituiscono la peggiore delle combinazioni possibili, causando fallimenti a cascata: un piccolo ritardo lato DB porterà al riavvio di tutti i tuoi contenitori!
- I parametri dei liveness e readiness probe devono essere diversi:
- puoi usare il liveness probe con lo stesso controllo di salute, ma con una soglia di attivazione più alta (
failureThreshold), ad esempio, assegnare uno stato not-ready dopo 3 tentativi e considerare che il liveness probe sia fallito dopo 10 tentativi;
- puoi usare il liveness probe con lo stesso controllo di salute, ma con una soglia di attivazione più alta (
- Non utilizzare controlli exec, poiché presentano problemi noti che portano alla comparsa di processi zombie:
- dettagli: vedere .
Riepilogo
- Utilizza i readiness probes per determinare quando un pod è pronto per ricevere traffico.
- Utilizza i liveness probes solo quando sono realmente necessari.
- Un uso errato dei readiness/liveness probes può portare a una diminuzione della disponibilità e a fallimenti a cascata.
Ulteriori materiali sull'argomento
- ;
- ;
- (parla anche di livenessProbe).
Aggiornamento n. 1 del 29-09-2019
: nota aggiunta.
il PDB: una delle difficoltà dei liveness probe è la mancanza di coordinamento tra i pod. In Kubernetes ci sono per limitare il numero di guasti parallelamente che un'applicazione può subire, tuttavia i controlli non considerano il PDB. Idealmente, possiamo istruire K8s: «Riavvia un pod se il suo controllo fallisce, ma non riavviarli tutti, per non peggiorare ulteriormente la situazione».
: «Utilizza il liveness probing quando sei sicuro che la cosa migliore da fare sia 'uccidere' l'applicazione» (anche in questo caso, non esagerare).
Aggiornamento n. 2 del 2019-09-29
: ho creato una richiesta corrispondente () per integrare la documentazione sui liveness probes.
P.S. dal traduttore
Leggi anche nel nostro blog:
- «»;
- «»;
- «».
Fonte: habr.com
