Difference between revisions of "Metrics and Monitoring in swarm"
(→Metrika a Prometheus-ban) |
(→Honnan jön a metrika) |
||
Line 61: | Line 61: | ||
− | Java-ban nagyon egyszerűen szolgáltathatunk metrikákat az alkalmazásunkból a Prometheus client library-val. Van hozzá Maven dependency. Abba az osztályba, ami a | + | Java-ban nagyon egyszerűen szolgáltathatunk metrikákat az alkalmazásunkból a Prometheus client library-val. Van hozzá Maven dependency. Abba az osztályba, ami a metrikát szolgáltatja, egy statikus konstruktorral inicializáljuk a Prometheus metrika gyűjtőt. Az alábbi példában inicializálnunk egy '''my_library_request_total''' metrikát, ami fölé a http metrika listában egy #-val oda lesz írva a help szöveg: "Total request" (ezt nem veszi figyelembe a Prometheus). A metrikához hozzáadtuk a '''method''' nevű címét. |
<source lang="java"> | <source lang="java"> | ||
class YourClass { | class YourClass { | ||
Line 93: | Line 93: | ||
context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics"); | context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics"); | ||
</source> | </source> | ||
− | |||
==Metrika típusok== | ==Metrika típusok== |
Revision as of 21:00, 14 August 2018
Contents
Mi az a metrika
A metrika egy fajta speciális loggolás, amit a metrikát szolgáltató rendszer nem egy log fájlba ír, hanem biztosít egy HTTP API-t, amin keresztül a metrikát feldolgozó szolgáltatás le tudja azt periodikusan kérdezni. A metrika név-érték párok listája, aminek a jelentése bármi lehet ami időben változik. A metrika listában minden egyes metrika jelentését a metrikát szolgáltató rendszernek kell definiálnia. Pl egy node-on lévő elérhető maradék memóriát jelképezheti a következő metrika:
node_memory_MemAvailable 210
A metrika értéke lehet szám, string vagy logikai érték is.
A metrikákat minden rendszerben, szervezetben vagy swarm cluster-ben egy központi egység kérdezi le és gyűjti össze a saját adatbázisában. A metrikát összegyűjtő rendszerben aztán lekérdezéseket írhatunk fel a metrikákra, aminek az eredménye alapján aztán automatizált folyamatokat indíthatunk be, mint pl a swarm cluster méretének megváltoztatása, alert küldése sms-ben, emailben. Tehát a metrikák a hagyományos log fájlokkal ellentétben a baj valós idejű detektálására, vagy sokkal inkább a baj elkerülésére szolgálnak. Ebből kifolyólag a logokkal ellentétben a metrikák élettartalma nagyon rövid, tipikusan olyan lekérdezéseket szoktunk írni, ahol a lekérdezett metrikák kora nem több mint 10 perc, de inkább pár perc, hiszen itt mindig valaminek az időben történő változására vagyunk kíváncsiak. Így nem olyan kritikus a metrikák elvesztése mint a hagyományos log fájloké, amik tipikusan offline elemzésre szolgálnak, ha a baj már bekövetkezett.
A metrikákat úgynevezett time-series (idősor) adatbázisban kell letárolni (TSDB), vagyis egy adott metrikához nyilván van tartva minden lekérdezéshez az akkor kapott érték. Ez a speciális struktúra ugyan letárolható lenne hagyományos adatbázis kezelőkben is, de nagyon nem lenne hatékony a bennük való keresés. Léteznek direkt erre a speciális adatmodellre készült adatbáziskezelők, amik rettentő hatékonyan tudnak keresni a time-series adatokban. Egy adott metrika tárolását egy listaként lehet elképzelni, ahol a lista elemek az időbélyegekkel vannak indexelve, és a listaelem tárolja az adott időpillanathoz (amikor a lekérdezés történt) a metrika értékét. A főbb time-series db-k:
- InfluxDB:
- Prometheus
- Graphite
- OpenTSDB
- KairosDB
...
Fontos, hogy a time-series db számára a metrika csak egy név-érték pár (egy string amihez tartozik egy érték), tehát a TSDB nem értelmezi a kapott metrikát, a lekérdezéseket úgy kell megírni, hogy legyen értelme a háttérrendszerre vonatkozóan. Tehát mikor megtervezzük a lekérdezéseinket a TSDB-ben, akkor elsőként a metrikát szolgáltató rendszer specifikációját kell megnézni, hogy az milyen metrikákat szolgáltat magáról, és melyiknek pontosan mi a jelentése.
A time-series adatbáziskezelő (TSDB) folyamatosan gyűjti a különböző komponensek metrikáit, és minden egyes begyűjtés után ki fogja értékelni a különböző metrikákra felírt lekérdezéseket, amik általában abból állnak, hogy egy time-series lekérdezés eredményét összeveti egy értékkel vagy logika változóval, és a végeredmény vagy igaz vagy hamis. Ha a végeredmény igaz, akkor a time-series adatbáziskezelő riasztást fog generálni (beindít egy automatizált folyamatot), ha a kiértékelés hamis, akkor meg nem fog semmit csinálni. A riasztás hatására küldhetünk emial-t, végrehajthatunk egy bash script-et... stb.
TSDB használatával lehet a swarm cluster egészségét automatizált módon monitorozni vagy akár dinamikusan változtatni a worker node-ok mennyiségét. Pl felírhatunk különböző szabályokat a node-ok leterheltségére. Ha a node-ok valamilyen metrika mentén túlságosan leterheltek, akkor újabb node-okat állítunk automatikusan üzembe, ha meg a terhelés túl alacsony ugyan ezen metrika alapján, akkor meg bizonyos node-okat megszüntetünk.
Mi innentől kezdve csak a Prometheus-ra fogunk fókuszálni.
Prometheus felépítése
Címkék, plusz dimenziók
A Prometheus szabványú metrikában további dimenziókat lehet bevezetni minden metrikához úgynevezett metrika címkékkel, amiket a metrikát szolgáltató rendszer (pl egy apache) hozzáfűz a metrika nevéhez. A címkék tehát tovább specializálnak egy metrikát, pl egy http proxy a proxy_http_request_total nevű metrikával mondhatja meg, hogy a lekérdezési időpontjáig hány kérés érkezett a proxy-hoz. De ezt tovább specializálhatja címkék bevezetésével. Az alábbi példában a method és a status címéket használta a proxy a proxy_http_request_total metrika finomításához. Az alábbi példában tehát a metrika értéke nem az összes request-re vonatkozik, csak azokra amiket GET-el kértek le, és amiknek 200-as volt a státusza.
proxy_http_request_total{method="GET", status="200"} 13
A valóságban ez úgy nézne ki a metrikát szolgáltató rendszer által gyárott metrika listában, hogy sorba jönne az összes variáció egymás után, pl:
... proxy_http_request_total{method="GET", status="200"} 13 proxy_http_request_total{method="GET", status="500"} 12 proxy_http_request_total{method="POST", status="200"} 30 proxy_http_request_total{method="POST", status="300"} 20 ...
Fontos, hogy a címkének is a metrikát szolgáltató rendszer ad jelentést, a time-series adatbázis kezelő számra (a mi esetünkben Prometheus) a metrika és a benne lévő címkék is csak név érték párok. Azonban a címke és annak az értéke is részei a metrika nevének. Tehát a metrikát az összes címéjével együtt felfoghatjuk egy string-nek, aminek van egy értéke. A time-series adatbázisokban a címkék segítségével nagyon trükkös lekérdezéseket lehet felírni, amiket a time-series adatbázis nagyon hatékonyan meg tud keresni.
Honnan jön a metrika
Metrikát magáról nagyon sok rendszer tud szolgáltatni, pl a Traefik reverse proxy, vagy ahogy azt majd látni fogjuk, akár a docker daemon is képes metrikákat szolgáltatni saját magáról. Általában a metrika lekérdezésére egy http interfészt biztosít a metrikát adó rendszer, amit a /metrics URL-en lehet elérni. A http interfészek esetében PULL metrika begyűjtésről beszélünk, vagyis a Prometheus (vagy bármelyik másik TSDB) a konfigurációja alapján periodikusan (pár másodpercenként) meghívja a megfelelő URL-t, ahol visszakapja az aktuális metrika listát (név-érték párokat), amit beír az adatbázisba. Léteik PUSH alapú metrika gyújtés is.
A Prometheus 4 nyelven is ad API-t metrika szolgáltatás írására: Go, Java, Python, Ruby.
https://prometheus.io/docs/instrumenting/clientlibs/
Tehát továbbra sem a Prometheus szolgáltatja metrikát, a Prometheus csak összegyűjti azt, de a kezünkbe ad egy API-t, amivel a saját rendszerünkbe nagyon könnyen építhetünk metrika szolgáltató interfészt.
Java-ban nagyon egyszerűen szolgáltathatunk metrikákat az alkalmazásunkból a Prometheus client library-val. Van hozzá Maven dependency. Abba az osztályba, ami a metrikát szolgáltatja, egy statikus konstruktorral inicializáljuk a Prometheus metrika gyűjtőt. Az alábbi példában inicializálnunk egy my_library_request_total metrikát, ami fölé a http metrika listában egy #-val oda lesz írva a help szöveg: "Total request" (ezt nem veszi figyelembe a Prometheus). A metrikához hozzáadtuk a method nevű címét.
class YourClass {
static final Counter requests = Counter.build()
.name("my_library_requests_total").help("Total requests.")
.labelNames("method").register();
void processGetRequest() {
requests.labels("get").inc();
// Your code here.
}
}
Ahányszor meghívjuk a processGetRequest() metódust, a fenti method="get" megcímkézett változatához hozzá fog adni egyet.
A lekérdezésben így nézne ki:
#Total requests. my_library_requests_total{method="get"} 23
Aztán meg pl egy HTTP servlet-el tudjuk szolgáltatni a metrikát:
Server server = new Server(1234);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
server.setHandler(context);
context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics");
Metrika típusok
https://prometheus.io/docs/concepts/metric_types/
A Prometheus 4 féle metrika típust definál, de ezek csak az API szinten vannak megkülönböztetve, a Prometheus-ban már nincsenek, ott nekünk kell tudni, hogy értelmes e amit felírunk szabály az adott metrikára.
Note
Ugyan a Prométeusz adatbázis nem tesz különbséget a metrika típusok között, fontos megérteni a 4 alaptípus közötti különbséget, mert a Prometheus API igen is megkülönbözteti őket és egyedi név és formátum konvenciót alkalmaz rájuk. Így kapásból érthetjük hogy mit jelenthet egy bonyolultabb nevű metrika, amit egy adott rendszer szolgáltat a Prometheus-nak
Gauge (ɡeɪdʒ)
A Gauge (mérő) a legegyszerűbb metrika a Prometheus-ban, ez egy egyszerű mérőszám, aminek fel és le is mehet az értéke, pl memória használat.
Counter
A számláló a második legegyszerűbb metrika fajta. A számlálónak csak nőhet az értéke, vagy reset-kor visszavált 0-ra. Persze ennek betartását a Prometheus nem ellenőrzi, számára ugyan olyan név-érték pár a számláló típusú metrika is mint bármelyik másik. Ha a hivatalos Java API-t használjuk az alkalmazásunkban, akkor ez az API biztosítja ennek a betartását. Pl:
# TYPE builder_builds_failed_total counter builder_builds_failed_total{reason="build_canceled"} 0
Histogram
http://linuxczar.net/blog/2017/06/15/prometheus-histogram-2/
https://statistics.laerd.com/statistical-guides/understanding-histograms.php
http://www.leanforum.hu/index.php/szocikkek/167-hisztogram-2
Fontos kifejezések:
distribution=eloszlás
latency=eltelt idő az input és az output között bármilyen rendszerben
frequency=gyakoriság
Mi az a Hisztogram:
A Hisztogram a gyakoriság eloszlást mutatja meg a mintának, amivel sokszor sokkal többre lehet menni, mint a hagyományos pl érték-idő diagramokból. A hisztogram egy minta elemzését segítő egyszerű statisztikai eszköz, amely a gyűjtött adatok (minta) alapján következtetések levonására ad lehetőséget. A hisztogram tulajdonképpen egy oszlopdiagram, amely X-tengelyén a tulajdonság osztályok (egy változó különböző értékei), Y-tengelyén pedig az előfordulási gyakoriságok találhatók. A hisztogram megmutatja az eloszlás alakját, középértékét és terjedelmét.
Nézzünk egy példát, hogy hogyan készül a hisztogram. Ha van egy mintám, amiben emberek korai vannak benne:
36 25 38 46 55 68 72 55 36 38 67 45 22 48 91 46 52 61 58 55
Ahhoz hogy ebből hisztogramot tudjunk készíteni (gyakorisági eloszlást), a minta elemeit úgynevezett osztályokba kell sorolni (bins vagy buckets), ami azt jelenti, hogy a folyamatos minta értékkészletet felvágjuk (általában egyenlő méretű) sávokra (x tengely), és megnézzük, hogy egy sávba hány minta elem tartozik (y tengely). A fenti példában az értékkészlet az emberek kora, amiben egy osztály (bin, bucket), amibe be akarjuk sorolni a mintákat, legyen 10 év, és induljon 20-tól és menjen 100-ig. Fontos, hogy a Hisztogramban az osztályok (buckets) mindig összeérnek, nem lehetnek benne lukak (Az hogy 10-re vettük az osztály méretét, ez a mi egyéni döntésünk volt, bármilyen más felosztást is választhattunk volna). Most nézzük meg, hogy egy osztályba (bucket) hány elem kerül, vagyis hogy pl a 40-től 50-ig terjedő osztályba hány ember kerül bele. Tehát a 40-50 osztályban a gyakoriság = 4.
Bin Frequency Scores Included in Bin 20-30 2 25,22 30-40 4 36,38,36,38 40-50 4 46,45,48,46 50-60 5 55,55,52,58,55 60-70 3 68,67,61 70-80 1 72 80-90 0 - 90-100 1 91
Ábrázoljuk a kapott eredményeket:
Osztályok (vödrök, bucket) meghatározása:
Azt hogy egy osztály (vödör, bucket, bin) mérete mekkora legyen arra nincs ökölszabály. Ne legyen túl kicsi, mert akkor túl sok oszlop lesz a grafikonon, de ne is legyen túl nagy, mert akkor meg túl kevés, és az eloszlási görbét nem lehet majd jól látni. Ezt pl kísérleti úton lehet meghatározni.
Hisztogram fajták:
- Normál Hisztogram: Ezt láthattuk a fenti példában. Minden egyes osztályhoz tartozó oszlop azt mutatja meg, hogy a mintából hány darab tartozik az adott osztályba (a példában hány ember tartozik egy adott idősávba)
- Cumulative Histogram: itt az a különbség, hogy egy osztályhoz tatozó oszlop nem csak azt mutatja meg, hogy hány elem tartozik oda a mintából. A Cumulative Histogram-ban minden oszlop az összes előző oszlop összege (összes előző gyakoriság összege) + az adott osztályhoz tartozó gyakoriság
Note
A Prometheus cumulative Histogram-ot használ
Histogram metrikák a Prometheus-ban: