Nota del traduttore.: Vi presentiamo i dettagli tecnici riguardanti le cause della recente interruzione del servizio cloud gestito dai creatori di Grafana. Questo è un classico esempio di come una nuova, apparentemente utile funzionalità, concepita per migliorare la qualità dell'infrastruttura… possa invece causare danni se non si considerano i numerosi aspetti del suo utilizzo in situazioni di production. È fantastico che emergano materiali come questi, che consentono di imparare non solo dai propri errori. Maggiori dettagli nel testo tradotto dal vicepresidente del prodotto di Grafana Labs.

Venerdì 19 luglio, il servizio Hosted Prometheus in Grafana Cloud ha smesso di funzionare per circa 30 minuti. Ci scusiamo con tutti i clienti colpiti dall'interruzione. Il nostro compito è fornire gli strumenti necessari per il monitoraggio e comprendiamo che la loro indisponibilità complica la vostra vita. Consideriamo questo incidente con la massima serietà. In questo documento spieghiamo cosa è successo, come abbiamo reagito e cosa stiamo facendo affinché non accada più.
Contesto
Il servizio Grafana Cloud Hosted Prometheus si basa su — un progetto CNCF per la creazione di un servizio Prometheus altamente disponibile, scalabile orizzontalmente e multi-tenant. L'architettura di Cortex è composta da un insieme di microservizi, ognuno dei quali svolge una propria funzione: replica, archiviazione, query, ecc. Cortex è in continua evoluzione con nuove funzionalità e miglioramenti delle prestazioni. Deployiamo regolarmente nuove versioni di Cortex nei cluster affinché i clienti possano beneficiare di queste innovazioni — fortunatamente, Cortex è in grado di aggiornarsi senza downtime.
Per aggiornamenti senza interruzioni, il servizio Ingester di Cortex richiede un'ulteriore replica dell'Ingester durante il processo di aggiornamento. (Nota del traduttore.: — il componente fondamentale di Cortex. Il suo compito è raccogliere un flusso continuo di campioni, raggrupparli in chunk di Prometheus e salvarli in un database come DynamoDB, BigTable o Cassandra. Questo consente ai vecchi Ingester di inviare dati correnti ai nuovi Ingester. Vale la pena notare che gli Ingester sono esigenti in termini di risorse. Per il loro funzionamento, è necessario avere 4 core e 15 GB di memoria per pod, ossia il 25% della potenza di elaborazione e della memoria della macchina base nel caso dei nostri cluster Kubernetes. In generale, di solito abbiamo molte più risorse inutilizzate nel cluster piuttosto che 4 core e 15 GB di memoria, quindi possiamo facilmente avviare questi Ingester aggiuntivi durante gli aggiornamenti.
Tuttavia, spesso accade che durante il funzionamento normale non ci siano queste risorse inutilizzate del 25% su nessuna delle macchine. E non aspiriamo nemmeno a farlo: CPU e memoria saranno sempre utili per altri processi. Per affrontare questo problema, abbiamo deciso di utilizzare . L'idea è quella di dare agli Ingester una priorità più alta rispetto ad altri microservizi (stateless). Quando abbiamo bisogno di avviare un Ingester aggiuntivo (N+1), spostiamo temporaneamente altri pod più piccoli. Questi pod vengono trasferiti su risorse libere su altre macchine, lasciando un'ampia "fessura" per avviare l'Ingester aggiuntivo.
Giovedì 18 luglio, abbiamo implementato quattro nuovi livelli di priorità nei nostri cluster: critica, alta, media e bassa. Sono stati testati su un cluster interno senza traffico clienti per circa una settimana. Per impostazione predefinita, i pod senza priorità specificata ricevevano media priorità, per gli Ingester è stata impostata una classe con alta priorità. Critica è stata riservata per il monitoraggio (Prometheus, Alertmanager, node-exporter, kube-state-metrics, ecc.). La nostra configurazione è aperta e puoi consultare il PR .
Incidente
Venerdì 19 luglio, uno degli ingegneri ha avviato un nuovo cluster dedicato Cortex per un grande cliente. La configurazione per questo cluster non includeva le nuove priorità dei pod, quindi a tutti i nuovi pod è stata assegnata la priorità predefinita — media.
Nel cluster Kubernetes non c'erano abbastanza risorse per il nuovo cluster Cortex, e il cluster Cortex di produzione esistente non è stato aggiornato (gli Ingester sono rimasti senza alta priorità). Poiché gli Ingester del nuovo cluster avevano per impostazione predefinita media priorità, mentre i pod esistenti in produzione funzionavano senza priorità, gli Ingester del nuovo cluster hanno sopraffatto gli Ingester del cluster Cortex di produzione esistente.
Il ReplicaSet per l'Ingester espulso nel cluster di produzione ha rilevato un pod espulso e ne ha creato uno nuovo per mantenere il numero designato di repliche. Al nuovo pod è stato assegnato per default media la priorità, e un altro "vecchio" Ingester nel production ha perso risorse. Il risultato è stato un processo a catena, che ha portato all'espulsione di tutti i pod con Ingester per i cluster di produzione di Cortex.
Gli Ingester sono stati progettati per mantenere lo stato e conservano i dati delle ultime 12 ore. Questo ci permette di compattarli in modo più efficiente prima della registrazione nello storage a lungo termine. A tal fine, Cortex esegue lo sharding dei dati per serie, utilizzando una tabella hash distribuita (Distributed Hash Table, DHT), e replica ogni serie su tre Ingester con un sistema di coerenza dei quorum in stile Dynamo. Cortex non scrive dati sugli Ingester che vengono spenti. Così, quando un gran numero di Ingester esce dalla DHT, Cortex non riesce a garantire una replica adeguata delle registrazioni, e queste "crollano".
Rilevamento e risoluzione
Nuove notifiche di Prometheus basate sul "budget degli errori" (error-budget-based — i dettagli saranno disponibili in un futuro articolo) hanno iniziato a suonare l'allerta dopo 4 minuti dall'inizio dell'interruzione. Nei successivi circa cinque minuti, abbiamo effettuato la diagnosi e abbiamo scalato il cluster sottostante di Kubernetes per ospitare sia i nuovi cluster che quelli esistenti in produzione.
Altri cinque minuti dopo, i vecchi Ingester hanno registrato con successo i propri dati, mentre i nuovi sono stati avviati e i cluster Cortex sono stati nuovamente resi disponibili.
Altri 10 minuti sono stati necessari per la diagnosi e la risoluzione degli errori out-of-memory (OOM) dai server proxy inversi di autenticazione situati davanti a Cortex. Gli errori OOM sono stati causati da un aumento decuplicato del QPS (presumibilmente a causa di richieste eccessivamente aggressive dai server Prometheus dei clienti).
Conseguenze
La durata totale dell'interruzione è stata di 26 minuti. I dati non sono stati persi. Gli Ingester hanno caricato con successo tutti i dati in memoria nel deposito a lungo termine. Durante l'interruzione, i server Prometheus dei clienti hanno messo in buffer le registrazioni remote (remote) con basato su WAL (di 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, dobbiamo riconoscere che non avremmo dovuto impostare per impostazione predefinita media la priorità, fino a quando tutti gli Ingester in produzione non hanno ricevuto alta la priorità. Inoltre, avremmo dovuto assicurarci in anticipo del loro elevato priorità. Ora tutto è risolto. 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. In futuro, tali modifiche saranno valutate daunmaggiore numero di persone. Inoltre, la modifica che ha portato al fallimento è stata considerata troppo insignificante per un documento di progetto separato - è stata discussa solo in un problema di GitHub. D'ora in poi, tutte le modifiche alle configurazioni simili saranno accompagnate dalla documentazione di progetto appropriata.
Infine, automatizziamo il ridimensionamento del server proxy inverso di autenticazione per prevenire l'OOM durante il sovraccarico, un episodio che abbiamo vissuto, e analizzeremo le impostazioni di default di Prometheus relative al rollback e al ridimensionamento, per evitare in futuro problemi simili.
Il guasto subito ha avuto anche alcune conseguenze positive: avendo a disposizione le risorse necessarie, Cortex si è ripristinato automaticamente senza ulteriori interventi. Abbiamo anche acquisito preziosa esperienza con — il nostro nuovo sistema di aggregazione dei log, — che ha aiutato a garantire che tutti gli Ingester si comportassero correttamente durante e dopo il guasto.
P.S. dal traduttore
Leggete anche nel nostro blog:
- «»;
- «»;
- «»;
- «».
Fonte: habr.com
