Nota di traduzione.: Presentiamo alla vostra attenzione i dettagli tecnici sui motivi del recente downtime del servizio cloud, gestito dai creatori di Grafana. Questo è un esempio classico di come una nuova e apparentemente utile funzionalità, destinata a migliorare la qualità dell'infrastruttura... possa invece nuocere se non si prevedono i numerosi aspetti del suo utilizzo nella realtà di produzione. È meraviglioso quando emergono materiali come questi, che consentono di imparare non solo dai propri errori. I dettagli sono nella traduzione di questo testo da parte del vicepresidente del prodotto di Grafana Labs.

Venerdì 19 luglio, il servizio Hosted Prometheus in Grafana Cloud ha smesso di funzionare per circa 30 minuti. Mi scuso con tutti i clienti che hanno subito il guasto. Il nostro compito è fornire gli strumenti necessari per il monitoraggio, e comprendiamo che la loro mancanza complica la vostra vita. Prendiamo molto sul serio questo incidente. In questa nota spieghiamo cosa è successo, come abbiamo reagito e cosa stiamo facendo per evitare che accada di nuovo.
Antefatti
Il servizio Grafana Cloud Hosted Prometheus si basa su — un progetto CNCF volto a creare un servizio Prometheus orizzontalmente scalabile, altamente disponibile e multi-tenant. L'architettura di Cortex consiste in un insieme di microservizi separati, ognuno dei quali svolge una propria funzione: replica, archiviazione, richieste, ecc. Cortex è in attiva sviluppo e sta continuamente acquisendo nuove funzionalità e migliorando le prestazioni. Rilasciamo regolarmente nuove versioni di Cortex nei cluster, affinché i clienti possano beneficiare di queste funzionalità, dato che Cortex è capace di aggiornarsi senza downtime.
Per aggiornamenti senza downtime, il servizio Ingester di Cortex richiede un'ulteriore replica dell'Ingester durante il processo di aggiornamento. (Nota di traduzione.: è il componente fondamentale di Cortex. Il suo compito è raccogliere un flusso costante di campioni, raggrupparli in chunk di Prometheus e salvarli in un database come DynamoDB, BigTable o Cassandra. Questo consente ai vecchi Ingester di trasferire i dati correnti ai nuovi Ingester. Va notato che gli Ingester sono esigenti in termini di risorse. Per funzionare, è necessario avere 4 core e 15 GB di memoria per pod, ovvero il 25% della potenza di elaborazione e della memoria della macchina base nei nostri cluster Kubernetes. In generale, abbiamo di solito molte più risorse inutilizzate nel cluster rispetto a 4 core e 15 GB di memoria, quindi possiamo eseguire facilmente questi ingester aggiuntivi durante gli aggiornamenti.
Tuttavia, spesso accade che durante un funzionamento normale nessuna delle macchine disponga di queste risorse inutilizzate del 25%. E non ci aspettiamo nemmeno che sia così: CPU e memoria saranno sempre utili per altri processi. Per risolvere questo problema, abbiamo deciso di utilizzare . L'idea è quella di assegnare agli Ingester una priorità più alta rispetto ad altri microservizi (stateless). Quando dobbiamo avviare un Ingester aggiuntivo (N+1), temporaneamente spostiamo altri pod più piccoli. Questi pod vengono trasferiti in risorse libere su altre macchine, creando un "vuoto" sufficientemente grande per avviare un Ingester aggiuntivo.
Giovedì, 18 luglio, abbiamo distribuito quattro nuovi livelli di priorità nei nostri cluster: critico, alto, medio e basso. Sono stati testati in un cluster interno senza traffico client per circa una settimana. Per impostazione predefinita, i pod senza priorità specificata ricevevano medio priorità, per gli Ingester è stata impostata una classe con alta priorità. Critico è stato riservato per il monitoraggio (Prometheus, Alertmanager, node-exporter, kube-state-metrics, ecc.). La nostra configurazione è aperta e puoi visualizzare la PR .
Guasto
Venerdì, 19 luglio, uno degli ingegneri ha avviato un nuovo cluster dedicato di Cortex per un grande cliente. La configurazione per questo cluster non includeva le nuove priorità dei pod, quindi a tutti i nuovi pod veniva assegnata la priorità predefinita - medio.
Nel cluster Kubernetes non c'erano risorse sufficienti per il nuovo cluster Cortex, e il cluster di produzione esistente di Cortex non è stato aggiornato (gli Ingester sono rimasti senza alta priorità). Poiché gli Ingester del nuovo cluster avevano per impostazione predefinita medio priorità, e i pod esistenti in produzione lavoravano senza alcuna priorità, gli Ingester del nuovo cluster hanno soppiantato gli Ingester del cluster di produzione esistente di Cortex.
Il ReplicaSet per l'Ingester estromesso nel cluster di produzione ha rilevato il pod estromesso e ne ha creato uno nuovo per mantenere il numero di repliche specificato. Al nuovo pod è stato assegnato per impostazione predefinita medio la priorità, e un altro "vecchio" Ingester nel production ha perso risorse. Il risultato è stato un processo a valanga, che ha portato all'estromissione di tutti i pod con Ingester per i cluster di produzione di Cortex.
Gli Ingester sono a stato conservato (stateful) e memorizzano i dati delle ultime 12 ore. Questo ci consente di comprimere più efficacemente i dati prima di scriverli nell'archiviazione a lungo termine. Per farlo, Cortex esegue lo sharding dei dati per serie, utilizzando una tabella hash distribuita (Distributed Hash Table, DHT), e replica ciascuna serie su tre Ingester utilizzando la coerenza di quorum in stile Dynamo. Cortex non scrive dati sugli Ingester che vengono spenti. Pertanto, quando un numero elevato di Ingester lascia la DHT, Cortex non può garantire una replicazione sufficiente delle registrazioni, e queste "falliscono".
Rilevamento e risoluzione
Nuove notifiche Prometheus basate sul "budget degli errori" (error-budget-based — i dettagli saranno forniti in un articolo futuro) hanno iniziato a suonare l'allerta dopo 4 minuti dall'inizio dello spegnimento. Nei successivi cinque minuti circa abbiamo eseguito la diagnostica e abbiamo aumentato il cluster Kubernetes sottostante per ospitare sia i nuovi che i già esistenti cluster di produzione.
Altri cinque minuti dopo, i vecchi Ingester hanno registrato con successo i loro dati, mentre i nuovi sono stati avviati e i cluster di Cortex sono tornati disponibili.
Ci sono voluti altri 10 minuti per la diagnostica e la risoluzione degli errori di out-of-memory (OOM) dai server proxy di autenticazione inversa, posizionati davanti a Cortex. Gli errori OOM sono stati causati da un incremento dieci volte superiore delle QPS (presumibilmente a causa di richieste eccessivamente aggressive dai server Prometheus dei clienti).
Conseguenze
La durata totale dell'inattività è stata di 26 minuti. I dati non sono stati persi. Gli Ingester hanno caricato con successo tutti i dati in memoria nell'archiviazione a lungo termine. Durante l'interruzione, i server Prometheus dei clienti hanno memorizzato temporaneamente le registrazioni (remote) utilizzando il basato su WAL (scritto da di Grafana Labs) e hanno ripetuto le registrazioni non riuscite dopo il guasto.

Operazioni di scrittura del cluster di produzione
Conclusioni
È importante trarre insegnamenti da questo incidente e adottare le misure necessarie per evitare che si ripeta.
Guardando indietro, bisogna ammettere che non avremmo dovuto impostare per default medio la priorità, finché tutti gli Ingester non fossero stati in produzione alto con priorità. Inoltre, sarebbe stato opportuno prendersi cura in anticipo delle loro alte priorità. Ora tutto è sistemato. Ci auguriamo che la nostra esperienza possa aiutare altre organizzazioni che stanno considerando l'uso delle priorità dei pod in Kubernetes.
Aggiungeremo un ulteriore livello di controllo sul dispiegamento di eventuali oggetti aggiuntivi, la cui configurazione è globale per il cluster. Da ora in poi, tali modifiche saranno valutate daunnumero maggiore di persone. Inoltre, la modifica che ha portato al guasto è stata ritenuta troppo insignificante per un documento di progetto separato — è stata discussa solo in un'issue di GitHub. Da questo momento in poi, tutte le modifiche simili alle configurazioni saranno accompagnate dalla relativa documentazione di progetto.
Infine, automatizzeremo il ridimensionamento del reverse proxy per l'autenticazione per prevenire OOM durante un sovraccarico, di cui siamo stati testimoni, e analizzeremo i parametri di Prometheus predefiniti relativi al rollback e al ridimensionamento, per prevenire in futuro problemi simili.
Il guasto subito ha avuto anche alcune conseguenze positive: ottenendo le risorse necessarie, Cortex si è riavviato automaticamente senza ulteriori interventi. Abbiamo anche appreso preziose lezioni lavorando con — il nostro nuovo sistema di aggregazione dei log, — che ha aiutato a verificare che tutti gli Ingester si comportassero correttamente durante e dopo il guasto.
P.S. dal traduttore
Leggi anche nel nostro blog:
- «»;
- «»;
- «»;
- «».
Fonte: habr.com
