Metrics and Monitoring in swarm

From berki WIKI
Revision as of 21:41, 19 September 2018 by Adam (talk | contribs)

Jump to: navigation, search

<< Back to Docker main

ClipCapIt-180919-234053.PNG


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ár, 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

A metrikát begyűjtő rendszer ezt periodikusan lekérdezi a metrikát szolgáltató rendszerbtől és a lekérdezés időpontjával együtt beírja az adatbázisába, így minden metrika úgynevezett idősort alkot a metrika adatbázisban. Pl:

 IDŐPONT         METRIKA NEVE       ÉRTÉK
  10:12   node_memory_MemAvailable   18
  10:13   node_memory_MemAvailable   17
  10:14   node_memory_MemAvailable   11

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 adatbázis kezelő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

Idősorok (time series)

A TSDB-ben idősorokat tárol el az adatbázis. Miden végpont minden metrikájához tárol egy idősort. Lekérdezéskor elmenti a metrika új értékét a lekérdezési időpontjával együtt Pl az alábbi példában 1 másodpercenként kérdezi le a roxy_http_request_total értékét:

roxy_http_request_total
1. 2018.08.19 13:12:01  -  23
2. 2018.08.19 13:12:02  -  23
3. 2018.08.19 13:12:03  -  24
4. 2018.08.19 13:12:04  -  25
5. 2018.08.19 13:12:05  -  27


Fontos, hogy az idősorokat a Prometheus végpontonként tárolja. Ha pl 20 swarm worker-em van, és mind a 20 "beszámol" a roxy_http_request_total nevű metrikáról, akkor ezek nem lesznek összemosva egy közös idősorba, hanem húsz különböző idősort (time series) fognak képezni.

NODE1: roxy_http_request_total
1. 2018.08.19 13:12:01  -  23
2. 2018.08.19 13:12:02  -  23
3. 2018.08.19 13:12:03  -  24

NODE2: roxy_http_request_total
1. 2018.08.19 13:12:01  -  6
2. 2018.08.19 13:12:02  -  7
3. 2018.08.19 13:12:03  -  10


A Prometheus adatbázisban a lekérdezéseket a Prometheus saját nyelvén, PromQL-ben kell megírni.

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.


Bár erről már beszéltünk, itt most külön kiemelem, hogy mit nevezünk a Prometheus-ban time series-nek. Minden egyes metrika minden címke előfordulási fajtájával külön idősort képez.


Beépített címkék és metrikák

https://prometheus.io/docs/concepts/jobs_instances/ Azt már említettük, hogy a Prometheus nem mossa össze a különböző végpontoktól begyűjtött mintákat, külön-külön idősorban menti el őket. De hogy éri ezt el. Úgy, hogy automatikusan két beépített címkét illeszt minden egyes begyűjtött metrikához:

  • job: A Prometheus config-ban konfigurált job neve, ami azonos konténereket fog össze. Pl cAdivsior vagy node-exporter konténerek.
  • instance: Egy job-on belül a példányneve, amit IP:port párossal ír le a Prometheus ha csak nem küld mást magáról a végpont.

Pl az alábbi metrikát a cAdvisor egyik konténere küldi. A Prometheus config-ban a job neve "cadivisor" (lást Prometheus konfig című fejezetet)

container_cpu_system_seconds_total{id="/",instance="10.0.0.12:8080",job="cadvisor"}


Ezen felül még 4 beépített idősort is automatikusan létrehoz a Prometheus minden egyes végponthoz, tehát minden instance-hoz:

up{job="<job-name>", instance="<instance-id>"}

1 if the instance is healthy, i.e. reachable, or 0 if the scrape failed.

scrape_duration_seconds{job="<job-name>", instance="<instance-id>"}

Lekérdezés ideje

scrape_samples_post_metric_relabeling{job="<job-name>", instance="<instance-id>"}

the number of samples remaining after metric relabeling was applied.

scrape_samples_scraped{job="<job-name>", instance="<instance-id>"}

the number of samples the target exposed.



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. Ezen felül nagyon sokféle metrika exporter is elérhető, amik OS szinten is képesek metrikákat szolgáltatni. Á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.


Általában nem várjuk el a swarm service-ektől hogy magukról metrikákat szolgáltassanak, sokkal inkább metrika gyűjtő rendszereket szokás beépíteni a cluster-be. A két legelterjedtebb metrika gyűjtő:

  • cAdvisor: Ez egy adott Docker démonról képes metrikákat begyűjteni (a Docker démonon futó konténerekről szolgáltat információt). Az összes konténer keretrendszert támogatja, nem csak a Docker-t.
  • node-exporter: OS szinten gyűjt metrikákat (pl CPU és Memória használat, szabad disk hely, stb..). Ez nem Docker (vagy konténer) specifikus komponens, akkor is használható ha a rendszerünknek semmi köze a konténeres világhoz.


Készíthetünk olyan alkalmazást ami metrikákat szolgáltat magáról. Ehhez a Prometheus 4 nyelven is ad API-t aminek a segítségével nagyon egyszerű Prometheus szabványú metrikákat szolgáltatni: 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. (Ez egy counter típusú metrika, erről részletesen olvashatunk majd a Metrika típusok című fejezetben.


A lekérdezésben így nézne ki:

#Total requests.
my_library_requests_total{method="get"} 23


A metrikát szolgáltató HTTP servlet elkészítésére több megoldást is kínál a Prometheus client API. Nézzünk egy példát az egyszerű Java HTTP servlet-re.

Server server = new Server(1234);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
server.setHandler(context);

context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics");
ImportantIcon.png

Note
A docker démon is tud magáról metrikákat szolgáltatni, de ez egyenlőre csak kísérleti jelleggel működik ... leírni hogy kell ...


Metrika típusok, statisztika alapok

https://www.weave.works/blog/promql-queries-for-the-rest-of-us/

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 (állítólag a következő verzióban már meglesz, most tarunk a 2-es főverziónál), ott nekünk kell tudni, hogy értelmes e amit felírunk szabály az adott metrikára.

ImportantIcon.png

Note
Ugyan a Prométeusz adatbázis nem tesz különbséget a metrika típusok között, mégis 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. Csak akkor tudunk értelmes lekérdezést írni egy metrikára, ha tudjuk, hogy mit jelent az adott metrika.


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. Megmutatja, hogy a metrika lekérdezésének a pillanatában hány darabot számoltunk össze abból, amit a metrika jelképez, pl http lekérdezések száma egy webszerverben. 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

A counter típusú metrikák neve a konvenció szerint _total postfix-el van ellátva.


A számláló abszolút értékére nem szokás támaszkodni, mivel a service újraindulásakor a számlálón nullázódik, folyton jú nodo-okat indítunk el, vagy régieket állítunk le, a service-ek jönnek, mennek. Sokkal inkább az időbeli változása a lényeg, tehát olyan lekérdezéseket (gráfokat) praktikus felírni, ami csak egy adott időszeletre vonatkozik, pl mindig csak az utolsó 5 percre. Lássunk két példát:


Az alábbi sum(<metrika név>) függvény az összes olyan már begyűjtött metrikának összegzi az értékét ahol a metrika neve és a címke az alábbi volt: batch_jobs_completed_total{job_type="hourly-cleanup"}. Azonban ha újraindul egy node, akkor a node-hoz tartozó batch_jobs_completed_total nevű számláló típusú metrika értéke nulláról fog újra indulni, így hamis képet láthatunk.

sum(batch_jobs_completed_total{job_type="hourly-cleanup"})


A rate() függvény a sum()-al ellentétben a változást számolja ki. Megmondja, hogy a megadott időintervallumban 1 másodpercre levetítve mekkora volt a változás a számlálóban: rate(<metrika név> [intervallum] ). Tehát a rate() egy csúszó ablakot használ, mindig visszanézve az időben. Ha pl 5 percre állítjuk az intervallumot, akkor legyen C1 az utoljára rögzített metrika érték, legyen C2 az 5 perccel ezelőtt rögzített első metrika érték, akkor a rate() a következő módon számolandó: (C1-C2)/300 (Az osztással megkapjuk másodpercre levetítve a változás értékét)

sum(rate(batch_jobs_completed_total{job_type="hourly-cleanup"}[5m]))


Na de mit csinál akkor a sum?? a lekérdezéseket majd külön megnézzük


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
cardinality=számosság


Mi az a Hisztogram

A Hisztogram a gyakoriság eloszlását 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/osztályokra (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 az osztályok, (amikbe be akarjuk sorolni a mintákat), legyenek 10 éves periódusok, és induljon 20-tól és menjen 100-ig, így összesen 8 osztályt kapunk. 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. Láthatjuk, hogy 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:

ClipCapIt-180812-233231.PNG


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
ClipCapIt-180812-234346.PNG
ImportantIcon.png

Note
A Prometheus cumulative Histogram-ot használ. Állítólag azért mert sokkal kevesebb erőforrásból lehet előállítani a kumulatív hisztogramot mint a simát
https://www.robustperception.io/why-are-prometheus-histograms-cumulative


Apdex, egy speciális histogram

http://apdex.org/overview.html
https://en.wikipedia.org/wiki/Apdex
Az Apdex index-el alkalmazások teljesítményét lehet mérni. A teljesítményen itt felhasználói elégedettséget kell érteni az alkalmazás válaszidejének a szempontjából, hiszen azon túl hogy egy rendszer üzemel, elérhető a felhasználó számára, semmi más nem számít, csak hogy elégedettek e a felhasználók a teljesítménnyel (válaszidővel) vagy sem. Valójában semmi más nem számít.


A metrikákon alapuló mérésekkel nehéz általános következtetést levonni a felhasználói elégedettségről az Apdex kitalálói szerint. Tegyük fel, hogy pl egy swarm cluster-ben az összes node összes alkalmazásáról összegyűjtjük a válaszidőket. De mit kezdjünk ezzel az adathalmazzal. Önmagában a válaszidőből nehéz elégedettséget levonni. Ha átlagoljuk a válaszidőket, akkor ezzel lehet hogy elveszítünk olyan információkat, ami arra utalna, hogy nagy az általános elégedetlenség.


Az Apdex az összes metrikából nyert adatot egyetlen számmá alakítja 0 és 1 között, ahol 0=mindenki elégedetlen, 1=mindenki maximálisan elégedett. Ez a szám a rendszer teljesítmény, más szóval az Apdex értéke (Apdex value)

Az Apdex érték mindig a Target válaszidő függvénye, ami az általunk megállapított, szerintünk optimális válaszideje egy alkalmazásnak: Apdex T
Tehát ha szerintünk egy alkalmazásnak a Target válaszideje 2 másodperc kéne legyen, akkor ezen alkalmazásra kiszámolt Apdex indexet így jelölik: Apdex 2 = X
Tegyük fel hogy az univerzumunk 3 alkalmazásból áll, amikre a következő Apdex Target számokat határoztuk meg (optimális válaszidők) és a következő Apdex értékek jöttek ki a mérés alapján:

  • Adatbázis: T=1, Apdex 1 = 0.72
  • Email rendszer: T=8, Apdex 8 = 0.62
  • Webshop: T=2, Apdex 2 = 0.53


A begyűjtött válaszidőkből egy speciális hisztogramot csinálunk, három nem egyenlő méretű vödörbe osztjuk az összes válaszidőt (emlékezzünk rá, hogy a histogram definíciója alapján nem kell hogy egyenlőek legyenek a vödrök):

  • Satisfied: Azon válaszok amik kisebbek, mint a Target válaszidő, vagyis gyorsabban kiszolgáltuk a felhasználókat. A response time 0 és T között van.
  • Tolerating: A válaszidő nagyobb mint T, de még az elfogadható határon belül van. A válaszidő T és F (elfogadhatatlan) között van, ahol F mindig 4*T a definíció szerint.
  • Frustrated: A válaszidő nagyobb mint F, vagyis az elfogadhatatlan kategória. A válaszidők F és végetlen között vannak.
ClipCapIt-180904-221625.PNG


Az Apdex érték kiszámolásához a histogram értékeit kell összeadni a következő módon: (Satisfied vödör darabszáma + a fele a Tolerating vödör darabszámának, és az egész osztva az összes darabbal.

ClipCapIt-180904-221645.PNG


Pl ha van 100 mintánk, ahol a Target idő = 3s, ahol 60 válaszidő van 3s alatt, 30 darab van 3 és 12 (4*3) között, és a maradék 10 van 12 fölött, akkor az Apdex:

ClipCapIt-180904-221702.PNG


Histogram a Prometheus-ban

https://prometheus.io/docs/practices/histograms/
https://prometheus.io/docs/concepts/metric_types/

A metrikák világában a hisztogramok általában válaszidőből és válasz méretből készülnek. A metrika base neve konvenció szerint megkapja a _bucket postfix-et. Ezen felül a vödör felső határát pedig az "le" címke tartalmazza. Mivel a Prometheus kumulatív hisztogramokkal dolgozik, a vödör midig 0-tól az "le" címkében megadott értékig tartalmazza a minták darabszámot. Az alábbi példában a prometheus_http_request_duration_seconds hisztogram 0-tól 0.4s-ig terjedő vödörhöz metrikáját láthatjuk.

 
prometheus_http_request_duration_seconds_bucket{le="0.4"}


Fontos, hogy a Prometheus-ban minden egyes vödör egy külön idősor. A hisztogramot a metrikát szolgáltató rendszerben előre kitalálták, előre rögzítették a vödrök méretét, ez fix, ez az időben nem változik. Pl a fenti prometheus_http_request_duration_seconds hisztogramban 9 vödröt definiált az alkotó, a legelső 0-tól 0.1-ig terjed, az utolsó meg 0-tól 120s-ig. Tehát az alkotó úgy gondolta, hogy az összes válaszidő 0 és 120 közé fog esni.
Minden egyes minta begyűjtéskor a metrikát szolgáltató rendszer elküldi a Prometheus-nak az aktuális, teljes hisztogramot, tehát a hisztogramot a Prometheus készen kapja, nem ő számolja ki. Ebből adódik, hogy minden egyes hisztogram vödör egy külön idősort alkot, hiszen minden egyes lekérdezéskor változhat a hisztogram. Tehát a _bucket-el végződő metrikák egy hisztogram darabkái. A hisztogramot alkotó minták száma időben folyton nő ahogy egyre több request-et szolgál ki a szerver, úgy egyre több mintánk lesz, ebből kifolyólag majdnem minden vödör értéke is nőni fog (kivéve az a vödör, ami olyan kicsi request időt szimbolizál, amibe nem estek bele minták. Mivel a hisztogram kumulatív, az összes ettől nagyobb válaszidőt szimbolizáló vödör értéke nőni fog). Ahogy telik az idő, egyre több válaszidő értéke (mintája) lesz a hisztogramot szolgáltató rendszernek, tehát mindig egyre több mintából állítja elő a hisztogramot, a hisztogram rudacskái minden lekérdezéskor egyre nagyobbak.
A példában említett hisztogramot a következő metrikák (vödrök) alkotják:

prometheus_http_request_duration_seconds_bucket{le="0.1"}
prometheus_http_request_duration_seconds_bucket{le="0.2"}
prometheus_http_request_duration_seconds_bucket{le="0.4"}
prometheus_http_request_duration_seconds_bucket{le="1"}
prometheus_http_request_duration_seconds_bucket{le="3"}
prometheus_http_request_duration_seconds_bucket{le="8"}
prometheus_http_request_duration_seconds_bucket{le="20"}
prometheus_http_request_duration_seconds_bucket{le="60"}
prometheus_http_request_duration_seconds_bucket{le="120"}


Speciális hisztogram metrikák
A _sum postfix-re végződő metrikában van az összes minta összege, de nem időben visszamenőleg, hanem az adott metrika begyűjtéskor aktuálisan kapott hisztogram-ban lévő minták összeg. Ezt egyfajta speciális számlálónak is felfoghatjuk, aminek az értéke szintén csak nőni tud, hiszen mindig egyre több mintából állítja elő a hisztogramot a mintákat szolgálató rendszer (pl cAdviser). Egy esetben tud nőni a _sum, ha negatív megfigyelések is lehetségesek, pl hőmérséklet esetén.

prometheus_http_request_duration_seconds_sum


A _count postfix-re végződő hisztogram metrika az összes minta darabszámát adja vissza. A fent leírt okokból ez értelem szerűen csak nőni tud.

prometheus_http_request_duration_seconds_count


Kötelezően kell legyen minden hisztogramban egy le=+Inf elem, aminek az értéke mindig megegyezik a _count metrikáéval.

prometheus_http_request_duration_seconds_bucket{le="+Inf"}


Summary (kvantilis)

Na ezt még egyáltalán nem értem. quantiles

A p-ed rendű kvantilis az a szám, amelynél az összes előforduló ismérvérték p-ed része nem nagyobb, (1-p)-ed része nem kisebb. Például az x2/5 kvantilis esetében az adatok 40%-a nem nagyobb, 60%-a nem kisebb a meghatározott kvantilisnél.

Meghatározásánál fontos az adatok sorrendbe való rendezése.

https://www.tankonyvtar.hu/hu/tartalom/tamop425/0027_MA3-7/ch01s07.html



Prometheus architektúra

Ha a pet szemléletet magunk mögött hagyjuk, akkor máris kézenfekvő, hogy számunkra irreleváns, hogy a swarm melyik node-ra fogja telepíteni a Prometheus-t (arra amelyik szerinte a legoptimálisabb), a lényeg, hogy garantáltan csak egy példány jöjjön belőle létre. Minket csak a portja érdekel, a port segítségével bármelyik node IP címével el lehet majd érni a load-balancolt ingress hálózaton. Ugyan ez igaz lesz a Grafana-ra is. A Grafana az ingress hálózaton keresztül bármelyik node IP címével eléri majd a Prometheus-t, és mi is a böngészőből az ingress hálózaton bármelyik node IP címével elérjük majd a Grafana konzolt.

Ellenben fontos, hogy a Prometheus a monitor overlay hálózatra is csatlakozzon, hogy közvetlenül el tudja érni a node-okon futó node-exporter-t és a cAdvisor-t (emlékezzünk, hogy ezen konténereknek nem nyitottunk portot a host felé, így ezek kizárólag a monitor overlay hálózaton érhetőek el). A Grafana már csak az ingress hálózatra kell hogy csatlakozzon, mert csak a Prometheus-ból végez majd lekérdezéseket.


ClipCapIt-180821-201901.PNG

Nem jó az ábra!!! A Grafana a monitor hálózatra is csatlakozik, ott éri el a Prometheus-t. Ezen felül az ingress-re is, ott érjük el kívülről. A Grafana ingress kapcsolatára a portot is rá kell írni, mert az publikálva lett!!


Itt leírni, hogy minden egyes node VM en indítani kell egy egy node-exporter-t és cAdvisor-t, és hogy melyik pontosan mit fog csinálni... ...

...


ImportantIcon.png

Note
Készíthetnénk speciális címkékkel ellátott swarm node-okat dedikáltan a Prometheus-nak és a Grafana-nak, de ez szembe menne a swarm személettel, vissza vinne minket a tehéncsordáról a háziállatos felfogás irányába. Majd a swarm tudja hogy hova a legjobb ezen konténereket rakni, ne mi akarjuk megmondani!


Cluster létrehozása

#!/bin/bash

#Create manager
docker-machine create -d kvm --kvm-network "docker-network" --kvm-disk-size "5000" --kvm-memory "800"  mg0


#Init cluster
docker-machine ssh mg0 docker swarm init --advertise-addr $(docker-machine ip mg0)

#Join managers
WORKER_TOKEN=`docker-machine ssh mg0 docker swarm join-token -q worker`


#Create workers
for i in 0 1 2 3; do 
	docker-machine create -d kvm --kvm-network "docker-network" --kvm-disk-size "5000" --kvm-memory "800"  worker$i
	docker-machine ssh worker$i docker swarm join --token $WORKER_TOKEN $(docker-machine ip mg0) --advertise-addr $(docker-machine ip worker$i)
done


# eval $(docker-machine env mg0)
# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
4nnp0k53i8739t1wxrp874wxa     worker1             Ready               Active              
lu4000w394kl622c3g211yg31     worker0             Ready               Active              
nx6kmd9qj55yc4f3fwpbhq60q     worker2             Ready               Active              
qvnnm8mvokpn662ooliqko3zv *   mg0                 Ready               Active              Leader
t2ng6ylwcgvq4ssx4cvf71lfi     worker4             Ready               Active              
# docker network create -d overlay monitor
# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
...
akhr117qs46o        monitor             overlay             swarm

Node exporter

Ezt nem lenne muszáj konténerként telepíteni, futhat natívan is, de egyszerűbb ha konténerként fut, mert a swarm így automatikusan ki tudja rakni minden node-ra, nem nekünk kell. Ha konténerként fut, akkor a host OS szinte minden porcikáját fel kell mountolni a node-exporter konténernek, hiszen a le kell tudja kérdezni a host OS állapotát. Ez azért sem nagy biztonsági kockázat, mert ha swarm-ot fut