Archiviazione delle metriche: come siamo passati da Graphite+Whisper a Graphite+ClickHouse

Ciao a tutti! Nel mio un articolo precedente Ho scritto sull'organizzazione di un sistema modulare di monitoraggio per architetture a microservizi. Nulla resta fermo, il nostro progetto cresce costantemente e anche il numero di metriche memorizzate aumenta. Come abbiamo organizzato la transizione da Graphite+Whisper a Graphite+ClickHouse in condizioni di carico elevato, le aspettative al riguardo e i risultati della migrazione leggete sotto.

Archiviazione delle metriche: come siamo passati da Graphite+Whisper a Graphite+ClickHouse

Prima di raccontarvi come abbiamo organizzato il passaggio dalla memorizzazione delle metriche in Graphite+Whisper a Graphite+ClickHouse, vorrei fornire informazioni sulle motivazioni che ci hanno portato a prendere questa decisione e sui vari limiti di Whisper con cui abbiamo convissuto per un lungo periodo.

Problemi di Graphite+Whisper

1. Alto carico sul sistema disco

Al momento della transizione, ricevevamo circa 1,5 milioni di metriche al minuto. Con un tale flusso, l'utilizzo del disco sui server era intorno al ~30%. In generale, era abbastanza accettabile: tutto funzionava in modo stabile, si scriveva velocemente, si leggeva velocemente... Fino a quando uno dei team di sviluppo non ha lanciato una nuova funzionalità e ha iniziato a inviarci 10 milioni di metriche al minuto. Proprio in quel momento, il sistema disco è andato in crisi e abbiamo registrato un utilizzo del 100%. Siamo riusciti a risolvere rapidamente il problema, ma è rimasta una certa frustrazione.

2. Mancanza di replica e consistenza

Probabilmente, come tutti coloro che utilizzano/hanno utilizzato Graphite+Whisper, abbiamo inviato lo stesso flusso di metriche su più server Graphite per garantire la resilienza. Non ci sono stati particolari problemi fino a quando uno dei server non è andato offline per qualche motivo. A volte riuscivamo a riavviare il server guasto abbastanza rapidamente e carbon-c-relay riusciva a inviarvi le metriche dal suo cache, altre volte no. In quel caso, c'era un buco nelle metriche che riempivamo con rsync. La procedura era piuttosto lunga. Ci ha salvato solo il fatto che tali eventi erano molto rari. Inoltre, a intervalli regolari, selezionavamo un insieme casuale di metriche e le confrontavamo con altre simili sui nodi vicini del cluster. In circa il 5% dei casi, alcuni valori differivano, il che non era molto incoraggiante.

3. Grande spazio occupato

Poiché scriviamo in Graphite non solo metriche infrastrutturali, ma anche metriche aziendali (e ora anche metriche da Kubernetes), ci troviamo piuttosto spesso nella situazione in cui la metrica contiene solo alcuni valori, mentre il file .wsp viene creato tenendo conto dell'intero periodo di retention e occupa uno spazio preassegnato, che per noi era pari a ~2MB. Il problema è ulteriormente aggravato dal fatto che nel tempo questi file aumentano notevolmente, e nella costruzione di report su di essi si perdono molte risorse e molto tempo per leggere i punti vuoti.

Vorrei subito sottolineare che è possibile affrontare i problemi descritti sopra con vari metodi e con diversi gradi di efficacia, ma più dati iniziano ad arrivare, più questi problemi si acuiscono.

Tenendo presente tutto quanto sopra (incluso quanto precedentemente sul CommunityHelpWiki (sullo stesso dominio), e anche la costante crescita del numero di metriche ricevute, il desiderio di ridurre a un intervallo di archiviazione di 30 secondi tutte le metriche (se necessario, fino a 10 secondi), abbiamo deciso di provare Graphite+ClickHouse come alternativa promettente a Whisper.

Graphite+ClickHouse. Aspettative

Dopo aver partecipato a diversi meetup con i ragazzi di Yandex, letto alcuni articoli su Habré, esaminato la documentazione e trovato componenti ragionevoli per collegare ClickHouse a Graphite, abbiamo deciso di agire!

Volevamo ottenere quanto segue:

  • ridurre l'utilizzo del sistema di archiviazione da 30% a 5%;
  • ridurre lo spazio occupato da 1TB a 100GB;
  • avere la possibilità di ricevere 100 milioni di metriche al minuto sul server;
  • replicazione dei dati e tolleranza ai guasti pronta all'uso;
  • non passare un anno su questo progetto e completare la transizione in un tempo ragionevole;
  • cambiare senza downtime.

Abbastanza ambizioso, vero?

Graphite+ClickHouse. Componenti

Per ottenere i dati tramite il protocollo Graphite e successivamente scriverli in ClickHouse, è stato scelto carbon-clickhouse (golang).

Come database per la memorizzazione delle serie temporali è stata scelta l'ultima versione stabile di ClickHouse, la 1.1.54253. Durante l'utilizzo vi erano problemi: i log erano pieni di errori e non era chiaro cosa farne. In una discussione con Roman Lomonosov (autore di carbon-clickhouse, graphite-clickhouse e molto altro) è stata scelta una versione più vecchia la 1.1.54236.Gli errori sono scomparsi — tutto ha iniziato a funzionare alla grande.

Per la lettura dei dati da ClickHouse è stato scelto graphite-slickhouse (golang). Come interfaccia API per Graphite — carbonapi (golang). Per organizzare la replicazione tra le tabelle ClickHouse è stato utilizzato zookeeper. Per il routing delle metriche abbiamo mantenuto il nostro amato carbon-c-relay (C) (vedi articolo precedente).

Graphite+ClickHouse. Struttura delle tabelle

“graphite” — un database creato da noi per le tabelle di monitoraggio.

“graphite.metrics” — tabella con motore ReplicatedReplacingMergeTree (replicato ReplacingMergeTree). In questa tabella vengono memorizzati i nomi delle metriche e i percorsi a cui si riferiscono.

CREATE TABLE graphite.metrics ( Date Date, Level UInt32, Path String, Deleted UInt8, Version UInt32 ) ENGINE = ReplicatedReplacingMergeTree('\/clickhouse\/tables\/replicator\/graphite.metrics', ‘r1’, Date, (Level, Path), 8192, Version);

“graphite.data” — tabella con motore ReplicatedGraphiteMergeTree (replicato GraphiteMergeTree). In questa tabella vengono memorizzati i valori delle metriche.

CREATE TABLE graphite.data ( Path String, Value Float64, Time UInt32, Date Date, Timestamp UInt32 ) ENGINE = ReplicatedGraphiteMergeTree('\/clickhouse\/tables\/replicator\/graphite.data', 'r1', Date, (Path, Time), 8192, 'graphite_rollup')

“graphite.date_metrics” — tabella popolare in base a una condizione, con motore ReplicatedReplacingMergeTree. In questa tabella vengono registrati i nomi di tutte le metriche che si sono presentate durante il giorno. Le motivazioni per la creazione sono descritte nella sezione «Problemi» alla fine di questo articolo.

CREATE MATERIALIZED VIEW graphite.date_metrics ( Path String,  Level UInt32,  Date Date) ENGINE = ReplicatedReplacingMergeTree('\/clickhouse\/tables\/replicator\/graphite.date_metrics', 'r1', Date, (Level, Path, Date), 8192) AS SELECT toUInt32(length(splitByChar('.', Path))) AS Level, Date, Path FROM graphite.data

“graphite.data_stat” — tabella popolare in base a una condizione, con motore ReplicatedAggregatingMergeTree (replicato AggregatingMergeTree). In questa tabella viene registrato il numero di metriche in entrata, suddiviso fino al livello di profondità 4.

CREATE MATERIALIZED VIEW graphite.data_stat ( Date Date,  Prefix String,  Timestamp UInt32,  Count AggregateFunction(count)) ENGINE = ReplicatedAggregatingMergeTree('\/clickhouse\/tables\/replicator\/graphite.data_stat', 'r1', Date, (Timestamp, Prefix), 8192) AS SELECT toStartOfMonth(now()) AS Date, replaceRegexpOne(Path, '^([^.]+.[^.]+.[^.]+).*$', '1') AS Prefix, toUInt32(toStartOfMinute(toDateTime(Timestamp))) AS Timestamp, countState() AS Count FROM graphite.data  GROUP BY Timestamp, Prefix

Graphite+ClickHouse. Schema di interazione dei componenti

Archiviazione delle metriche: come siamo passati da Graphite+Whisper a Graphite+ClickHouse

Graphite+ClickHouse. Migrazione dei dati

Come ricordiamo dalle aspettative per questo progetto, il passaggio a ClickHouse dovrebbe avvenire senza tempi di inattività, quindi dovevamo trovare un modo per commutare il nostro sistema di monitoraggio sul nuovo archivio nel modo più trasparente possibile per i nostri utenti.
Abbiamo fatto questo.

  • In carbon-c-relay abbiamo aggiunto una regola per inviare un flusso aggiuntivo di metriche a carbon-clickhouse da uno dei server partecipanti alla replicazione delle tabelle ClickHouse.

  • Abbiamo scritto un piccolo script in python, che utilizzando la libreria whisper-dump ha estratto tutti i file .wsp dal nostro archivio e ha inviato questi dati al carbon-clickhouse descritto sopra in 24 flussi. Il numero di valori metrici ricevuti dal carbon-clickhouse ha raggiunto i 125 milioni/min., e ClickHouse non ha nemmeno mostrato segni di affaticamento.

  • Abbiamo creato una DataSource separata in Grafana per il debug delle funzioni utilizzate nei dashboard esistenti. Abbiamo identificato un elenco di funzioni che abbiamo utilizzato, ma che non erano implementate in carbonapi. Abbiamo completato queste funzioni e inviato i PR agli autori di carbonapi (un grazie particolare a loro).

  • Per commutare il carico di lettura, nelle impostazioni dei bilanciatori abbiamo cambiato gli endpoint da graphite-api (interfaccia API per Graphite+Whisper) a carbonapi.

Graphite+ClickHouse. Risultati

  • ridotto l'utilizzo del sistema di archiviazione del disco dal 30% all'1%;

    Archiviazione delle metriche: come siamo passati da Graphite+Whisper a Graphite+ClickHouse

  • ridotto lo spazio occupato da 1 TB a 300 GB;
  • abbiamo la possibilità di accettare 125 milioni di metriche al minuto sul server (picchi durante la migrazione);
  • abbiamo trasferito tutte le metriche a un intervallo di archiviazione di trenta secondi;
  • abbiamo ottenuto la replica dei dati e l'immunità agli errori;
  • siamo passati senza downtime;
  • abbiamo impiegato circa 7 settimane.

Graphite+ClickHouse. Problemi

Nel nostro caso non siamo stati esenti da insidie. Ecco cosa abbiamo affrontato dopo il passaggio.

  1. ClickHouse non sempre rilegge le configurazioni al volo, a volte è necessario riavviarlo. Ad esempio, nel caso della descrizione del cluster zookeeper nel file di configurazione di ClickHouse, questa non è stata applicata fino al riavvio di clickhouse-server.
  2. Le grandi query non passavano a ClickHouse, quindi nel nostro caso in graphite-clickhouse la stringa di connessione a ClickHouse appare così:
    url = "http://localhost:8123/?max_query_size=268435456&max_ast_elements=1000000"
  3. In ClickHouse piuttosto spesso vengono rilasciate nuove versioni stabili, che possono riservare sorprese: fate attenzione.
  4. I contenitori creati dinamicamente in Kubernetes inviano un grande numero di metriche con un periodo di vita breve e casuale. Ci sono poche istanze di tali metriche e non ci sono problemi di spazio. Tuttavia, durante la costruzione di query, ClickHouse recupera un'enorme quantità di queste metriche dalla tabella 'metrics'. Nella maggior parte dei casi, circa il 90%, i dati per esse sono assenti per un intervallo di 24 ore. Il tempo speso per cercare questi dati nella tabella 'data' si accumula e alla fine arriva a un timeout. Per risolvere questo problema, abbiamo iniziato a mantenere una vista separata con informazioni sulle metriche che sono state riscontrate durante il giorno. In questo modo, durante la generazione di report (grafici) sui contenitori creati dinamicamente, interroghiamo solo quelle metriche che sono state riscontrate all'interno dell'intervallo specificato, e non per tutto il tempo, il che ha notevolmente accelerato la generazione di report. Per la soluzione sopra descritta è stato raccolto graphite-clickhouse (fork), che include l'implementazione del lavoro con la tabella date_metrics.

Graphite+ClickHouse. Tag

Dalla versione 1.1.0 Graphite ha ufficialmente supportato i tag. E stiamo attivamente pensando a cosa e come fare per supportare questa iniziativa nello stack graphite+clickhouse.

Graphite+ClickHouse. Rilevatore di anomalie

Sulla base dell'infrastruttura descritta sopra, abbiamo implementato un prototipo di rilevatore di anomalie, e funziona! Ma ne parleremo nel prossimo articolo.

Iscrivetevi, cliccate sulla freccia in su e siate felici!

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