Le liveness probes in Kubernetes possono essere pericolosi

Nota del traduttore.: Henning Jacobs, chief engineer at Zalando, ha notato più volte che gli utenti di Kubernetes hanno difficoltà a comprendere lo scopo dei liveness (e readiness) probes e il loro corretto utilizzo. Pertanto, ha raccolto i suoi pensieri in questa concisa nota, che nel tempo diventerà parte della documentazione di K8s.

Le liveness probes in Kubernetes possono essere pericolosi

I controlli dello stato, conosciuti in Kubernetes come liveness probes (ossia, letteralmente, "test di vitalità" — nota del traduttore), possono essere molto pericolosi. Ti consiglio di evitarli se possibile: le eccezioni sono solo i casi in cui sono davvero necessari e sei pienamente consapevole delle specificità e delle conseguenze del loro utilizzo. In questo documento si parlerà dei liveness e readiness probes, e si spiegherà in quali casi è consigliabile e non è consigliabile applicarli.

Il mio collega Sandor ha recentemente condiviso su Twitter gli errori più comuni che incontra, inclusi quelli legati all'uso dei readiness/liveness probes:

Le liveness probes in Kubernetes possono essere pericolosi

Configurazione errata livenessProbe può esacerbare le situazioni di carico elevato (spegnimenti a valanga + riavvio potenzialmente lungo del container/applicazione) e portare ad altre conseguenze negative come il fallimento delle dipendenze (vedi anche il mio recente articolo sul limite del numero di richieste nella combinazione K3s+ACME). È ancora peggio quando il liveness probe è combinato con il controllo dello stato delle dipendenze (health check), rappresentato da un database esterno: un singolo guasto del database riavvierà tutti i tuoi container!

Messaggio generale "Non utilizzare i liveness probes" in questo caso non aiuta molto, quindi consideriamo a cosa servono i readiness e liveness check.

Nota: la maggior parte del test fornito di seguito era originariamente inclusa nella documentazione interna per gli sviluppatori di Zalando.

Controlli Readiness e Liveness

Kubernetes fornisce due importanti meccanismi chiamati liveness probes e readiness probes. Eseguono periodicamente un'azione — ad esempio, inviare una richiesta HTTP, aprire una connessione TCP o eseguire un comando nel container — per confermare che l'applicazione funzioni correttamente.

Kubernetes utilizza readiness probes, per capire quando il contenitore è pronto a ricevere traffico. Un pod si considera pronto per il lavoro se tutti i suoi contenitori sono pronti. Uno degli usi di questo meccanismo è controllare quali pod vengono utilizzati come backend per i servizi Kubernetes (e in particolare per Ingress).

Liveness probes aiutano Kubernetes a capire quando è il momento di riavviare il contenitore. Ad esempio, una tale verifica può intercettare un deadlock, quando l'applicazione 'si blocca' in un punto. Riavviare il contenitore in questo stato aiuta a sbloccare l'applicazione, nonostante gli errori, ma può anche portare a guasti a cascata (vedi sotto).

Se cerchi di distribuire un aggiornamento dell'applicazione che fallisce i controlli di liveness/readiness, il rilascio si fermerà poiché Kubernetes attenderà lo stato Pronto di tutti i pod.

Esempio

Ecco un esempio di readiness probe che controlla il percorso /health via HTTP con impostazioni predefinite (interval: 10 secondi, timeout: 1 secondo, success threshold: 1, failure threshold: 3):

# часть общего описания deployment'а/стека
podTemplate:
  spec:
    containers:
    - name: my-container
      # ...
      readinessProbe:
        httpGet:
          path: /health
          port: 8080

Raccomandazioni

  1. Per i microservizi con endpoint HTTP (REST, ecc.) definisci sempre una readiness probe, che verifica se l'applicazione (pod) è pronta a ricevere traffico.
  2. Assicurati che la readiness probe copre la disponibilità 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 (come 8080) è pronta per ricevere traffico*;

      * Sono a conoscenza di almeno un caso in Zalando in cui ciò non è accaduto, cioè readinessProbe ho controllato la porta «management», ma il server stesso non è partito a causa di problemi di caricamento della cache.

    • collegare la readiness probe a una porta separata può fare in modo che il sovraccarico sulla porta principale non si rifletta nel health check (cioè il pool di thread sul server è pieno, ma l'health check continua a mostrare che tutto va bene).
  3. Assicurati che la readiness probe includa l'inizializzazione/migrazione del database;
    • il modo più semplice per ottenerlo è contattare il server HTTP solo dopo il completamento dell'inizializzazione (ad esempio, la migrazione del DB con Flyway ecc.); cioè invece di modificare lo stato dell'health check, non avviare semplicemente il server web fino al completamento della migrazione del DB*.

      * È possibile eseguire migrazioni del database da init-container esterni al pod. Rimango un sostenitore delle applicazioni autonome, ovvero quelle in cui il container dell'applicazione sa come portare il database nello stato desiderato senza coordinazione esterna.

  4. Usa httpGet per i controlli di readiness attraverso i tipici endpoint delle health check (ad esempio, /health).
  5. Comprendere 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 funzionalità non riusciti).
  6. 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.
  7. Se necessario, la readiness probe può essere utilizzata per riscaldare/caricare la cache restituendo un codice di stato 503, finché il container non è «riscaldato»:

Avvertenze

  1. Non fare affidamento su dipendenze esterne (come i repository di dati) durante i test di readiness/liveness — questo può portare a guasti a cascata:
    • prendiamo come esempio un servizio stateful REST con 10 pod che dipendono da un'unica base di dati Postgres: quando il controllo dipende da una connessione funzionante al DB, tutti e 10 i pod possono andare in crash se si verifica un ritardo nella rete/o dal lato del DB — di solito tutto ciò termina peggio di quanto potrebbe;
    • si noti che Spring Data controlla la connessione con il DB per impostazione predefinita*;

      * Questo è il comportamento predefinito di Spring Data Redis (almeno era così quando ho verificato l'ultima volta), il che ha portato a un crash 'catastrofico': quando Redis è stato temporaneamente non disponibile, tutti i pod sono 'crollati'.

    • 'esterno' in questo senso può anche significare altri pod della stessa applicazione, quindi idealmente il controllo non dovrebbe dipendere dallo stato di altri pod dello stesso cluster per prevenire i crolli a cascata:
      • i risultati possono variare per applicazioni con stato distribuito (ad esempio, caching in-memory nei pod).
  2. Non utilizzare il liveness probe per i pod (eccetto nei casi in cui siano davvero necessari e si sia pienamente consapevoli delle specifiche e delle conseguenze del loro utilizzo):
    • il liveness probe può aiutare a recuperare contenitori "bloccati", ma poiché hai il pieno controllo sulla tua applicazione, situazioni come processi "bloccati" e deadlock non dovrebbero idealmente verificarsi: la migliore alternativa è il crash intenzionale dell'applicazione e il suo ritorno a uno stato stabile precedente;
    • un liveness probe non riuscito porterà al riavvio del contenitore, il che potenzialmente esacerba le conseguenze di errori legati al caricamento: il riavvio del contenitore porterà a 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à di guasti, ecc.;
    • le verifiche di liveness cominate con una dipendenza esterna sono la peggiore delle combinazioni possibili, minacciando danni a cascata: un leggero ritardo da parte del database porterà al riavvio di tutti i tuoi contenitori!
  3. Parametri delle verifiche di liveness e readiness dovrebbero essere diversi:
    • È possibile utilizzare il liveness probe con lo stesso health check, ma con una soglia di attivazione più alta (failureThreshold), ad esempio, assegnare lo stato not-ready dopo 3 tentativi e considerare il liveness probe fallito dopo 10 tentativi;
  4. Non utilizzare controlli exec, poiché comportano noti problemi che portano alla creazione di processi zombie:

Riepilogo

  • Utilizzare i readiness probes per determinare quando il pod è pronto a ricevere traffico.
  • Utilizzare i liveness probes solo quando sono realmente necessari.
  • Un uso errato dei readiness/liveness probes può portare a una riduzione della disponibilità e a fallimenti a cascata.

Le liveness probes in Kubernetes possono essere pericolosi

Ulteriori materiali sull'argomento

Aggiornamento n. 1 del 2019-09-29

Sugli init-container per la migrazione del DB: aggiunta una nota.

EJ mi ha ricordato del PDB: una delle problematiche delle liveness checks è l'assenza di coordinazione tra i pod. In Kubernetes ci sono Pod Disruption Budgets (PDB) per limitare il numero di fallimenti paralleli che un'app può subire, tuttavia i controlli non considerano il PDB. Idealmente, possiamo ordinare a K8s: "Riavvia un pod se il suo controllo fallisce, ma non riavviare tutti, per non peggiorare la situazione".

Bryan ha formulato molto bene: «Utilizza i controlli di liveness quando sei certo che la cosa migliore da fare sia «terminare» l'applicazione» (anche se non esagerare).

Le liveness probes in Kubernetes possono essere pericolosi

Aggiornamento n. 2 del 2019-09-29

Riguardo alla lettura della documentazione prima dell'uso: ho creato una richiesta pertinente (feature request) per aggiungere documentazione sui controlli di liveness.

P.S. dal traduttore

Leggete anche nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster