Come abbiamo gestito i terabyte di log in CIAN

Come abbiamo gestito i terabyte di log in CIAN

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 nostri articoli precedenti ci hanno chiesto di raccontare come raccogliamo 4 TB di log al giorno e cosa ne facciamo. Sì, abbiamo molti log, e per il loro trattamento è stato creato un cluster infrastrutturale dedicato, che ci permette di risolvere i problemi in modo tempestivo. In questo articolo parlerò di come abbiamo adattato questo sistema nel corso di un anno per gestire un flusso di dati in costante crescita.

Da dove siamo partiti

Come abbiamo gestito i terabyte di log in CIAN

Negli ultimi anni, il carico su cian.ru è cresciuto rapidamente, e nel terzo trimestre del 2018 il sito ha raggiunto 11,2 milioni di utenti unici al mese. In quel periodo, nei momenti critici, abbiamo perso fino al 40% dei log, il che ci impediva di gestire rapidamente gli incidenti e ci faceva perdere molto tempo e risorse per risolverli. Spesso non riuscivamo nemmeno a trovare la causa del problema, il che si ripresentava dopo un certo periodo. Era un incubo, e bisognava fare qualcosa.

All'epoca, per la conservazione dei log, utilizzavamo un cluster di 10 nodi dati con ElasticSearch versione 5.5.2 con impostazioni standard per gli indici. È stato implementato più di un anno fa come una soluzione popolare e accessibile: in quel momento, il flusso di log non era così elevato, quindi non c'era motivo di inventare configurazioni personalizzate. 

La gestione dei log in entrata era garantita da Logstash su porte diverse su cinque coordinatori ElasticSearch. Un indice, indipendentemente dalle dimensioni, era composto da cinque shard. Era organizzata una rotazione oraria e giornaliera, risultando in circa 100 nuovi shard nel cluster ogni ora. Finché non c'era un numero eccessivo di log, il cluster gestiva la situazione e nessuno prestava attenzione alle sue impostazioni. 

Problemi di rapida crescita

Il volume dei log generati cresceva rapidamente, poiché si sovrapponevano due processi. Da una parte, il numero di utenti del servizio aumentava. Dall'altra, iniziavamo a migrare attivamente verso un'architettura a microservizi, suddividendo i nostri vecchi monoliti in C# e Python. 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 un punto in cui il cluster è diventato praticamente ingestibile. Quando i log hanno iniziato a fluire a una velocità di 20.000 messaggi al secondo, la frequente rotazione inutile ha aumentato il numero di shard a 6.000, e su una singola nodo gravavano più di 600 shard. 

Questo ha portato a problemi con l'allocazione della memoria. Quando un nodo falliva, iniziava la migrazione simultanea di tutti gli shard, raddoppiando il traffico e sovraccaricando gli altri nodi, rendendo praticamente impossibile la scrittura di dati nel cluster. In quel periodo siamo rimasti privi di log. E con il problema di server perdevamo 1/10 del cluster in generale. A complicare le cose contribuiva l'elevato numero di indici di piccole dimensioni.

Senza i log, non comprendevamo le cause degli incidenti e avremmo potuto ripetere gli stessi errori in futuro, cosa inaccettabile per la nostra squadra, poiché tutti i nostri processi sono progettati per evitare di ripetere gli stessi problemi. Per questo avevamo bisogno di un completo volume di log e di una loro consegna quasi in tempo reale, poiché il team di ingegneri di guardia monitorava non solo gli avvisi dalle metriche, ma anche dai log. Per dare un’idea dell’entità del problema, all'epoca il volume totale dei log era di circa 2 TB al giorno. 

Abbiamo fissato l'obiettivo di escludere completamente la perdita di log e di ridurre il tempo di consegna al cluster ELK a un massimo di 15 minuti in caso di imprevisti (su questo dato ci siamo basati in seguito come KPI interno).

Nuovo meccanismo di rotazione e nodi hot-warm

Come abbiamo gestito i terabyte di log in CIAN

Abbiamo iniziato la trasformazione del cluster aggiornando la versione di ElasticSearch da 5.5.2 a 6.4.3. Il nostro cluster della versione 5 si è nuovamente bloccato, e abbiamo deciso di spegnerlo e aggiornare completamente — tanto i log non ci sono. Quindi, questo passaggio lo abbiamo completato in poche ore.

La trasformazione più significativa in questa fase è stata l'implementazione di tre nodi con un coordinatore come buffer intermedio di Apache Kafka. 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", dislocati in diverse rack nel data center. Su di essi abbiamo reindirizzato i log che non potevano essere persi in nessun caso — nginx, e anche i log di errore 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 in base alla dimensione dell'indice fosse 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 doveva scattare la rotazione. In questo modo abbiamo raggiunto una dimensione ottimale del shard — non oltre 50 GB. 

Ottimizzazione del cluster

Come abbiamo gestito i terabyte di log in CIAN

Tuttavia, non siamo riusciti a eliminare completamente i problemi. Sfortunatamente, continuavano a comparire piccoli indici: non raggiungevano il volume stabilito, non venivano ruotati e venivano eliminati da una pulizia globale degli indici più vecchi di tre giorni, poiché abbiamo rimosso la rotazione per data. Questo portava a perdite di dati perché l'indice scompariva completamente dal cluster e il tentativo di scrittura in un indice inesistente rompeva la logica del curator che usavamo per la gestione. L'alias per la scrittura veniva trasformato 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 un alias di rollover si verificava 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 risoluzione di questo problema a un'iterazione successiva e ci siamo occupati di un altro aspetto: siamo passati alla logica pull di Logstash, che si occupa dell'elaborazione dei log in ingresso (rimozione delle informazioni superflue e arricchimento). L'abbiamo posizionato in un container Docker, avviato tramite docker-compose, e abbiamo collocato anche logstash-exporter, che invia le metriche a Prometheus per monitorare in tempo reale il flusso dei log. In questo modo abbiamo potuto modificare agevolmente il numero di istanze di Logstash responsabili dell'elaborazione di ciascun tipo di log.

Mentre perfezionavamo il cluster, il traffico su cian.ru è aumentato fino a 12,8 milioni di utenti unici al mese. Di conseguenza, le nostre trasformazioni non riuscivano a tenere il passo con i cambiamenti in produzione, e ci siamo trovati di fronte al problema delle nodi 'caldi' che non riuscivano a gestire il carico, rallentando l'intera consegna dei log. I dati 'caldi' venivano ricevuti senza interruzioni, ma per la consegna degli altri era necessario intervenire manualmente e effettuare un rollover per distribuire uniformemente gli indici. 

Tuttavia, la scalabilità e la modifica delle impostazioni degli istanze di logstash nel cluster sono state 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 attraverso tutti i server e fare docker-compose up -d ovunque).

Ridefinizione dei log

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

Come abbiamo gestito i terabyte di log in CIAN

La prossima iterazione è iniziata con l'aggiornamento dell'hardware. Da cinque coordinatori siamo passati a tre, abbiamo sostituito i nodi dei dati e abbiamo guadagnato sia in costi che in capacità di archiviazione. Per i nodi utilizziamo due configurazioni: 

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

In questa iterazione abbiamo trasferito l'indice con i log di accesso dei microservizi, che occupa quanto i log dei frontend nginx, nel secondo gruppo di tre nodi "caldi". I dati sui nodi "caldi" ora vengono conservati per 20 ore e poi trasferiti ai nodi "temperati" insieme agli altri log. 

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

Di conseguenza, nel cluster abbiamo sei nodi 'caldi' e solo quattro 'tiepidì. Questo provoca un leggero ritardo nelle richieste 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 della mancanza di scalabilità semi-automatica. Per questo motivo, abbiamo implementato un cluster infrastrutturale Nomad, simile a quello già attivo nel nostro ambiente di produzione. Al momento, il numero di Logstash non cambia automaticamente in base al carico, ma arriveremo anche a questo.

Come abbiamo gestito i terabyte di log in CIAN

Piani per il futuro

La configurazione implementata scala in maniera eccellente e ora stiamo memorizzando 13,3 TB di dati — tutti i log di 4 giorni, necessari per l'analisi rapida degli alert. Parte dei log viene trasformata in metriche che raccogliamo in Graphite. Per facilitare il lavoro degli ingegneri, abbiamo metriche per il cluster infrastrutturale e script per la riparazione semi-automatica di problemi tipici. Dopo l'aumento previsto del numero di nodi di dati per il prossimo anno, passeremo da 4 a 7 giorni di memorizzazione dei dati. Questo sarà sufficiente per lavorare operativamente, poiché cerchiamo sempre di investigare gli incidenti il prima possibile, mentre per le indagini a lungo termine utilizziamo i dati di telemetria. 

Nel mese di ottobre 2019, il traffico di cian.ru è aumentato a 15,3 milioni di utenti unici al mese. Questo è stato un serio test della soluzione architetturale per la consegna dei log. 

Attualmente ci stiamo preparando per aggiornare ElasticSearch alla versione 7. Tuttavia, questo richiederà l'aggiornamento del 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 affatto). Ciò significa che nel processo di aggiornamento ci sarà sicuramente qualche imprevisto che ci lascerà senza log per un certo periodo. Dalla versione 7, attendiamo con maggior ansia Kibana con un'interfaccia migliorata e nuovi filtri. 

Abbiamo raggiunto l'obiettivo principale: abbiamo smesso di perdere log e ridotto il tempo di inattività del cluster infrastrutturale da 2-3 guasti a settimana a un paio d'ore di manutenzione al mese. Tutto questo lavoro in produzione è quasi impercettibile. Tuttavia, ora possiamo determinare esattamente cosa sta accadendo con il nostro servizio, possiamo farlo rapidamente in modo tranquillo e senza preoccuparci di perdere i log. Insomma, siamo soddisfatti, felici e ci stiamo preparando per 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