
VictoriaMetrics — un database scalabile e veloce per la memorizzazione e l'elaborazione di dati sotto forma di serie temporali (una registrazione forma il tempo e un insieme di valori corrispondenti a quel tempo, ad esempio ottenuti attraverso il campionamento periodico dello stato dei sensori o la raccolta di metriche).


Mi chiamo Kolobaev Pavel. DevOps, SRE, LeroyMerlin, tutto come codice – questo è ciò di cui parliamo: di me e degli altri dipendenti di LeroyMerlin.

C'è un cloud basato su OpenStack. Ecco un link a un tech radar.

È costruito su hardware Kubernetes, oltre a tutti i servizi associati a OpenStack e al logging.

Lo schema era questo durante lo sviluppo. Quando abbiamo sviluppato tutto ciò, avevamo un operatore Prometheus che memorizzava i dati all'interno del cluster K8s. Trova automaticamente ciò che deve essere estratto e lo mette a disposizione, per così dire.

Dobbiamo estrarre tutti i dati al di fuori del cluster Kubernetes, perché se succede qualcosa, dobbiamo capire cosa e dove.

La prima soluzione è l'uso della federazione, quando abbiamo un Prometheus esterno e accediamo al cluster Kubernetes tramite il meccanismo di federazione.

Qui ci sono alcuni problemi. Nel nostro caso, i problemi sono iniziati quando avevamo 250.000 metriche, e quando sono aumentate a 400.000 metriche, abbiamo capito che non potevamo continuare a lavorare in questo modo. Abbiamo aumentato il timeout di estrazione a 25 secondi.
Perché abbiamo dovuto farlo? Prometheus inizia a contare il tempo del timeout dall'inizio del recupero. Non importa se i dati continuano a fluire. Se, entro il suddetto intervallo temporale, i dati non sono stati trasferiti e la sessione non viene chiusa tramite http, la sessione è considerata fallita e i dati non vengono inviati a Prometheus.

Tutti conosciamo i grafici che otteniamo quando mancano parte dei dati. I grafici risultano frastagliati e questo non ci soddisfa.

La soluzione successiva è lo sharding basato su due diversi Prometheus tramite lo stesso meccanismo di federazione.
Ad esempio, possiamo semplicemente effettuare lo sharding in base ai nomi. Questo può essere utilizzato, ma abbiamo deciso di andare oltre.

Ora dovremo gestire questi shard in qualche modo. Possiamo utilizzare promxy, che accede all'area di uno shard e moltiplica i dati. Funziona con due shard come se fosse un'unica punto di accesso. Questo può essere implementato tramite promxy, ma è ancora troppo difficile.

La prima opzione è che vogliamo rinunciare al meccanismo di federation, perché è molto lento.
Gli sviluppatori di Prometheus affermano chiaramente: "Ragazzi, usate altre TimescaleDB, perché non supporteremo a lungo la conservazione delle metriche". Non è compito loro. 
Annotiamo su carta che abbiamo comunque bisogno di un'esportazione esterna, per non conservare tutto in un unico posto.

Il secondo inconveniente è il consumo di memoria. Sì, capisco che molti diranno che nel 2020 un paio di gigabyte di memoria sono pochi, ma rimane comunque un problema.
Attualmente abbiamo ambienti dev e prod. In dev ci sono circa 9 gigabyte per 350.000 metriche. In prod, ci sono oltre 14 gigabyte per 780.000 metriche. Inoltre, il retention time è solo di 30 minuti. Questo è un problema. E ora spiegherò perché.

Facciamo un calcolo: con un milione e mezzo di metriche, e ci stiamo avvicinando, in fase di progettazione otteniamo 35-37 gigabyte di memoria. Ma già con 4 milioni di metriche servirebbero circa 90 gigabyte di memoria. Questo è stato calcolato con la formula fornita dagli sviluppatori di Prometheus. Abbiamo analizzato la correlazione e capito che non vogliamo pagare un paio di milioni per un server solo per il monitoraggio.
Non solo aumenterà il numero di macchine, ma monitoriamo anche le macchine virtuali stesse. Quindi, più macchine virtuali ci sono, più metriche di vario tipo avremo. Ci sarà una crescita specifica del nostro cluster in termini di metriche.

La situazione con lo spazio su disco non è così drammatica, ma ci sarebbe la possibilità di migliorare. In 15 giorni abbiamo accumulato per un totale di 120 gigabyte, di cui 100 sono dati compressi e 20 non compressi, ma si desidera sempre avere meno.

Di conseguenza, aggiungiamo un altro punto: il grande consumo di risorse, che è meglio ottimizzare, perché non vogliamo che il nostro cluster di monitoraggio consumi più risorse del cluster che gestisce OpenStack.

C'è un altro svantaggio di Prometheus che abbiamo identificato: esiste un qualche tipo di limitazione della memoria. Con Prometheus la situazione è molto peggiore, perché non ha proprio impostazioni di questo tipo. Usare limiti in Docker non è un'opzione. Se per caso il vostro RAF va giù e ci sono 20-30 gigabyte, il ripristino sarà molto lungo.

Questa è un'altra ragione per cui Prometheus non fa per noi, cioè non è possibile limitare il consumo di memoria.

Potremmo implementare un sistema di questo tipo. Questo schema è necessario per organizzare un cluster HA. Vogliamo che le nostre metriche siano sempre e ovunque accessibili, anche in caso di guasto del server che le memorizza. Pertanto, dovremo costruire uno schema di questo tipo.
Questo schema indica che avremo ridondanza dei shard e, di conseguenza, anche ridondanza dei costi delle risorse consumate. Può essere quasi scalato orizzontalmente, ma il consumo delle risorse sarà comunque elevato.

Gli svantaggi, in ordine, come li abbiamo elencati:
- È necessaria l'esportazione delle metriche verso l'esterno.
- Elevato consumo di risorse.
- Non è possibile limitare il consumo di memoria.
- Implementazione complessa e ad alta intensità di risorse per l'HA.

Abbiamo deciso di allontanarci da Prometheus come sistema di archiviazione.
Abbiamo anche identificato ulteriori requisiti necessari, cioè:
- Supporto per promql, poiché è già stato scritto molto per Prometheus: query, allerta.
- E poi abbiamo Grafana, che è stata anch'essa sviluppata per Prometheus come backend. Non vogliamo riscrivere i dashboard.
- Vogliamo costruire una buona architettura HA.
- Vogliamo ridurre il consumo di qualsiasi risorsa.
- C'è ancora un piccolo dettaglio. Non possiamo utilizzare sistemi cloud di raccolta metriche. Non sappiamo cosa andrà a finire in queste metriche per ora. E poiché potrebbe esserci di tutto, dobbiamo limitarci all'hosting locale.

La scelta non era ampia. Abbiamo raccolto tutto ciò di cui avevamo esperienza. Abbiamo guardato la pagina di Prometheus nella sezione integrazioni, letto molti articoli, e visto cosa c'era in generale. E per noi abbiamo scelto VictoriaMetrics come sostituto di Prometheus.
Perché?
- Supporta promql.
- Ha un'architettura modulare.
- Non richiede modifiche a Grafana.
- E cosa più importante, possiamo fornire un archivio metriche all'interno della nostra azienda come servizio, quindi stiamo già considerando dei limiti, affinché gli utenti possano utilizzare tutte le risorse del cluster in modo limitato, poiché c'è la possibilità che sia multitenancy.

Facciamo il primo confronto. Prendiamo lo stesso Prometheus all'interno del cluster, a cui accede un Prometheus esterno. Aggiungiamo VictoriaMetrics tramite remoteWrite.

Voglio precisare subito che qui abbiamo notato un leggero aumento nel consumo di CPU da parte di VictoriaMetrics. Nella wiki di VictoriaMetrics sono indicati i parametri più adatti. Li abbiamo verificati e hanno ridotto notevolmente il consumo di CPU.
Nel nostro caso, il consumo di memoria di Prometheus, che si trova nel cluster Kubernetes, è aumentato solo leggermente.

Confrontiamo due data source con gli stessi dati. In Prometheus vediamo tutti gli stessi dati mancanti. In VictoriaMetrics, invece, tutto è a posto.

Risultati dei test sullo spazio disco. Abbiamo ottenuto 120 gigabyte complessivi in Prometheus. In VictoriaMetrics riceviamo già 4 gigabyte al giorno. Lì c'è un meccanismo un po' diverso rispetto a quello a cui siamo abituati in Prometheus. In altre parole, i dati vengono già compressi bene in un giorno, in mezz'ora. Già ben compressi in un giorno, in mezz'ora, anche se poi i dati saranno ancora fusi. Alla fine, abbiamo risparmiato spazio su disco.

Inoltre, risparmiamo sulle risorse di memoria. Durante i test, abbiamo eseguito Prometheus su una macchina virtuale con 8 core e 24 gigabyte. Prometheus consuma praticamente tutto. È crollato a causa di OOM Killer. Nel frattempo, erano in ingresso solo 900.000 metriche attive. Questo corrisponde a circa 25.000-27.000 metriche al secondo.
VictoriaMetrics è stata avviata su una macchina virtuale a due core con 8 gigabyte di RAM. Siamo riusciti a far funzionare bene VictoriaMetrics, ottimizzando alcune cose su una macchina da 8 gigabyte. Alla fine, ci siamo mantenuti sotto i 7 gigabyte. Inoltre, abbiamo ottenuto una velocità di erogazione dei contenuti, ovvero delle metriche, anche superiore a quella di Prometheus.

Le prestazioni della CPU sono migliorate notevolmente rispetto a Prometheus. Qui Prometheus consuma 2,5 core, mentre VictoriaMetrics solo 0,25 core. All'inizio, consuma 0,5 core. Man mano che l'uso cresce, arriva a un core, ma questo è estremamente raro.

Nel nostro caso, la scelta è caduta su VictoriaMetrics per motivi evidenti: volevamo risparmiare e ci siamo riusciti.

Eliminiamo subito due punti: l'esportazione delle metriche e l'elevato consumo di risorse. Ci rimangono da risolvere due punti che abbiamo lasciato in sospeso.

Qui chiarisco subito, consideriamo VictoriaMetrics come un sistema di archiviazione delle metriche. Ma dato che probabilmente forniremo VictoriaMetrics come archiviazione per tutto Leroy, dobbiamo limitare chi utilizzerà questo cluster, affinché non ci crei problemi.
C'è una fantastica opzione che permette di limitare per tempo, per volume di dati e per tempo di esecuzione.
C'è anche un'eccellente opzione che consente di limitare il consumo di memoria, in modo da poter trovare quel giusto equilibrio che ci permette di avere una velocità operativa adeguata e un consumo di risorse ragionevole.

Un altro punto negativo, cioè possiamo depennare questo punto – non è possibile limitare il consumo di memoria.

Nelle prime iterazioni abbiamo testato VictoriaMetrics Single Node. Ora passiamo alla versione Cluster di VictoriaMetrics.
Qui abbiamo libertà in merito alla distribuzione dei vari servizi in VictoriaMetrics a seconda delle piattaforme su cui gireranno e delle risorse che consumeranno. È una soluzione molto flessibile e comoda. L'abbiamo utilizzata direttamente.

I componenti principali della versione Cluster di VictoriaMetrics sono vmstorage. Possono essere in un numero N. Nel nostro caso, attualmente sono 2.
C'è vminsert. È un server proxy che ci consente di: implementare lo sharding tra tutti gli storage di cui lo abbiamo informato, e consente anche la replica, quindi avrete sia sharding che replica.
Vminsert supporta i protocolli OpenTSDB, Graphite, InfluxDB e remoteWrite di Prometheus.

C'è anche vmselect. Il suo compito principale è quello di interagire con vmstorage, recuperare i dati, deduplicarli e fornirli al cliente.

C'è una fantastica funzionalità chiamata vmagent. Ci piace molto. Permette di configurarsi esattamente come Prometheus e di funzionare allo stesso modo. Cioè, raccoglie metriche da entità e servizi diversi e le invia a vminsert. Dopodiché, tutto dipende da voi.

Un altro servizio straordinario è vmalert, che consente di utilizzare VictoriaMetrics come backend, ricevere dati da vminsert e inviarli a vmselect per l'elaborazione. Si occupa degli alert e delle regole. Nel caso degli alert, riceviamo l'alert tramite alertmanager.

Esiste il componente wmauth. Potremmo utilizzarlo, o forse no (non siamo ancora certi) come sistema di autorizzazione per la versione multitenancy dei cluster. Supporta remoteWrite per Prometheus e può autorizzare in base all'URL, più precisamente alla seconda sua parte, dove è possibile o meno scrivere.

Ci sono anche vmbackup e vmrestore. Si tratta, in sostanza, del ripristino e del backup di tutti i dati. Supporta S3, GCS e file.

La prima iterazione del nostro cluster è stata realizzata durante il lockdown. In quel momento non c'era una replica, quindi la nostra iterazione consisteva in due cluster diversi e indipendenti, dai quali ottenevamo dati tramite remoteWrite.

Qui va detto che, quando siamo passati da VictoriaMetrics Single Node a VictoriaMetrics Cluster Version, siamo rimasti comunque sugli stessi consumi di risorse, cioè principalmente la memoria. In questo modo si sono distribuiti i nostri dati, cioè il consumo delle risorse.

Qui è stata già aggiunta una replica. Abbiamo unito tutto in un cluster relativamente grande. Tutti i dati sono sia shardati che replicati.
L'intero cluster ha N punti di accesso, ovvero Prometheus può aggiungere dati attraverso HAPROXY. Ecco il nostro punto di accesso. Da questo punto di accesso si può accedere con Grafana.

Nel nostro caso, HAPROXY è l'unica porta che gestisce select, insert e altri servizi all'interno di questo cluster. Non abbiamo potuto utilizzare un solo indirizzo, abbiamo dovuto creare diversi punti di accesso perché le macchine virtuali su cui gira il cluster di VictoriaMetrics si trovano in diverse zone di un unico provider di servizi cloud, ovvero all'esterno del nostro cloud.

Abbiamo un sistema di alerting. Lo utilizziamo. Utilizziamo alertmanager di Prometheus. Come canale di consegna degli alert utilizziamo Opsgenie e Telegram. Su Telegram riceviamo notifiche da dev, forse qualcosa da prod, ma soprattutto informazioni statistiche utili agli ingegneri. Opsgenie invece gestisce gli alert critici. Questa è gestione delle emergenze.

La domanda eterna: «Chi monitora il monitoraggio?». In questo caso, il monitoraggio è monitorato dal monitoraggio stesso, poiché utilizziamo vmagent su ogni nodo. E poiché i nostri nodi sono distribuiti in diversi data center dello stesso fornitore, abbiamo un canale separato per ogni data center; sono indipendenti e anche se si verifica un split brain, riceveremo comunque degli avvisi. Sì, ce ne saranno di più, ma è meglio ricevere più avvisi che nessuno.

Concludiamo la nostra lista con l'implementazione dell'HA.

Vorrei anche sottolineare l'esperienza di interazione con la community di VictoriaMetrics. Si è rivelata molto positiva. I ragazzi sono disponibili. Cercano di comprendere ogni caso che viene presentato.
Ho aperto issue su GitHub. Sono state risolte molto rapidamente. Ci sono ancora un paio di issue che non sono completamente chiuse, ma già dal codice vedo che il lavoro in questa direzione sta procedendo.
Il principale problema durante le iterazioni per me era che se spegnevo un nodo, nei primi 30 secondi vminsert non riusciva a capire che il backend non esisteva. Ora questo è già risolto. In un secondo o due, i dati vengono già recuperati da tutti gli altri nodi, e la richiesta smette di aspettare quel nodo assente.

Volevamo in un certo momento un operatore di VictoriaMetrics. Finalmente è arrivato. Stiamo attualmente costruendo un'interfaccia sopra l'operatore di VictoriaMetrics per integrare tutte le regole di pre-calcolo e così via. Prometheus, poiché utilizziamo attivamente le regole associate all'operatore Prometheus.
Ci sono proposte per migliorare l'implementazione del cluster. Le ho esposte sopra.
Inoltre, c'è una forte richiesta per il downsampling. Nel nostro caso, il downsampling è necessario esclusivamente per visualizzare le tendenze. In parole povere, mi basterebbe una sola metrica per tutta la giornata. Queste tendenze sono necessarie per un anno, tre, cinque, dieci anni. E un solo valore della metrica è più che sufficiente.

- Abbiamo conosciuto il dolore, come alcuni dei nostri colleghi, nell'utilizzare Prometheus.
- Abbiamo scelto di utilizzare VictoriaMetrics.
- Si scala piuttosto bene sia verticalmente che orizzontalmente.
- Possiamo distribuire diversi componenti su un numero variabile di nodi nel cluster, limitandoli in base al consumo di memoria, aumentando la memoria, ecc.
Utilizzeremo VictoriaMetrics, perché ci è piaciuta molto. Ecco com'era e come è diventata.

Alcuni codici qr per la chat di VictoriaMetrics, i miei contatti, il tech radar di LeroyMerlin.
Fonte: habr.com
