Changes

Jump to: navigation, search

Metrics and Monitoring in swarm

29,355 bytes added, 10:53, 18 July 2019
Summary (kvantilis)
[[Docker|<< Back to Docker main]]
 
:[[File:ClipCapIt-180919-234053.PNG|280px]]
==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_totalproxy_http_request_total
1. 2018.08.19 13:12:01 - 23
2. 2018.08.19 13:12:02 - 23
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_totalproxy_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
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/<br>
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 [[Metrics_and_Monitoring_in_swarm#Prometheus_konfigur.C3.A1ci.C3.B3|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.
 
 
<br>
==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 Létezik PUSH alapú metrika gyújtés gyűjtés is.
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.
 
 
 
{{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/<br>
* pillanat vektor (instant vector)
* tartomány vektor (range vector)
PromQL nyelven kell írni a lekérdezéseket.
===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:
<pre>
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/<br>
https://statistics.laerd.com/statistical-guides/understanding-histograms.php<br>
http://www.leanforum.hu/index.php/szocikkek/167-hisztogram-2<br>
Fontos kifejezések: <br>
''distribution=eloszlás<br>
latency=eltelt idő az input és az output között bármilyen rendszerben <br>
frequency=gyakoriság<br>
cardinality=számosság<br>''
'''===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.
'''===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
:[[File:ClipCapIt-180812-234346.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<br>https://www.robustperception.io/why-are-prometheus-histograms-cumulative}} ===Apdex, egy speciális histogram===http://apdex.org/overview.html<br>https://en.wikipedia.org/wiki/Apdex<br>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 <sub>T</sub> <br>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 <sub>2</sub> = X<br>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 <sub>1</sub> = 0.72* Email rendszer: T=8, Apdex <sub>8</sub> = 0.62* Webshop: T=2, Apdex <sub>2</sub> = 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. :[[File: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.:[[File: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: :[[File:ClipCapIt-180904-221702.PNG]]   ===Histogram a Prometheus-ban===https://prometheus.io/docs/practices/histograms/<br>https://prometheus.io/docs/concepts/metric_types/<br> 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. <pre> prometheus_http_request_duration_seconds_bucket{le="0.4"}</pre>  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. <br>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. <br>A példában említett hisztogramot a következő metrikák (vödrök) alkotják: <pre>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"}</pre>  '''Speciális hisztogram metrikák'''<br>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 x<sub>2/5</sub> 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 
'''Histogram metrikák a Prometheus-ban:'''
===Summary===https://povilasv.me/prometheus-tracking-request-duration/<br>
=Prometheus architektúra=
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.
:[[File:ClipCapIt-180926-194910.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!!
:[[File:ClipCapIt-180821-201901.PNG]]
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...
</source>
{{note|Mivel csak egy manager node-ot hoztunk létre,
<pre>
"^/(sys|proc|dev|host|etc)($|/)"
</pre>
 
 
<pre>
# docker-machine ssh mg0 docker ps
--collector.filesystem.ignored-mount-points \
"^/(sys|proc|dev|host|etc)($|/)"
</pre>
 
 
Létezik egy módosított változata is a node-exporter-nek, ami képes a swarm node nevét is belerakni a metrika címkéjébe, így nem csak egy IP címet látunk majd a Prometheus-ban/Grafana-ban, ahem egy beszédes node nevet, pl: mg0
<pre>
docker service create --detach=false \
--name node-exporter \
--mode global \
--network monitor \
--mount type=bind,source=/proc,target=/host/proc \
--mount type=bind,source=/sys,target=/host/sys \
--mount type=bind,source=/,target=/rootfs \
--mount type=bind,source=/etc/hostname,target=/etc/host_hostname \
-e HOST_HOSTNAME=/etc/host_hostname \
basi/node-exporter:latest \
--path.procfs /host/proc \
--path.sysfs /host/sys \
--collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)" \
--collector.textfile.directory /etc/node-exporter/
</pre>
=Lekérdezések=
https://prometheus.io/docs/prometheus/latest/querying/basics/#gotchas<br>
A Prometheus-ban a lekérdezéseket PromQL nyelven kell írni. A lekérdezéseknek két legfontosabb eleme:
* Instant vector: A szelektronak megfelelő idősorok egy-egy értékét adja vissza egy meghatározott időpillanatra. Pl ha a selector a '''machine_memory_bytes''', akkor az összes olyan idősort vissza fogja adni, ahol a metrika alapneve machine_memory_bytes, vagyis az összes címe variánsát. Fontos, hogy minden egyes idősorhoz csak egyetlen egy értéket fog vissza adni. Ha külön nem határozzuk meg, akkor ez a legutolsó lekérdezés eredménye lesz. Az instant vector lekérdezések jeleníthetők meg gráfokon.
* Range vektor: A szelektor mellé megadunk egy idő intervallumot is. A szelektornak megfelelő idősorhoz az összes értéket vissza fogja adni amit a megadott intervallumban rögzített. Az intervallum mindig a jelenben kezdődik és az intervallum hosszával megy vissza az időben. Pl: ha a selector '''machine_memory_bytes [5m]''' akkor az összes illeszkedő nevű idősor minden felvett értékét vissza fogja adni amit az elmúlt 5 percben rögzített.
==Selector-ok==
'''===Instant vektor választó''' <br>===
Ha magunk akarunk lekérdezést írni, akkor ezt a legegyszerűbb a Prometheus webes felületén összerakni a '''Graph''' képernyőn. A képernyő tetején lévő kereső mezőbe (Expression) kezdjük el begépelni a keresett metrika nevét, ekkor fel fogja dobni az összes olyan metrikát, ami tartalmazza a beírt nevet. A legegyszerűbb selector, ha beírjunk egy metrika alap nevet, aminek vannak címke variánsai: '''machine_memory_bytes'''
Ha átkapcsolunk a Graph fülre, akkor a Prometheus a Console fülön listázott metrikákhoz ki fog rajzolni egy gráfot, ahol az adott metrika értékeit láthatjuk egy órára visszamenően, tehát itt nem csak a legutolsó értéket láthatjuk, hanem az utolsó egy óra összes értékét. Mivel a cluster-en még semmilyen valódi szolgáltatás nem fut, ezért a gráf nem túl látványos:
:[[File:ClipCapIt-180903-234741.PNG]]
Mivel összesen 4 metrika találat volt az eredeti lekérdezésre, mind a négynek kirajzolja az 1 órás grafikonját (jelenleg a négy vonal teljesen egybe esik, nem a legjobb példa)
 
 
===Range vektor választó===
A range vektor lekérdezésben a metrika alapneve után oda kell írni az intervallumot kapcsos zárójelben, aminek az értékeire kíváncsiak vagyunk. Az eredmény a selector-ra illeszkedő összes címke variáns összes értéke a megadott intervallumban csoportosítva metrika nevek szerint. Pl nézzük meg a '''machine_memory_bytes''' selector-ra illeszkedő metrikákat az elmúlt 15 másodperce:
:[[File:ClipCapIt-180904-001113.PNG]]
Láthatjuk, hogy mind a 4 megtalált metrikához (a négy cAdviser konténerből) 3-3 érték tartozik, mivel 5 másodpercenként mintavételez a Prometheus a konfiguráció alapján. A jobboldali oszlopban láthatjuk a metrika értéke után @-al elválasztva az időbélyeget.
 
 
 
==Fontos függvények és operátorok==
===rate function===
A rate függvény megmutatja range vektorokra az egy másodperce jutó változást: rate(<metrika név>[intervallum hossz])
 
Elsőnek nézzünk egy range vektort:
prometheus_http_request_duration_seconds_count{handler="/query",instance="prometheus:9090",job="prometheus"}[10s]
 
Mivel 5 másodpercre állítottuk a Prometheus adatbegyűjtését, ezért 10s-re visszamenve a jelenből, két minta lesz benne:
139 @1536269070.221
141 @1536269075.221
 
Láthat hogy a 10s ezelőtti begyűjtéskor a request-ek száma 139-volt, de szorgosan kattintgattam az ezt követő 5 másodpercben, ezért a következő begyűjtéskor már 141-volt. Vegyük ennek a range értékét, vagyis nézzük meg, hog 1 másodperce mekkora változás jutott:
rate(prometheus_http_request_duration_seconds_count{handler="/query",instance="prometheus:9090",job="prometheus"}[10s])
 
Az eredmény 0.5 lesz, tehát a 10s hosszú intervallumban 0.5-öt nőt a számláló másodpercenként.
 
 
<br>
Ha a '''range vektorunk''' selector-a nem csak egy metrikára illeszkedik, akkor a '''rate''' is több eredményt fog visszaadni, minden egyes range vektor találatra egyet.<br>
Tegyük fel, hogy van két counter típusú metrikánk (az alap nevük megegyezik, csak a címkében különböznek)
example_metric{type="Y"}
example_metric{type="X"}
 
Nézzük az alábbi range vektort:
example_metric[10s]
Ennek az eredménye a következő lesz, ha 5 másodpercenként mintavételezünk:
example_metric{type="X"} 1 @1536433370.221
2 @1536433375.221
 
example_metric{type="Y"} 5 @1536433370.221
10 @1536433375.221
 
Ha erre alkalmazzuk a '''rate''' függvényt, két eredményt kapunk:
rate(example_metric[10s])
{type="X"} 0.1
{type="Y"} 0.5
 
===aggregation operators===
Egy instant vektor összes találatára kijött metrika összegét mondja meg. Ezek a metrikák csak címkékben különbözhetnek egymástól, mivel a metrika alap nevét (a címke nélküli részt) kötelező tejesen megadni. Az instant vektor-os keresés találatai a keresésben nem megadott címkék értékeiben különbözhetnek csak egymástól.
 
Pl: ha vannak ilyen metrikáim:
prometheus_http_request_duration_seconds_count{handler="...",instance="...",job="..."}
Ha az instant vektor keresésekor csak az alapnevet adom meg (prometheus_http_request_duration_seconds_count) akkor az összes címke variánst meg fogom találni:
prometheus_http_request_duration_seconds_count{handler="/query",instance="prometheus:9090",job="prometheus"} 1
prometheus_http_request_duration_seconds_count{handler="/graph",instance="prometheus:9090",job="prometheus"} 3
prometheus_http_request_duration_seconds_count{handler="/label/:name/values",instance="prometheus:9090",job="prometheus"} 4
prometheus_http_request_duration_seconds_count{handler="/metrics",instance="prometheus:9090",job="prometheus"} 10619
prometheus_http_request_duration_seconds_count{handler="/query",instance="prometheus:9090",job="prometheus"} 168
prometheus_http_request_duration_seconds_count{handler="/static/*filepath",instance="prometheus:9090",job="prometheus"} 8
 
 
De ha pontosítom a keresést a '''handler="/query"''' címével, akkor már csak két elemű lesz a találat:
prometheus_http_request_duration_seconds_count{handler="/query",instance="prometheus:9090",job="prometheus"} 1
prometheus_http_request_duration_seconds_count{handler="/query",instance="prometheus:9090",job="prometheus"} 168
 
 
Nam most, az összes aggregation operator ezen instant vektor találatokkal csinál valamit, pl a sum(..) ezen találatok értékét adja össze:
sum(prometheus_http_request_duration_seconds_count) 10841
 
 
Továbbiak:
* sum (calculate sum over dimensions)
* min (select minimum over dimensions)
* max (select maximum over dimensions)
* avg (calculate the average over dimensions)
* count (count number of elements in the vector)
* count_values (count number of elements with the same value)
 
 
 
===Aggregation operation eredmény csoportosítása===
 
Ha a by vagy a without kulcssavakat az aggregation operátor lekérdezés mögé írunk, és megadunk ott egy címke listát, akkor az eredmény a címke lista lapján lesz csoportosítva.
<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
 
 
'''by (label list)'''<br>
Ha a by mögé megadunk egy címkét, akkor az aggregation operator elsőként csoportokat fog képezni azokból a mintákból, ahol a címke(ék) megegyeznek, és azokra fogja végrehajtani az aggregálást.
Nézzük az alábbi nagyon egyszerű példát, ahol a metrika alapnév=example_metric:
example_metric{job="A", type="X"} = 1
example_metric{job="A", type="Y"} = 2
example_metric{job="B", type="X"} = 4
example_metric{job="B", type="Y"} = 5
 
Ekkor a sum by nélküli eredménye:
sum(example_metric)
Element Value
{} 12
 
 
De ha hozzáadjuk a by (job)-ot, akkor két választ kapunk, egyet az A sum-ra, egyet a B-sum-ra:
sum(example_metric) by (job)
Element Value
{job="A"} 3
{job="B"} 9
 
 
 
'''without (label list)'''<br>
A without-al pont az ellenkezőjét mondjuk meg, hogy mi szerint ne csoportosítson mielőtt össze adná a csoportok eredményét, tehát minden más szerint csoportosítani fog. A fenti példával ekvivalens eredményt kapunk, ha a '''by (job)''' helyett '''without (type)''' -ot írunk.
sum(example_metric) without (type)
Element Value
{job="A"} 3
{job="B"} 9
 
 
<br>
==Lekérdezés példák==
 
 
Átlag válaszidő az elmúlt 5 percben <br>
A http_request_duration_seconds hisztogramnak van egy _sum és egy _count metrikája. Vegyük az összes _sum értéket az elmúlt 5 percben [5], majd vegyük ennek a
<pre>
rate(http_request_duration_seconds_sum[5m])
/
rate(http_request_duration_seconds_count[5m])
</pre>
 
=Vizualizáció: Grafana=
Ugyan a Prometheus-ban tudunk magunk lekérdezéseket írni, és bizonyos keretek között ezt a Prometheus meg is tudja jeleníteni, produkciós környezetben szükségünk van egy vizualizációs eszközre, ami a mi esetünkben a Grafana lesz.
Grafana a piacvezető Time Series DB vizualizációs eszköz. Out of the box támogatja az elterjedt TSDB-ket:
* Graphite
* Elasticsearch
* InfluxDB
* OpenTSDB
* KairosDB
* Prometheus
 
 
==Telepítés==
 
===Volume plugin használata===
A konténerek írható rétegét nem szabad írás intenzíven használni, írás intenzív alkalmazásokhoz (mint amilyen a Granafa is) volume-okta kell használni. Ehhez a már ismert '''Netshare''' volume plugin-t fogjuk használni nfs protokollal. Ezen felül a grafana konfigurációs mappáját is át fogjuk helyezni az on-demand volume megosztásra.
 
 
A Grafan adatbázis a konténeren belül a '''/var/lib/grafana''' mappában található. Ezt szimplán mount-olni fogjuk az NFS megosztás '''grafana/data''' mappájába. A konfigurációs állomány a '''/etc/grafana''' mappában van. Ezt fogjuk mount-olni az NFS megosztás grafana/config mappájába, de előtte át kell oda másolni az '''/etc/grafana''' mappa tartalmát, ugyan úgy ahogy ezt a Prometheus telepítésénél is tettük. Elsőként feltelepítjük standalone docker konténerként, majd kimásoljuk belőle a konfigurációs mappát:
 
<pre>
docker run --name grafana \
grafana/grafana:5.2.4
</pre>
<pre>
# docker cp -L grafana:/etc/grafana /home/adam/Projects/DockerCourse/persistentstore/grafana/config/
# cd /home/adam/Projects/DockerCourse/persistentstore/grafana/config/grafana/provisioning/
# mv grafana/ config/
# chmod 777 -R config/
</pre>
 
 
A használni kívánt datasource-okat (jelen esetben a Prometheus-t) vagy kézzel állítjuk be a Grafana webes konfigurációs felületén, vagy készítünk egy datasource yaml konfigurációs fájlt a '''/etc/grafana/provisioning/datasource''' mappába, így telepítéskor automatikusan létre fogja hozni a Prometheus adatkapcsolatot.
 
grafana/provisioning/datasources/datasource.yaml
<syntaxhighlight lang="C++">
apiVersion: 1
 
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
</syntaxhighlight>
 
A Grafana is a '''monitor''' nevű overlay hálózathoz fog csatlakozni, így közvetlenül el tudja érni a Promethues konténert. Mivel közös overlay hálózaton vannak, a Docker DNS fel tudja oldani a szolgáltatás nevét a konténer overlay hálózatbeli IP címére ha olyan rendszer indítja a névfeloldást, aki ugyan azon az overlay hálózaton van.
 
 
 
Ugyan így a '''grafana/provisioning/dashboards/''' mappába előre hozzáadhatunk dashboard-okat a Grafana-hoz, ami telepítés után azonnal rendelkezésre fog állni.
 
 
<br>
 
===Service létrehozása===
 
A Grafana-t ugyan úgy a monitor nevű overlay hálózathoz fogjuk csatlakoztatni. Két volume-ot fogunk felcsatolni a Netshare volume plugin segítségével, egyet a konfigurációnak, egyet pedig az adatbázisnak. Publikáljuk az '''ingress''' hálózatra a 3000-as portot.
<pre>
docker service create \
--detach=false \
--name grafana \
--network monitor \
--mount "type=volume,src=192.168.42.1/home/adam/Projects/DockerCourse/persistentstore/grafana/config/,dst=/etc/grafana,volume-driver=nfs" \
--mount "type=volume,src=192.168.42.1/home/adam/Projects/DockerCourse/persistentstore/grafana/data/,dst=/var/lib/grafana,volume-driver=nfs" \
-p 3000:3000 \
grafana/grafana:5.2.4
</pre>
 
<pre>
# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
959l8hlvh4u8 grafana replicated 1/1 grafana/grafana:5.2.4 *:3000->3000/tcp
cbg79ex3db2g portainer replicated 1/1 portainer/portainer:latest *:9000->9000/tcp
dzha5bvpjx67 node-exporter global 4/4 prom/node-exporter:v0.16.0
x035ni7e3qhi prometheus replicated 1/1 prom/prometheus:v2.3.2 *:9090->9090/tcp
z60yg7cemg7p cadvisor global 4/4 google/cadvisor:v0.28.5
</pre>
 
==Login to Grafana==
 
Mindegy is melyik node-ra került föl, az mg0 IP címével nyissuk meg az előbb publikált 3000 portot: <br>
 
http://192.168.123.141:3000/login<br>
A default user/password: '''admin/admin'''
 
Miután megadtuk az új jelszót első belépéskor a settings képernyőn landolunk, ahol megjelenik az előre hozzáadott Prometheus data source.
:[[File:ClipCapIt-180909-122943.PNG]]
 
 
==Adding dashboards==
 
===Terhelés a node-okon===
Elsőként generáljuk egy kis forgalmat a node-okon, ehhez a '''progrium/stress''' docker konténert fogjuk használni. <br>
https://github.com/progrium/docker-stress
<pre>
docker service create \
--detach=false \
--mode global \
--name loadgenerator \
progrium/stress --cpu 2 --io 1 --vm 2 --vm-bytes 128M --timeout 30s
</pre>
 
A progrium/stress mindig csak 30s-ig fog futni, de ahogy leáll a swarm újra fogja indítani, tehát pár perc után töröljük:
<pre>
# docker service rm loadgenerator
</pre>
 
===CPU idle grafikon===
Menjünk a bal oldali "+" jelre, majd "Dashboard" majd Graph (bal felső sarok). Data source-nak válasszuk ki a Prometheus-t, majd adjuk meg a következő lekérdezést:
irate(node_cpu_seconds_total{mode="idle"}[5m])
 
:[[File:ClipCapIt-180910-231059.PNG]]
 
Ezután a Time range fülön adjuk meg hogy 1 óra legyen a felbontás:
:[[File:ClipCapIt-180910-231250.PNG]]
 
Ekkor mind a 4 node-ra mutatni fogja, hogy a CPU hány százalékban idle:
:[[File:ClipCapIt-180910-231334.PNG]]
A jobb felső sarokban lévő save ikonnal mentsük el.
 
===Node Exporter Server Metrics===
https://grafana.com/dashboards/405
:[[File:ClipCapIt-180910-223918.PNG]]
Importálhatunk komplett Dashboard-okat, ami előre van gyártva. A NodeExporter metrikákhoz pl több Dashboard is készült, ilyen pl a '''Node Exporter Server Metrics''', ahol az összes node-ot akár egyszerre is láthatjuk. Az a baj, hogy a Node listában nem csak a Node Exporter-ek vannak, hanem az összes hoszt, aki a '''monitor''' nevű overlay hálózatra csatlakozik.
A node exporter-hez ebből a hosszú listából csak 4 IP tartozik
'''Range vektor választó''' <br>
=Vizualizáció: GraphanaSwarm stack=
Az egész fentebb leírt architektúrát létrehozhatjuk swarm stack-ként egyetlen egy docker compose fájlal.
===compose fájl===
'''docker-compose.yml'''
<syntaxhighlight lang="C++">
version: '3'
services:
cadvisor:
image: google/cadvisor:v0.28.5
networks:
- monitor
volumes:
- "/:/rootfs"
- "/var/run:/var/run"
- "/sys:/sys"
- "/var/lib/docker:/var/lib/docker"
deploy:
mode: global
restart_policy:
condition: on-failure
node-exporter:
image: basi/node-exporter:v1.15.0
networks:
- monitor
volumes:
- "/proc:/host/proc"
- "/sys:/host/sys"
- "/:/rootfs"
- "/etc/hostname:/etc/host_hostname"
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- "--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)"
- "--collector.textfile.directory=/etc/node-exporter/"
environment:
- HOST_HOSTNAME=/etc/host_hostname
deploy:
mode: global
restart_policy:
condition: on-failure
prometheus:
image: prom/prometheus:v2.3.2
ports:
- "9090:9090"
networks:
- monitor
volumes:
- "prometheus-conf:/etc/prometheus"
- "prometheus-data:/prometheus"
grafana:
image: grafana/grafana:5.2.4
ports:
- "3000:3000"
networks:
- monitor
volumes:
- "grafana-conf:/etc/grafana"
- "grafana-data:/var/lib/grafana"
docker Volume plugins "KVM"networks: monitor: driver: overlay
httpsvolumes: prometheus-conf: driver: nfs driver_opts: share: 192.168.42.1:/home/adam/Projects/DockerCourse/persistentstore/prometheus/config prometheus-data: driver: nfs driver_opts: share: 192.168.42.1:/home/adam/Projects/DockerCourse/persistentstore/prometheus/data grafana-conf: driver: nfs driver_opts: share: 192.168.42.1:/home/adam/Projects/DockerCourse/persistentstore/grafana/config grafana-data: driver: nfs driver_opts: share: 192.168.42.1:/home/adam/Projects/DockerCourse/persistentstore/grafana/data</syntaxhighlight> Kiemelendők: * A '''Netshare''' NFS volume-okat csak a globális '''volumes''' szekcióban lehet definiálni, mert csak a globális volumes szekciónak van '''driver''' és '''driver_opts''' paramétere. A service definíción belüli '''volumes''' szekciónak nincs. * A Netshare 0.35-ös verziójában bevezették a '''share''' paraméter kezelését. Korábbi verziókat még nem lehetett swarm stack-ben (compose) használni. A globális '''volumes''' szekcióban a volume forrását elvileg nem kell megadni, az a swarm-ra van bízva, hogy hol hozza létre, ezért nincs neki src paramétere. Az egyetlen erre használható paraméter a '''driver_opts''' share paramétere, amit a korábbi verziók még nem tudtak kezelni. (Emlékezzünk vissza, hogy a swarm service definícióban ez nem okoz gondot, mert ott a forrást is meg tudtuk adni)* Mivel a globális '''networks''' szekcióban nem adtuk meg az external paramétert, a '''monitor''' nevű overlay hálózatot minden alkalommal létre fogja hozni a swarm stack telepítése előtt, és le is fogja törölni ha töröljük a stack-et.* A node-exporter command line paramétereibe kötőjelet kell használni, és nem kell dupla macskakörmöt használni a paraméter értékének megadásakor. A "&" jelet még egy "&" jellel kell escape-elni. ===Stack telepítése=== A stack-et az alábbi paranccsal hozhatjuk létre. docker stack deploy --compose-file <yaml fájl név> <stack név>  A megadott stack nevet minden létrehozott szolgáltatáshoz hozza fogja fűzni prefix-ként, ezzel jelezve, hogy azok egy swarm stack részei. Még a monitor nevű overlay hálózat neve elég is oda fogja rakni a stack nevét.   Legyen a stack neve monitor:<pre># docker stack deploy --compose-file docker-compose.yml monitorCreating network monitor_monitorCreating service monitor_prometheusCreating service monitor_cadvisorCreating service monitor_node-exporterCreating service monitor_grafana</pre>  Ezzel létrejött a monitor_monitor nevű overlay hálózatunk, ezen felül 4 swarm service, szintén a monitor prefix-el: <pre># docker network lsNETWORK ID NAME DRIVER SCOPE...nar4kl8o8tat monitor_monitor overlay swarm</pre><pre># docker stack lsNAME SERVICESmonitor 4</githubpre><pre># docker service lsID NAME MODE REPLICAS IMAGE PORTSfb3poq1m3my0 monitor_cadvisor global 4/4 google/cadvisor:v0.com28.5 pidw51mgpc0e monitor_node-exporter global 4/4 basi/node-exporter:v1.15.0 pu4z76b6oijq monitor_grafana replicated 1/1 grafana/grafana:5.2.4 *:3000->3000/tcpterni4ylw5ca monitor_prometheus replicated 1/1 prom/prometheus:v2.3.2 *:9090->9090/SvenDowideittcp</pre>  Keressük meg az egyik node ingress hálózatbeli címét, hogy tesztelni tudjuk a Prometheus és Grafana konzolt: # docker-volumesmachine ssh worker0 ifconfig | grep -nfsA 1 eth0 | grep "inet addr" inet addr: '''<span style="color:red">192.168.123.252</span>''' Bcast:192.168.123.255 Mask:255.255.255.0
http://netshare.containx.io/docs/nfs
httpsMost lépjünk be a Prometheus-ba és a Grafana-ba. Mivel mind a kettő az NFS megosztásból szedi a beállításait és az adatbázisát is, már semmilyen beállításra nincs szükség, ezeket már korábban mind elvégeztük. * Grafana: http://netapp-trident192.168.readthedocs123.io252:3000* Prometheus: http:/en/stable-v18192.168.07/docker/install/host_config123.html252:9090

Navigation menu