Prometheus monitoringas: metrikos realiu laiku

Kas yra Prometheus ir kodėl jis tapo tokiu populiarus?

Jei dirbi IT srityje, tikrai girdėjai apie Prometheus. Šis atvirojo kodo monitoringo įrankis per pastaruosius kelerius metus tapo beveik standartu, kai kalbama apie sistemų stebėjimą ir metrikų rinkimą. Bet kodėl būtent Prometheus? Gal todėl, kad jis buvo sukurtas SoundCloud komandos, kuri susidūrė su realiais iššūkiais stebint mikroservisų architektūrą? O gal todėl, kad jis dabar yra Cloud Native Computing Foundation (CNCF) projektas, kaip ir Kubernetes?

Prometheus nėra tiesiog dar vienas monitoringo įrankis. Tai pilna ekosistema, kuri leidžia rinkti, saugoti ir analizuoti laiko eilučių duomenis (time series data). Svarbiausia jo savybė – tai pull modelis, kai Prometheus pats kreipiasi į stebimus taikinius ir renka metrikus, o ne laukia, kol kas nors jam atsiųs duomenis. Tai gali atrodyti kaip smulkmena, bet praktikoje šis sprendimas suteikia daug lankštumo ir patikimumo.

Dar vienas dalykas, kuris išskiria Prometheus – tai PromQL užklausų kalba. Ji gali atrodyti bauginanti iš pradžių, bet kai išmoksti jos pagrindus, supranti, kad tai vienas galingiausių įrankių duomenų analizei. Galima sakyti, kad PromQL yra tai, kas SQL duomenų bazėms – tik pritaikyta laiko eilučių duomenims.

Kaip veikia metrikų rinkimas realiu laiku

Realybėje „realus laikas” Prometheus kontekste nėra visiškai realus. Paprastai Prometheus renka metrikus kas 15-60 sekundžių (tai vadinama scrape interval). Bet praktikoje šis dažnumas yra daugiau nei pakankamas daugumai panaudojimo atvejų. Jei tau reikia tikrai tikro realaus laiko su milisekundžių tikslumu – galbūt turėtum pažiūrėti į kitus sprendimus.

Prometheus veikia pagal paprastą principą: tu apibrėži taikinius (targets), kuriuos jis turi stebėti, ir jis periodiškai kreipiasi į juos per HTTP, tikėdamasis gauti metrikus specialiu formatu. Šie taikiniai gali būti bet kas – tavo aplikacija, duomenų bazė, serveris, tinklo įrenginys. Vienintelis reikalavimas – jie turi eksportuoti metrikus Prometheus formatu.

Štai kaip tai atrodo praktikoje: tavo aplikacija turi `/metrics` endpoint’ą, kuris grąžina tekstinį atsakymą su metrikais. Prometheus kas 30 sekundžių (arba kiek tu nustatei) kreipiasi į šį endpoint’ą, nuskaito duomenis ir išsaugo juos savo duomenų bazėje. Paprasta, ar ne? Bet šis paprastumas ir yra Prometheus stiprybė.

Metrikų tipai ir kada juos naudoti

Prometheus palaiko keturis pagrindinius metrikų tipus, ir svarbu suprasti, kada naudoti kurį. Tai nėra tik teorija – neteisingas metriko tipo pasirinkimas gali sukelti painiavą ir neteisingas išvadas.

Counter – tai monotoniškai didėjanti reikšmė. Pavyzdžiui, užklausų skaičius, klaidų skaičius, apdorotų užduočių skaičius. Counter’is niekada nemažėja (išskyrus atvejį, kai aplikacija perkraunama). Kai nori sužinoti, kiek užklausų per sekundę gauni, naudoji `rate()` funkciją, kuri apskaičiuoja pokytį per laiko tarpą.

Gauge – tai reikšmė, kuri gali ir didėti, ir mažėti. Pavyzdžiui, atminties naudojimas, aktyvių vartotojų skaičius, eilės ilgis. Gauge’us galima tiesiog stebėti ir vizualizuoti be jokių papildomų transformacijų.

Histogram – tai sudėtingesnis tipas, kuris leidžia matuoti reikšmių pasiskirstymą. Pavyzdžiui, užklausų trukmę. Histogram’a automatiškai sukuria kelis metrikų – bendrus skaičiavimus ir „buckets” (intervalus), kurie parodo, kiek reikšmių patenka į tam tikrus diapazonus. Tai labai naudinga, kai nori apskaičiuoti percentiles (pvz., 95-ąjį percentilį).

Summary – panašus į histogram’ą, bet percentiles skaičiuoja kliento pusėje. Tai turi privalumų ir trūkumų – mažiau apkrauna Prometheus serverį, bet negali agregavoti duomenų iš kelių instancijų.

Prometheus konfigūracija: nuo pagrindų iki pažangių scenarijų

Prometheus konfigūracija yra YAML failas, ir jei esi dirbęs su Kubernetes, tai tau bus pažįstama. Bet nepasiklysk – Prometheus konfigūracija gali tapti gana sudėtinga, kai pradedi pridėti service discovery, relabeling ir kitas pažangias funkcijas.

Paprasčiausias `prometheus.yml` failas atrodo maždaug taip:

„`yaml
global:
scrape_interval: 15s
evaluation_interval: 15s

scrape_configs:
– job_name: ‘my-application’
static_configs:
– targets: [‘localhost:9090’]
„`

Bet realybėje tu tikriausiai nenorėsi rankiniu būdu prižiūrėti visų taikinių sąrašo. Čia į pagalbą ateina service discovery mechanizmai. Prometheus palaiko daugybę jų – Kubernetes, Consul, EC2, Azure, GCE ir kitus. Pavyzdžiui, jei naudoji Kubernetes, Prometheus gali automatiškai atrasti visus pod’us su tam tikromis anotacijomis.

Relabeling – tai dar viena galinga funkcija, kuri leidžia transformuoti labels prieš išsaugant metrikus. Galima filtruoti taikinius, pakeisti label’ų pavadinimus, pridėti naujus label’us. Tai atrodo kaip smulkmena, bet praktikoje tai suteikia neįtikėtiną lankstumą. Pavyzdžiui, galima automatiškai pridėti environment label’ą pagal namespace’ą Kubernetes’e.

PromQL: užklausų kalba, kurią verta išmokti

PromQL – tai Prometheus užklausų kalba, ir ji yra šio įrankio širdis. Iš pradžių ji gali atrodyti keista, bet kai supranti jos logiką, ji tampa labai intuityvi. Pagrindinis dalykas, kurį reikia suprasti – PromQL dirba su laiko eilutėmis (time series), o ne su atskiromis reikšmėmis.

Paprasčiausia užklausa tiesiog grąžina visas laiko eilutes su tam tikru pavadinimu:

„`
http_requests_total
„`

Bet tai retai kada naudinga. Paprastai nori filtruoti pagal label’us:

„`
http_requests_total{method=”GET”, status=”200″}
„`

Dabar tampa įdomiau. Jei nori sužinoti užklausų per sekundę greitį, naudoji `rate()` funkciją:

„`
rate(http_requests_total[5m])
„`

Šis pavyzdys apskaičiuoja vidutinį greitį per paskutines 5 minutes. Kodėl 5 minutes? Tai kompromisas tarp tikslumo ir atsparumo trumpalaikiams šuoliams. Jei naudotum [1m], matytum daugiau svyravimų, bet duomenys būtų jautresni.

Agregavimas – dar viena svarbi PromQL dalis. Galima sumuoti, apskaičiuoti vidurkį, maksimumą ir t.t.:

„`
sum(rate(http_requests_total[5m])) by (status)
„`

Ši užklausa parodo bendrą užklausų greitį, sugrupuotą pagal status kodą. Tai labai naudinga, kai nori pamatyti, kiek gauni 200, 404, 500 atsakymų.

Exporters: kaip stebėti viską, kas juda

Viena iš Prometheus ekosistemos stiprybių – tai daugybė jau paruoštų exporter’ių. Exporter’is – tai programa, kuri renka metrikus iš sistemos, kuri pati jų neeksportuoja Prometheus formatu, ir juos konvertuoja.

Node Exporter – tai turbūt populiariausias exporter’is. Jis renka sistemos metrikus – CPU, atmintį, diską, tinklą ir daug kitų. Jei nori stebėti serverio sveikatą, tai būtinas įrankis. Jis eksportuoja šimtus metrikų, ir iš pradžių gali būti sunku suprasti, kurie iš jų svarbūs. Bet paprastai pradedi nuo pagrindinių: CPU usage, memory usage, disk I/O, network traffic.

MySQL Exporter, PostgreSQL Exporter – duomenų bazių stebėjimui. Jie eksportuoja tokius dalykus kaip aktyvūs connection’ai, užklausų greitis, replikacijos būsena ir t.t. Jei tavo aplikacija priklauso nuo duomenų bazės (o kuri ne?), šie exporter’iai yra būtini.

Redis Exporter, RabbitMQ Exporter, Kafka Exporter – ir taip toliau. Beveik kiekvienai populiariai technologijai yra exporter’is. O jei nėra – gali parašyti savo. Prometheus exporter’io rašymas nėra sudėtingas – daugelyje kalbų yra oficialios bibliotekos, kurios padaro šį procesą labai paprastą.

Alerting: kai metrikos virsta veiksmais

Metrikos yra naudingos, bet tikroji jų vertė atsiskleidžia, kai jos virsta alert’ais. Prometheus turi integruotą alert’ų sistemą, kuri veikia kartu su Alertmanager komponentu.

Alert’ų taisyklės apibrėžiamos kaip PromQL užklausos su sąlygomis. Pavyzdžiui:

„`yaml
groups:
– name: example
rules:
– alert: HighErrorRate
expr: rate(http_requests_total{status=~”5..”}[5m]) > 0.05
for: 10m
labels:
severity: warning
annotations:
summary: „High error rate detected”
description: „Error rate is {{ $value }} requests per second”
„`

Šis alert’as suveiks, jei 5xx klaidų greitis viršys 0.05 per sekundę ir išliks toks 10 minučių. `for` parametras yra svarbus – jis apsaugo nuo false positive alert’ų dėl trumpalaikių šuolių.

Alertmanager – tai atskiras komponentas, kuris gauna alert’us iš Prometheus ir juos apdoroja. Jis gali siųsti pranešimus į Slack, PagerDuty, email ir daug kitų kanalų. Bet svarbiausia – jis gali grupuoti, nutildyti ir deduplikuoti alert’us. Jei turi 100 serverių ir visi jie vienu metu pradeda reportuoti tą patį alert’ą, nenori gauti 100 pranešimų – nori gauti vieną.

Alertmanager konfigūracija leidžia apibrėžti sudėtingas routing taisykles. Pavyzdžiui, kritiniai alert’ai gali eiti į PagerDuty ir žadinti on-call inžinierių, o warning’ai – tik į Slack kanalą. Galima nustatyti, kad tam tikrais laikais (pvz., naktį) būtų siunčiami tik kritiniai alert’ai.

Praktiniai patarimai ir dažniausios klaidos

Per metus darbo su Prometheus pamačiau daugybę klaidų, kurias daro komandos. Štai keletas patarimų, kurie gali sutaupyti daug laiko ir nervų.

Cardinality – tai tavo priešas. Cardinality reiškia unikalių laiko eilučių skaičių. Kiekviena unikali label’ų kombinacija sukuria naują laiko eilutę. Jei pradedi naudoti label’us su dideliu kiekiu unikalių reikšmių (pvz., user ID, session ID), Prometheus duomenų bazė labai greitai išsipūs ir sulėtės. Taisyklė paprasta: label’ai turėtų turėti ribotą kiekį galimų reikšmių.

Nenaudok timestamp’ų kaip label’ų. Tai atrodo akivaizdu, bet mačiau komandų, kurios tai darė. Timestamp’ai yra laiko eilučių dalis, ne label’ai. Jei nori saugoti timestamp’us, naudok metriko reikšmę.

Scrape interval’as turėtų būti pakankamai didelis. 15-30 sekundžių yra geras pasirinkimas daugumai atvejų. Jei naudoji 5 sekundes ar mažiau, tikriausiai be reikalo apkrauni sistemą. Išimtis – jei tikrai reikia labai didelio tikslumo, bet tai reti atvejai.

Naudok recording rules sudėtingoms užklausoms. Jei turi PromQL užklausą, kuri užima daug laiko, gali sukurti recording rule, kuri periodiškai ją vykdys ir išsaugos rezultatą kaip naują metriką. Tai labai pagreitina dashboard’ų įkėlimą.

Retention policy – nepamirštamas dalykas. Prometheus pagal nutylėjimą saugo duomenis 15 dienų. Jei reikia ilgesnio laikotarpio, reikia padidinti retention. Bet atmink – kuo ilgesnis retention, tuo daugiau vietos diske reikia. Jei reikia ilgalaikio saugojimo, pažiūrėk į Thanos arba Cortex projektus.

Integracijos ir ekosistema: daugiau nei tik Prometheus

Prometheus retai kada naudojamas vienas. Paprastai jis yra dalies didesnės monitoringo stack’o. Grafana – tai de facto standartas vizualizacijai. Ji palaiko Prometheus kaip duomenų šaltinį ir leidžia kurti gražius, interaktyvius dashboard’us. Grafana turi daugybę paruoštų dashboard’ų Prometheus metrikoms, tad nebūtina kurti visko nuo nulio.

Thanos ir Cortex – tai projektai, kurie išsprendžia Prometheus skalės problemas. Jie leidžia saugoti metrikus ilgiau, agregavus duomenis iš kelių Prometheus instancijų, ir užtikrina high availability. Jei tavo infrastruktūra auga, anksčiau ar vėliau susidursi su poreikiu naudoti vieną iš šių sprendimų.

Kubernetes integracija – jei naudoji Kubernetes, Prometheus yra beveik būtinas. Prometheus Operator supaprastina Prometheus diegimą ir konfigūravimą Kubernetes klasteryje. Jis įveda naujus Custom Resource Definition (CRD) tipus, tokius kaip ServiceMonitor ir PodMonitor, kurie leidžia apibrėžti monitoringo konfigūraciją deklaratyviai.

OpenMetrics – tai standartas, kuris išaugo iš Prometheus metrikų formato. Dabar jis yra CNCF projektas ir tampa industrijos standartu. Tai reiškia, kad vis daugiau įrankių ir sistemų palaiko šį formatą natyviai, be papildomų exporter’ių.

Kai metrikos tampa kultūros dalimi

Prometheus – tai ne tik technologija, tai būdas mąstyti apie sistemų stebėjimą. Kai pradedi naudoti Prometheus, pamažu keičiasi požiūris į tai, kaip kurti ir prižiūrėti sistemas. Pradedi galvoti apie observability nuo pat pradžių, o ne kaip apie „nice to have” funkciją, kurią pridėsi vėliau.

Svarbu suprasti, kad Prometheus nėra sidabrinė kulka. Jis puikiai tinka metrikoms, bet ne log’ams ar distributed tracing’ui. Šiuolaikinė observability strategija paprastai apima tris stulpus: metrikos (Prometheus), log’ai (ELK, Loki) ir tracing (Jaeger, Zipkin). Kiekvienas iš jų sprendžia skirtingas problemas.

Pradėti su Prometheus nėra sunku – gali paleisti jį lokalioje mašinoje per kelias minutes. Bet išmokti jį naudoti efektyviai užtrunka. Reikia suprasti PromQL, cardinality problemas, alert’ų konfigūravimą, retention politikas. Bet investicija atsiperkama – turėsi aiškų vaizdą, kas vyksta tavo sistemose, ir galėsi greitai reaguoti į problemas, dažnai dar prieš jas pastebint vartotojams.

Galiausiai, Prometheus yra bendruomenės projektas su aktyvia ekosistema. Yra daugybė resursų, pavyzdžių, exporter’ių. Jei susiduri su problema, tikėtina, kad kažkas jau ją išsprendė ir pasidalino sprendimu. Tai viena iš atvirojo kodo stiprybių – stovi ant milžinų pečių.

Daugiau

XML external entity (XXE) atakos