Come abbiamo a CIAN domato terabyte di log

Come abbiamo a CIAN domato terabyte di log

Ciao a tutti, mi chiamo Alessandro, lavoro in CIAN come ingegnere e mi occupo di amministrazione di sistema e automazione dei processi infrastrutturali. Nei commenti a uno dei miei articoli passati ci è stato chiesto di spiegare da dove prendiamo 4 TB di log al giorno e cosa ne facciamo. Sì, abbiamo molti log e per il loro trattamento è stato creato un cluster infrastrutturale separato che ci consente di risolvere i problemi rapidamente. In questo articolo parlerò di come nel corso di un anno l'abbiamo adattato per lavorare con un flusso di dati in costante crescita.

Da dove siamo partiti

Come abbiamo a CIAN domato terabyte di log

Negli ultimi anni il carico su cian.ru è cresciuto molto rapidamente, e nel terzo trimestre del 2018 la visitabilità della risorsa ha raggiunto 11,2 milioni di utenti unici al mese. In quegli anni, nei momenti critici, perdevamo fino al 40% dei log, il che ci impediva di affrontare rapidamente gli incidenti e ci faceva perdere molto tempo ed energie per risolverli. Inoltre, spesso non riuscivamo a trovare la causa del problema, che si ripresentava dopo qualche tempo. Era un vero incubo, e dovevamo fare qualcosa.

A quel tempo, per memorizzare i log, usavamo un cluster di 10 data node con ElasticSearch versione 5.5.2 con configurazioni degli indici standard. È stato implementato più di un anno fa come una soluzione popolare e accessibile: all'epoca il flusso di log non era così grande, quindi non aveva senso creare configurazioni personalizzate. 

Il trattamento dei log in ingresso era assicurato da Logstash su diverse porte su cinque coordinatori ElasticSearch. Un indice, indipendentemente dalle dimensioni, consisteva di cinque shard. Era organizzata una rotazione oraria e giornaliera, risultando in circa 100 nuovi shard ogni ora nel cluster. Finché i log non erano troppo numerosi, il cluster gestiva la situazione e nessuno si soffermava sulle sue impostazioni. 

Problemi di crescita rapida

Il volume di log generati cresceva molto rapidamente, poiché si sovrapponevano due processi. Da un lato, il numero di utenti del servizio aumentava. Dall'altro, abbiamo iniziato a passare attivamente a un'architettura a microservizi, suddividendo i nostri vecchi monoliti in C# e Python. Diverse decine di nuovi microservizi, che sostituivano parti del monolite, generavano notevolmente più log per il cluster infrastrutturale. 

È proprio la scalabilità che ci ha portato a una situazione in cui il cluster è diventato praticamente ingovernabile. Quando i log hanno iniziato ad arrivare a una velocità di 20.000 messaggi al secondo, una rotazione frequente e inutile ha aumentato il numero di shard a 6.000, con oltre 600 shard per nodo. 

Questo ha portato a problemi di allocazione della memoria, e quando un nodo falliva, si verificava un trasferimento simultaneo di tutti gli shard, moltiplicando il traffico e sovraccaricando gli altri nodi, rendendo praticamente impossibile scrivere dati nel cluster. E in quel periodo siamo rimasti senza log. E quando si verificava un problema con server perdevamo 1/10 del cluster in linea di massima. Un gran numero di indici di piccole dimensioni complicava ulteriormente la situazione.

Senza log non capivamo le cause dell'incidente e, prima o poi, avremmo potuto ricadere negli stessi errori, e nella nostra ideologia di squadra ciò era inaccettabile, poiché tutti i nostri meccanismi di lavoro sono progettati proprio per evitare di ripetere gli stessi problemi. Per questo avevamo bisogno di avere accesso a tutti i log e di riceverli quasi in tempo reale, poiché il team di ingegneri di guardia monitorava gli allerta non solo dalle metriche, ma anche dai log. Per far comprendere l'entità del problema, a quel punto il volume totale dei log era di circa 2 TB al giorno. 

Abbiamo stabilito l'obiettivo di eliminare completamente la perdita di log e ridurre il tempo di consegna nel cluster ELK a un massimo di 15 minuti in caso di emergenze (su questo valore ci siamo poi basati come KPI interno).

Il nuovo meccanismo di rotazione e nodi hot-warm

Come abbiamo a CIAN domato terabyte di log

Abbiamo iniziato la trasformazione del cluster aggiornando la versione di ElasticSearch da 5.5.2 a 6.4.3. Il nostro cluster della quinta versione è crollato di nuovo e abbiamo deciso di spegnerlo e aggiornare completamente— tanto non ci sono log. Quindi, questo passaggio lo abbiamo effettuato in sole poche ore.

La trasformazione più significativa in questa fase è stata l'implementazione di Apache Kafka su tre nodi con un coordinatore come buffer intermedio. Il broker dei messaggi ci ha liberato dalla perdita di log durante i problemi con ElasticSearch. Contemporaneamente, abbiamo aggiunto 2 nodi al cluster e siamo passati a un'architettura hot-warm con tre nodi "caldi" posizionati in diverse rack nel data center. Su di essi abbiamo reindirizzato i log, che non possono essere persi in nessun caso — nginx, così come i log degli errori delle applicazioni. Gli altri nodi ricevevano log minori — debug, warning, ecc., e dopo 24 ore venivano trasferiti i log "importanti" dai nodi "caldi".

Per non aumentare il numero di indici di piccole dimensioni, siamo passati da una rotazione basata sul tempo a un meccanismo di rollover. Nei forum c'era molta informazione sul fatto che la rotazione per dimensione dell'indice è molto inaffidabile, quindi abbiamo deciso di utilizzare la rotazione in base al numero di documenti nell'indice. Abbiamo analizzato ogni indice e registrato il numero di documenti dopo il quale deve scattare il rollover. In questo modo abbiamo raggiunto una dimensione ottimale per lo shard — non superiore a 50 GB. 

Ottimizzazione del cluster

Come abbiamo a CIAN domato terabyte di log

Tuttavia, non ci siamo liberati completamente dei problemi. Sfortunatamente, comparivano comunque piccoli indici: non raggiungevano il volume stabilito, non venivano ruotati e venivano eliminati tramite una pulizia globale degli indici più vecchi di tre giorni, poiché avevamo rimosso la rotazione per data. Ciò portava a una perdita di dati poiché l'indice scompariva completamente dal cluster, e il tentativo di scrivere in un indice inesistente rompeva la logica del curator che usavamo per la gestione. L'alias per la scrittura si trasformava in un indice e rompeva la logica del rollover, causando una crescita incontrollata di alcuni indici fino a 600 GB. 

Ad esempio, per la configurazione del rollover:

curator-elk-rollover.yaml

---
actions:
  1:
    action: rollover
    options:
      name: "nginx_write"
      conditions:
        max_docs: 100000000
  2:
    action: rollover
    options:
      name: "python_error_write"
      conditions:
        max_docs: 10000000

In assenza di rollover, alias si è verificato un errore:

ERROR     alias "nginx_write" not found.
ERROR     Failed to complete action: rollover.  : Unable to perform index rollover with alias "nginx_write".

Abbiamo rimandato la soluzione di questo problema alla prossima iterazione e ci siamo occupati di un'altra questione: siamo passati alla logica di lavoro pull di Logstash, che si occupa dell'elaborazione dei log in ingresso (rimuovendo informazioni superflue e arricchendo i dati). Lo abbiamo inserito in Docker, che gestiamo tramite docker-compose, e lì abbiamo collocato logstash-exporter, che invia metriche a Prometheus per il monitoraggio in tempo reale del flusso di log. In questo modo ci siamo dati la possibilità di modificare agevolmente il numero di istanze logstash responsabili dell'elaborazione di ciascun tipo di log.

Mentre raffinavamo il cluster, il traffico su cian.ru è aumentato fino a 12,8 milioni di utenti unici al mese. Di conseguenza, ci siamo trovati con il fatto che le nostre trasformazioni non riuscivano a tenere il passo con le modifiche in produzione, e ci siamo scontrati con il problema che le nodi "calde" non erano in grado di gestire il carico e rallentavano l'intera consegna dei log. I dati "caldi" li ricevevamo senza problemi, ma per la consegna degli altri dovevamo intervenire manualmente e fare un rollover, per distribuire uniformemente gli indici. 

Nel contempo, la scalabilità e la modifica delle impostazioni delle istanze logstash nel cluster erano complicate dal fatto che si trattava di un docker-compose locale, e tutte le operazioni venivano eseguite manualmente (per aggiungere nuovi endpoint, era necessario passare manualmente su tutti i server e eseguire everywhere docker-compose up -d).

Ridimensionamento dei log

A settembre di quest'anno continuavamo ancora a disgregare il monolite, il carico sul cluster aumentava, e il flusso di log si avvicinava a 30.000 messaggi al secondo. 

Come abbiamo a CIAN domato terabyte di log

Abbiamo iniziato la prossima iterazione con l'aggiornamento dell'hardware. Da cinque coordinatori siamo passati a tre, abbiamo sostituito le nodi dati e abbiamo ottenuto vantaggi sia in termini di costi che di spazio di archiviazione. Per le nodi utilizziamo due configurazioni: 

  • Per le nodi "calde": E3-1270 v6 / 960 Gb SSD / 32 Gb x 3 x 2 (3 per Hot1 e 3 per Hot2).
  • Per le nodi "fredde": E3-1230 v6 / 4 Tb SSD / 32 Gb x 4.

In questa iterazione abbiamo spostato l'indice con i log di accesso dei microservizi, che occupa lo stesso spazio dei log dei nginx frontend, in un secondo gruppo di tre nodi "caldi". Ora conserviamo i dati sui nodi "caldi" per 20 ore, per poi trasferirli sui nodi "freddi" insieme agli altri log. 

Abbiamo risolto il problema della scomparsa dei piccoli indici riconfigurando la loro rotazione. Ora gli indici rotano ogni 23 ore, anche se ci sono pochi dati. Questo ha leggermente aumentato il numero di shard (ora sono circa 800), ma dal punto di vista delle prestazioni del cluster è accettabile. 

Di conseguenza, nel cluster ci sono sei nodi "caldi" e solo quattro nodi "tiepidi". Questo provoca un leggero ritardo nelle query su intervalli di tempo ampi, ma un aumento del numero di nodi in futuro risolverà questo problema.

In questa iterazione abbiamo risolto anche il problema dell'assenza di scaling semi-automatico. Per questo abbiamo distribuito un cluster Nomad infrastrutturale, simile a quello già attivo nella nostra produzione. Attualmente, il numero di Logstash non varia automaticamente in base al carico, ma ci arriveremo.

Come abbiamo a CIAN domato terabyte di log

Piani futuri

La configurazione implementata scala magnificamente e attualmente stiamo archiviando 13,3 TB di dati, ovvero tutti i log degli ultimi 4 giorni, necessari per un'analisi rapida degli alert. Parte dei log viene trasformata in metriche, che andiamo a collocare in Graphite. Per facilitare il lavoro degli ingegneri, abbiamo metriche per il cluster infrastrutturale e script per la risoluzione semi-automatica di problemi tipici. Dopo l'aumento del numero di nodi dati, previsto per il prossimo anno, passeremo a un'archiviazione dei dati da 4 a 7 giorni. Questo sarà sufficiente per operare in modo efficace, poiché cerchiamo sempre di analizzare gli incidenti il prima possibile, mentre per indagini a lungo termine sfruttiamo i dati di telemetria. 

Nel ottobre 2019, il traffico di cian.ru è salito a 15,3 milioni di utenti unici al mese. Questo ha rappresentato una seria sfida per la soluzione architetturale di gestione dei log. 

Attualmente ci stiamo preparando ad aggiornare ElasticSearch alla versione 7. Tuttavia, per farlo dovremo aggiornare il mapping di molti indici in ElasticSearch, poiché sono stati migrati dalla versione 5.5 e sono stati dichiarati obsoleti nella versione 6 (nella versione 7 non ci sono). Questo significa che durante il processo di aggiornamento ci sarà sicuramente qualche imprevisto che ci lascerà senza log per un certo periodo. Dalla versione 7, non vediamo l'ora di esplorare Kibana con un'interfaccia migliorata e nuovi filtri. 

Abbiamo raggiunto l'obiettivo principale: abbiamo smesso di perdere log e abbiamo ridotto il tempo di inattività del cluster infrastrutturale da 2-3 crash a settimana a un paio d'ore di manutenzione al mese. Tutto questo lavoro in produzione è quasi impercettibile. Tuttavia, ora possiamo determinare con precisione cosa sta accadendo al nostro servizio, possiamo farlo rapidamente in modalità tranquilla e non preoccuparci di perdere i log. In generale, siamo soddisfatti, felici e ci prepariamo a nuove imprese di cui parleremo in seguito.

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