
VictoriaMetrics — szybka i skalowalna baza danych do przechowywania i przetwarzania danych w formie szeregów czasowych (zapis tworzy czas oraz zbiór odpowiadających mu wartości, na przykład uzyskanych przez okresowe zapytanie stanu czujników lub zbieranie metryk).


Nazywam się Pawel Kolobaev. DevOps, SRE, LeroyMerlin, wszystko jako kod — to wszystko o nas: o mnie i o innych pracownikach LeroyMerlin.

Mamy chmurę opartą na OpenStack. Jest tam niewielki link do radarów technologicznych.

Zbudowane jest na bazie sprzętu Kubernetes oraz wszystkich towarzyszących usług OpenStack i logowania.

Schemat wyglądał tak podczas rozwoju. Kiedy to wszystko tworzyliśmy, mieliśmy operatora Prometheus, który przechowywał dane wewnątrz samego klastra K8s. Automatycznie znajduje to, co trzeba zeskrobić i składa sobie pod nogi, mówiąc w przenośni.

Wszystkie dane musimy przenieść poza klaster Kubernetes, ponieważ jeśli coś się wydarzy, musimy wiedzieć, co i gdzie jest.

Pierwsze rozwiązanie — używamy federacji, kiedy mamy zewnętrzny serwer Prometheus, kiedy wchodzimy w klaster Kubernetes przez mechanizm federacji.

Ale pojawiają się małe problemy. W naszym przypadku problemy zaczęły się, gdy mieliśmy 250 000 metryk, a kiedy stało się 400 000 metryk, zrozumieliśmy, że nie możemy tak działać. Zwiększyliśmy scrape_timeout do 25 sekund.
Dlaczego musieliśmy to zrobić? Prometheus zaczyna odliczać czas wygaśnięcia od chwili pobrania danych. I nieistotne, że dane wciąż płyną. Jeśli w tym określonym czasie dane nie zostały przesłane, a sesja nie zostanie zamknięta przez http, to uważa się, że sesja jest nieudana i dane nie trafiają do samego Prometheusa.

Wszystkie znajome wykresy, które otrzymujemy, gdy część danych brakuje. Wykresy są porwane i nam to nie odpowiada.

Następną opcją jest szardowanie w oparciu o dwa różne serwery Prometheus przez ten sam mechanizm federacji.
Na przykład po prostu wziąć i rozdzielić po nazwie. To można również wykorzystać, ale postanowiliśmy iść dalej.

Będziemy teraz musieli jakoś przetwarzać te shard'y. Można wziąć promxy, który wejdzie w obszar sharda i zduplikuje dane. Działa z dwoma shardami jak z jednolitym punktem wejścia. Można to zrealizować przez promxy, ale jak na razie jest zbyt skomplikowane.

Pierwsza opcja – chcemy zrezygnować z mechanizmu federacji, ponieważ jest bardzo wolny.
Deweloperzy Prometheus wyraźnie mówią: „Ludzie, używajcie innych TimescaleDB, ponieważ nie będziemy długo wspierać przechowywania metryk”. To nie jest ich zadanie. 
Zapisujemy sobie na kartce, że jednak potrzebujemy eksportu na zewnątrz, aby nie przechowywać wszystkiego w jednym miejscu.

Drugą wadą jest zużycie pamięci. Tak, rozumiem, że wielu powie, że w 2020 roku kilka gigabajtów pamięci to kosztuje grosze, ale mimo to.
Obecnie mamy środowisko dev i prod. W dev to około 9 gigabajtów na 350 000 metryk. W prod – to nieco ponad 14 gigabajtów na 780 000 metryk. Przy tym czas retencji wynosi zaledwie 30 minut. To źle. I teraz wytłumaczę dlaczego.

Robimy obliczenia, tzn. przy półtora miliona metryk, a już się do nich zbliżamy, na etapie projektowania otrzymujemy 35-37 gigabajtów pamięci. Ale już przy 4 milionach metryk potrzeba około 90 gigabajtów pamięci. Tzn. to zostało obliczone na podstawie formuły dostarczonej przez deweloperów Prometheus. Zbadaliśmy korelację i zrozumieliśmy, że nie chcemy płacić kilku milionów za serwer tylko do monitorowania.
Nie tylko zwiększy się liczba maszyn, ale również monitorujemy same maszyny wirtualne. Dlatego im więcej maszyn wirtualnych, tym więcej różnych metryk itd. Będzie to specjalny wzrost naszego klastra pod względem metryk.

Z przestrzenią dyskową nie jest aż tak źle, ale chcielibyśmy poprawić sytuację. W ciągu 15 dni uzyskaliśmy łącznie 120 gigabajtów, z czego 100 – to dane skompresowane, 20 – to dane nieskompresowane, ale zawsze chcemy, aby było ich mniej.

Odpowiednio, zapisujemy jeszcze jeden punkt – to duże zużycie zasobów, które chcielibyśmy jednak oszczędzać, ponieważ nie chcemy, aby nasz klaster monitorowania pochłaniał więcej zasobów niż nasz klaster zajmujący się zarządzaniem OpenStack.

Jest jeszcze jedna wada Prometheus, którą zidentyfikowaliśmy, to jakieś ograniczenie dotyczące pamięci. Z Prometheus jest tutaj znacznie gorzej, ponieważ nie ma w ogóle takich opcji. Używanie ograniczeń w Dockerze również nie jest rozwiązaniem. Jeśli nagle у was spadł RAF i tam jest 20-30 gigabajtów, to jego uruchomienie zajmie bardzo dużo czasu.

To jeszcze jedna przyczyna, dla której Prometheus nam nie odpowiada, tzn. nie można ograniczyć zużycia pamięci.

Można by było opracować taki schemat. Ten schemat jest nam potrzebny, aby zorganizować klaster HA. Chcemy, aby nasze metryki były zawsze i wszędzie dostępne, nawet w przypadku awarii serwera przechowującego te metryki. W związku z tym musimy stworzyć taki schemat.
Ten schemat mówi, że będziemy mieć duplikację shardów, a tym samym duplikację wydatków na zasoby. Można go prawie poziomo skalować, jednak zużycie zasobów będzie ogromne.

Wady w kolejności, w jakiej je wypisaliśmy:
- Wymagana jest eksfiltracja metryk na zewnątrz.
- Duże zużycie zasobów.
- Nie można ograniczyć zużycia pamięci.
- Skomplikowana i zasobożerna realizacja HA.

Zdecydowaliśmy, że rezygnujemy z Prometheus jako z magazynu.
Określiliśmy dodatkowe wymagania, które są nam potrzebne. Są to:
- Wsparcie dla promql, ponieważ już wiele rzeczy zostało stworzonych dla Prometheus: zapytania, alerty.
- A następnie mamy Grafanę, która również została stworzona dla Prometheus jako backend. Nie chcemy przepisywać pulpitów nawigacyjnych.
- Chcemy zbudować normalną architekturę HA.
- Chcemy zmniejszyć zużycie wszelkich zasobów.
- Jest jeszcze jeden mały szczegół. Nie możemy korzystać z różnego rodzaju systemów chmurowych do zbierania metryk. Nie wiemy, co zanika w tych metrykach na razie. A ponieważ tam może trafić wszystko, co zechcemy, musimy ograniczyć się do lokalnego umiejscowienia.

Wybór był niewielki. Zebraliśmy wszystko, co mieliśmy doświadczenie. Spojrzeliśmy na stronę Prometheus w sekcji integracji, przeczytaliśmy mnóstwo artykułów, sprawdziliśmy, co w ogóle jest dostępne. I dla siebie wybraliśmy VictoriaMetrics jako zamiennik Prometheus.
Dlaczego? Ponieważ:
- Obsługuje promql.
- Ma architekturę modułową.
- Nie wymaga zmian w Grafanie.
- I najważniejsze – być może będziemy oferować magazyn metryk w naszej firmie jako usługę, dlatego z wyprzedzeniem patrzymy w kierunku różnych ograniczeń, aby użytkownicy mogli w pewien ograniczony sposób korzystać ze wszystkich zasobów klastra, ponieważ istnieje szansa, że będzie on wielonajem.

Robimy pierwsze porównanie. Bierzemy ten sam Prometheus w obrębie klastra, do którego łączy się zewnętrzny Prometheus. Dodajemy przez remoteWrite VictoriaMetrics.

Od razu zaznaczę, że tutaj zauważyliśmy niewielki wzrost zużycia CPU ze strony VictoriaMetrics. Na wiki VictoriaMetrics napisano, jakie parametry są najlepsze. Sprawdziliśmy je. Bardzo dobrze zmniejszyły zużycie CPU.
W naszym przypadku zużycie pamięci przez Prometheus, który znajduje się w klastrze Kubernetes, wzrosło nieznacznie.

Porównujemy dwa źródła danych tych samych danych. W Prometheus widzimy wszystkie te same brakujące dane. W VictoriaMetrics wszystko jest w porządku.

Wyniki testów dotyczących przestrzeni dyskowej. W Prometheus uzyskaliśmy łącznie 120 gigabajtów. W VictoriaMetrics uzyskujemy już 4 gigabajty dziennie. Tam jest trochę inny mechanizm niż w Prometheus. Tzn. dane są już dość dobrze kompresowane za dzień, za pół godziny. Są już dobrze skompresowane za dzień, za pół godziny, mimo że później będą jeszcze scalane. Ostatecznie zaoszczędziliśmy na przestrzeni dyskowej.

Ponadto oszczędzamy na zużyciu zasobów pamięci. Nasz Prometheus w momencie testów był uruchomiony na maszynie wirtualnej – 8 rdzeni, 24 gigabajty. Prometheus praktycznie zajmuje wszystko. Upadł przez OOM Killer. Jednocześnie w nim było tylko 900 000 aktywnych metryk. To około 25 000-27 000 metryk na sekundę.
VictoriaMetrics uruchomiliśmy na dwurdzeniowej maszynie wirtualnej z 8 gigabajtami RAM. Udało nam się sprawić, że VictoriaMetrics działa dobrze, manipulując niektórymi rzeczami na 8-gigabajtowej maszynie. Ostatecznie zmieściliśmy się w 7 gigabajtach. Przy tym uzyskaliśmy prędkość dostarczania treści, tzn. metryk, nawet wyższą niż w Prometheus.

Zużycie CPU w porównaniu do Prometheus stało się znacznie lepsze. Tutaj Prometheus zużywa 2,5 rdzenia, a VictoriaMetrics tylko 0,25 rdzenia. Na początku - 0,5 rdzenia. W miarę scalania osiąga jedno rdzenie, ale to skrajnie rzadko.

W naszym przypadku wybór padł na VictoriaMetrics z oczywistych powodów, chcieliśmy zaoszczędzić i zaoszczędziliśmy.

Odrzucamy na początek dwa punkty – to wywóz metryk i duże zużycie zasobów. Pozostają nam dwa punkty do rozwiązania, które jeszcze zostawiliśmy dla siebie.

Tutaj zaznaczę od razu, że VictoriaMetrics traktujemy jako magazyn metryk. Ale ponieważ prawdopodobnie będziemy oferować VictoriaMetrics jako magazyn dla całego Leroy, musimy ograniczyć tych, którzy będą korzystać z tego klastra, aby nam go nie zniszczyli.
Jest wspaniały parametr, który pozwala ograniczać czas, objętość danych oraz czas wykonania.
A także istnieje doskonała opcja, która pozwala ograniczać zużycie pamięci, dzięki czemu możemy znaleźć równowagę, która pozwoli nam osiągnąć normalną prędkość pracy i adekwatne zużycie zasobów.

Odbieramy jeszcze jeden punkt, t. j. skreślamy punkt – nie można ograniczyć zużycia pamięci.

W pierwszych iteracjach testowaliśmy VictoriaMetrics Single Node. Następnie przechodzimy do wersji klastrowej VictoriaMetrics.
Tutaj mamy wolną rękę w kwestii rozdzielania różnych usług w VictoriaMetrics w zależności od tego, na czym będą działać i jakie zasoby będą zużywać. To bardzo elastyczne i wygodne rozwiązanie. Używaliśmy go na własnej skórze.

Podstawowe komponenty VictoriaMetrics Cluster Version to vmstorage. Może ich być N liczba. W naszym przypadku na razie są 2.
Jest też vminsert. To serwer proxy, który pozwala nam: zorganizować sharding pomiędzy wszystkimi storage, o których mu powiedzieliśmy, a także zapewnia replikę, t. j. będziecie mieć zarówno sharding, jak i replikę.
Vminsert wspiera protokoły OpenTSDB, Graphite, InfluxDB oraz remoteWrite od Prometheus.

Jest jeszcze vmselect. Jego głównym zadaniem jest przeprowadzanie zapytań do vmstorage, uzyskiwanie danych od nich, deduplikacja tych danych i przekazywanie ich klientowi.

Jest wspaniała rzecz jak vmagent. Bardzo nam się podoba. Umożliwia konfigurację w ten sam sposób jak Prometheus i wykonuje wszystko tak samo jak Prometheus. T. j. zbiera metryki z różnych encji, usług i wysyła je do vminsert. Dalej wszystko już zależy od was.

Kolejna wspaniała usługa to vmalert, która pozwala korzystać z VictoriaMetrics jako backendu, pobierać dane z vminsert i wysyłać je do vmselect w formie przetworzonych danych. Obsługuje same alerty oraz reguły. W przypadku alertów otrzymujemy alert przez alertmanager.

Jest komponent wmauth. Możliwe, że go użyjemy, a być może nie (jeszcze się z tym nie zdecydowaliśmy) jako system autoryzacji przy wieloaspektowej wersji klastrów. Wspiera remoteWrite dla Prometheus i może autoryzować na podstawie url, a dokładniej drugiej jego części, gdzie można lub nie można pisać.

Jest też vmbackup, vmrestore. To w zasadzie odzyskiwanie i backup wszystkich danych. Obsługuje S3, GCS, plik.

Pierwsza iteracja naszego klastra została zrealizowana w czasie kwarantanny. Wówczas nie było replik, więc nasza iteracja składała się z dwóch różnych i niezależnych klastrów, do których przez remoteWrite pozyskiwaliśmy dane.

Zaznaczę, że podczas przechodzenia z wersji VictoriaMetrics Single Node na wersję VictoriaMetrics Cluster, wciąż pozostałyśmy w tych samych zużywanych zasobach, tj. głównie pamięć. W ten sposób rozkładały się nasze dane, tj. zużycie zasobów.

Tutaj już była dodana replika. Połączyliśmy to wszystko w jeden stosunkowo duży klaster. Wszystkie dane są zarówno shardowane, jak i replikowane.
Cały klaster ma N punktów wejścia, tj. Prometheus może dodawać dane przez HAPROXY. To jest nasz punkt wejścia. Przez ten punkt wejścia można się łączyć z Grafana.

W naszym przypadku HAPROXY to jedyny port, który proxy'uje selekcję, wstawianie i inne usługi do wewnątrz tego klastra. W naszym przypadku nie mogliśmy stworzyć jednego adresu, musieliśmy zrealizować kilka punktów wejścia, ponieważ same maszyny wirtualne, na których działa klaster VictoriaMetrics, znajdują się w różnych strefach jednego dostawcy chmurowego, tj. nie w naszym chmurze, a na zewnątrz.

Mamy alertowanie. Używamy go. Korzystamy z alertmanagera od Prometheus. Jako kanału dostawy alertów używamy Opsgenie i Telegrama. Na Telegram wpływają powiadomienia od dev, może coś od prod, ale bardziej coś takiego statystycznego, potrzebnego inżynierom. A Opsgenie – krytyczne. To telefony, zarządzanie incydentami.

Odwieczne pytanie: „Kto monitoruje monitoring?”. W naszym przypadku monitoring monitoruje sam monitoring, ponieważ używamy vmagent na każdym węźle. A ponieważ nasze węzły są rozmieszczone w różnych centrach danych jednego dostawcy, dla każdego centrum danych mamy swój kanał, są one niezależne i nawet jeśli zajdzie splitting brain, to i tak otrzymamy alerty. Tak, będzie ich więcej, ale lepiej mieć więcej alertów niż żadnego.

Kończymy naszą listę realizacją HA.

I chciałbym jeszcze podkreślić doświadczenie związane z interakcją z społecznością VictoriaMetrics. Okazała się bardzo pozytywna. Chłopaki są pomocni. Starają się zrozumieć każdy przypadek, który jest przedstawiany.
Zakładałem zgłoszenia na GitHubie. Zostały one bardzo szybko rozwiązane. Są jeszcze jakieś dwa zgłoszenia, które nie są całkowicie zamknięte, ale już po kodzie widzę, że prace w tym kierunku trwają.
Głównym problemem podczas iteracji było dla mnie to, że jeśli wyłączyłem węzeł, to przez pierwsze 30 sekund nie mogłem zrozumieć, że backend nie działa. Teraz to już rozwiązano. I dosłownie w ciągu sekundy lub dwóch dane są pobierane ze wszystkich pozostałych węzłów, a zapytanie przestaje czekać na brakujący węzeł.

W pewnym momencie chcieliśmy, żeby to był operator VictoriaMetrics. Czekaliśmy na niego. Teraz aktywnie budujemy nakładkę na operator VictoriaMetrics, aby przejąć wszystkie zasady pre-calculation i tak dalej. Prometheus, ponieważ dość aktywnie używamy reguł, które idą razem z operatorem Prometheus.
Są propozycje dotyczące ulepszenia realizacji klastra. Przedstawiłem je powyżej.
I jeszcze bardzo chcemy downsampling. W naszym przypadku downsampling jest potrzebny wyłącznie do przeglądania trendów. Mówiąc wprost, potrzebuję jednej metryki w ciągu dnia. Te trendy są potrzebne na rok, na trzy, na pięć, na dziesięć lat. I jedna wartość metryki jest wystarczająca.

- Doświadczyliśmy bólu, podobnie jak niektórzy nasi koledzy, podczas korzystania z Prometheus.
- Wybraliśmy dla siebie VictoriaMetrics.
- Dobrze się skaluje zarówno w pionie, jak i w poziomie.
- Możemy rozdzielać różne komponenty na różną liczbę węzłów w klastrze, ograniczać je pod względem pamięci, dodawać pamięć itd.
Będziemy używać VictoriaMetrics, ponieważ bardzo nam się spodobała. Oto co było, a co się zmieniło.

Para kodów qr do czatu VictoriaMetrics, moje dane kontaktowe, radar technologiczny LeroyMerlin.
Źródło: habr.com
