added szoveg

This commit is contained in:
Torma Kristóf 2019-12-04 16:00:50 +01:00
parent a4419f15d4
commit 1265aebafa
Signed by: tormakris
GPG Key ID: DC83C4F2C41B1047
9 changed files with 457 additions and 14 deletions

View File

@ -28,7 +28,7 @@ A szakdolgozat keretein belül a Knative sajátosságait vizsgálom, összehason
%---------------------------------------------------------------------------- %----------------------------------------------------------------------------
\chapter*{Abstract}\addcontentsline{toc}{chapter}{Abstract} \chapter*{Abstract}\addcontentsline{toc}{chapter}{Abstract}
This document is a \LaTeX-based skeleton for BSc/MSc~theses of students at the Electrical Engineering and Informatics Faculty, Budapest University of Technology and Economics. The usage of this skeleton is optional. It has been tested with the \emph{TeXLive} \TeX~implementation, and it requires the PDF-\LaTeX~compiler. Same in English.
\vfill \vfill

View File

@ -2,4 +2,6 @@
\chapter*{\koszonetnyilvanitas}\addcontentsline{toc}{chapter}{\koszonetnyilvanitas} \chapter*{\koszonetnyilvanitas}\addcontentsline{toc}{chapter}{\koszonetnyilvanitas}
%---------------------------------------------------------------------------- %----------------------------------------------------------------------------
Ez nem kötelező, akár törölhető is. Ha a szerző szükségét érzi, itt lehet köszönetet nyilvánítani azoknak, akik hozzájárultak munkájukkal ahhoz, hogy a hallgató a szakdolgozatban vagy diplomamunkában leírt feladatokat sikeresen elvégezze. A konzulensnek való köszönetnyilvánítás sem kötelező, a konzulensnek hivatalosan is dolga, hogy a hallgatót konzultálja. A szakdolgozatban ismertetett eredmények a Budapesti Műszaki és Gazdaságtudományi Egyetem Villamosmérnöki és Informatikai Kar Balatonfüredi Hallgatói Kutatócsoport szakmai közössége keretében jöttek létre a régió gazdasági fejlődésének elősegítése érdekében. Az eredmények létrehozása során figyelembe vettük a balatonfüredi központú Rendszertudományi Innovációs Klaszter által megfogalmazott célkitűzéseket, valamint a párhuzamosan megvalósuló EFOP 4.2.1-16-2017-00021 pályázat támogatásával elnyert „BME Balatonfüredi Tudáscentrum” térségfejlesztési terveit.
A kutatás az Európai Unió támogatásával, az Európai Szociális Alap társfinanszírozásával valósult meg (EFOP-3.6.2-16-2017-00013, Innovatív Informatikai és Infokommunikációs Megoldásokat Megalapozó Tematikus Kutatási Együttműködések).

17
src/content/closing.tex Normal file
View File

@ -0,0 +1,17 @@
\chapter{\"Osszefoglal\'as}
\section{K\"ovetkeztet\'esek}
A méréseim alapján számos következtetést le lehet vonni a Knative és a Kubeless skálázási mechanizmusairól. Tisztán látható, hogy a pánik skálázásnak hála a Knative gyorsan képes reagálni a hirtelen érkező nagy terhelésre. Ennek gyakorlati haszna egy új szolgáltatás bevezetésnél lehet, ugyanis ilyen esetekben rövid idő alatt kell lefoglalni a szükséges erőforrásokat. Az is megfigyelhető, hogy a stabil, vagy lassan változó terhelésre nehézkesen változik. Ez az ObservedStableConcurrency belső érték mozgó átlag jellegéből adódik. Például, ezen érték csökkenését kiváltó esemény akár fél perccel korábban is lehetett. Továbbá, például egy szolgáltatás inkrementális bevezetése esetén érkező, lassan, de folyamatosan növekvő terhelés esetén előfordulhat, hogy később hozza létre a szükséges Podokat a Knative, mint kéne.
A Kubeless a Knative-val szemben sokkal egyszerűbb skálázási mechanizmust alkalmaz. Nem számít, hogy a terhelés milyen karakterisztikával éri el a skálázási határt, ha a processzor használat meghaladja az előre beállított értéket, felskálázza a függvényt. Eme egyszerűség hátránya, hogy nem képes gyorsan reagálni a rövid idő alatt megnövekedő terhelésre. Fontosnak tartom megemlíteni, hogy annak ellenére, hogy ez az egyszerűbb rendszer, a Knative esetében nem ütköztem olyan hibába, amely meggátolta volna a rendszer használatát.
\section{Tov\'abbi kutat\'asi lehetős\'egek}
Az általam elvégzett munka számos irányba folytatható. Érdekes lehet ugyanezen méréseket elvégezni olyan klaszteren, amelynek több Worker is tagja. Ez \'altal a Workerek k\"oz\"otti \"utemez\'es elem\'ez\'es\'ere is lehetős\'eg ny\'ilik.
Az elkészített Python programok és bash szkriptek felhasználhatók akár a Knative további mérései során, vagy kisebb adaptációkkal könnyen felhasználható másik rendszerek mérésére. Hasonlóan, az eszközkészlet továbbfejlesztése, komplexebb ábrák, azok finomítása hasznos és érdekes további fejlesztési irány lehet.
\section{Tapasztalataim}
Számomra kifejezetten érdekes és hasznos volt a féléves munka. Nem csak egy új rendszerről tanultam sokat, de megtanultam, hogy érdemes automatizálni egy komplex munkafolyamatot. Én a továbbiakban legszívesebben ebbe az irányba dolgoznék a továbbiakban.
%TODO remove
\cite{Meme}

View File

@ -0,0 +1,22 @@
\chapter{F\"uggv\'enyek l\'etrehoz\'asa}
A rendszerek sajátosságai miatt ugyanazt a kódot nem lehet változtatás nélkül felhasználni a két eltérő rendszerben. Mindkét rendszerre két tesztfüggvényt valósítottam meg. Az egyik célja a lehető legrövidebb válaszidő és a legnagyobb áteresztőképesség. A másik célja a kérésenként nagyobb processzorterhelés generálása.
Az első egy Go nyelven megvalósított tesztfüggvény, amely a meghívás után “Hello Go!” szöveggel tér vissza. A Kubeless rendszerhez írt függvény szignatúrája egyezik a korábban bemutatott egyszerű “Hello World!” függvényével. Függőségként importálni kell a Kubeless sztenderd könyvtárát.
%TODO
<hello-go Dockerfile ide>
Knative rendszerben szükség van a Go sztenderd könyvtárban megtalálható HTTP szerver implementációra, valamint egy belépési függvényre, amely elindítja a webszervert és beköti a függvényünket úgy, hogy az alapértelmezett URL, ahol elindul a webszerver, az ide érkező kéréseket továbbítsa neki. Mivel a Knative-ba Docker Image-eket lehet telepíteni, ezért azt is létre kell hozni. Annak érdekében, hogy a végső Image a lehető legkisebb méretű legyen, a Go program binárissá fordítását külön végezzük el, a végső Image-be csak bemásoljuk azt. Erre a Docker ad eszközt, az úgynevezett multi-stage buildek segítségével. Ez azt jelenti, hogy egy külön végrehajtási láncot leírva lefordítjuk a kódot, majd a végső Image-be csak bemásoljuk a fordítással végzett konténer Image-éből. Az elkészült Image-et a Docker Hubra feltöltöttem, hogy ne kelljen minden frissen telepített Workernek megépítenie az Image-et.
A várhatóan nagyobb processzorterhelést generáló függvényként egy Python nyelven implementált prímszám számoló szerepelt. E függvény viselkedése egyezik mindkét rendszerbe telepített verzió esetében, csupán a bemeneti érték kinyerése tér el. A függvény erről a bemeneti értékről dönti el, hogy az prímszám-e. Kubeless esetében a Go-val ellentétben nincs szükség semmilyen függőség megjelölésére, a megírt függvényt egyből lehet telepíteni.
A Knative esetében szintén eltérő módon érdemes Docker Image-et készíteni a megírt függvényből. Szükség van a Flask nevű könyvtárra, amely segítségével webes alkalmazásokat lehet készíteni Pythonban. Használata igen hasonló a Go-ban megtalálható implementációhoz. Úgynevezett dekorátor segítségével lehet a Flask számára jelezni, hogy az adott függvény milyen URL meghívásakor fusson le, valamint a használni kívánt port számát is itt lehet megadni. A Docker Image építése során multi-stage build használatára nincsen szükség, hiszen a Python értelmezőnek mindenképpen jelen kell lennie a végső Image-ben is. A Flask telepítése mellett úgy döntöttem, hogy a gunicorn Pythonban implementált webszervert is telepítem, valamint azt használom, mint webszervert a Docker Image-ben. Használatának előnye, hogy képes kihasználni a Python által nyújtott multiprocessing lehetőségeket, amely azt jelenti, hogy több Python értelmezőt indítva, több folyamat használatával jobb teljesítményt lehet elérni, mint több szál használatával, ugyanis a Python értelmező egyszerre egy szálon futó programkódot értelmez.
%TODO
<isprime-python skálázós service YAML ide>
Minden Knative függvényhez definiáltam egy-egy YAML állományban egy olyan Service-t, amelyhez tartozó Podok számát nullára képes leskálázni a rendszer, valamint egy konkurencia alapú skálázást használó Service-t.
Az elkészített függvényen, valamint a Docker Image-eket leíró Dockerfile-okat Git verziókezelőrendszerrel kezeltem, a létrehozott repository-t a GitHub szolgáltatásba feltöltöttem. Ez lehetővé tette a Travis Continuos Integration/Continuos Delivery rendszer használatát. Ezt arra használtam, hogy a változások nyugtázása után, valamint azok GitHubra történő feltöltése után a Docker Image-ek automatikusan épüljenek meg, valamint kerüljenek fel a Docker Hubra. Fontos, hogy ez nem feltétlen jelenti, hogy a Kubernetesben éppen futó, vagy később létrejövő Podok a legfrissebb Image-et fogják használni. Ahhoz szükség van vagy a latest nevű címkét használni, vagy az ImagePullPolicy nevű opciót bekapcsolni a Knative Service, vagy Kubernetes Deployment definiálásánál.
Az elkészített függvények Kubelessbe telepítése a korábban telepített parancssori interfész segítségével lehetséges. A függvény telepítése, ahhoz http végpont csatolása, valamint a skálázás létrehozása különálló parancs. Skálázás esetében a processzor limit alkalmazása a függvény telepítését végző parancs argumentumaként adható meg. Ebből adódóan skálázás esetén nem lehet csak a skálázás telepítését végrehajtó parancsot kiadni. A Kubeless függvények telepítését megkönnyítendő, elkészítettem egy bash nyelven írt szkriptet, amely paramétereként elvárja a függvény és az állomány nevét, ami tartalmazza azt, illetve a futtató környezet nevét és azt, hogy kell-e skálázás. Ezek alapján kiadja a szükséges parancsokat helyesen paraméterezve. Ezáltal a parancssori interfész helyes használatát gyorsabbá és könnyebbé tettem.

136
src/content/preparation.tex Normal file
View File

@ -0,0 +1,136 @@
\chapter{M\'er\'esi k\"ornyezet ismertet\'ese}
\section{Topol\'ogia}
A mérési infrastruktúra kialakításánál a fő szempont a potenciális szűk keresztmetszetek elkerülése volt, ennek okán a méréseket három nagy teljesítményű szerveren végeztem. A Kubernetes klaszter egy Masterből és egy Workerből állt, a harmadik számítógépen pedig a mérőeszközök futottak. Az így kialakított mérési klaszter előnye, hogy az egyik gépen futó, nagy erőforrás igényű folyamatok nem vesznek el egy másik gépen futó folyamattól erőforrást. Több Kubernetes Worker használatára volt lehetőség, de mivel egyszerre egy mérés futott, valamint a Workerek közötti elosztást nem volt cél vizsgálni, egyet is elégségesnek ítéltem.
%TODO
<szép ábra a fizikai klaszterről>
A számítógépek két tíz gigabites hálózati interfészen keresztül is össze vannak kötve. Egyiken keresztül csatlakoznak az internetre, ezen az interfészen publikus IP címmel rendelkeznek. A másikon csak egymást érik el, itt privát IP címük volt. Mindkét interfészen egy Layer 2-es szórási tartományban voltak. Szakdolgozatom elkészítése során több klaszterrel is dolgoztam, melyek fizikailag nem feltétlen voltak egy switchre bekötve, viszont ez legrosszabb esetben is csak minimálisan befolyásolhatja a méréseket.
\section{Mérési környezet automatizált telepítése}
\subsection{Kubernetes telep\'it\'ese}
Egy Kubernetes klaszter létrehozásához szükség van egy Master és legalább egy Worker telepítésére. A mérésekhez használt szerverek úgy kerültek telepítésre, hogy a root felhasználó a klaszter bármely másik számítógépét eléri ssh-n a magán hálózaton keresztül, jelszó nélkül. Az automatizmus elkészítéséhez ezt felhasználtam. További megkötés, hogy a telepítő programot a létrehozni kívánt Master-en kell futtatni, a Worker-ek IP címének, vagy hosztnevének listáját pedig egy tömbben kell megadni. A méréseket az Ubuntu operációs 18.04-es verzióján végeztem, ez is fontos megkötés, ugyanis a Linux disztribúciókon elérhető csomagkezelő, valamint egyéb eszközök eltérhetnek.
A Kubernetes szoftver előtt telepítésre kell kerüljön a Docker a klaszter minden számítógépére. Ezt az Ubuntuban elérhető apt csomagkezelővel lehet telepíteni. Bár az alapértelmezett csomaggyűjteményben benne van a Docker egy verziója, ez a mérések megkezdésekor egy már nem támogatott verzió volt, ezért szükség volt a Docker fejlesztői által fenntartott csomaggyűjtemény telepítésére. Ezeket a lépéseket bash szkriptnyelven írt program segítségével lehet automatizálni. A majdani Masterre a telepítést parancsok szekvenciális végrehajtásával lehet, a Workerekre pedig ugyanezen parancsok ssh sztenderd bemenetére irányítva lehet végrehajtani.
A Kubernetes telepítése előtt az operációs rendszer lapozófájlját ki kell kapcsolni, ugyanis a Kubernetes csak akkor működik, ha a hostgépen nincs swap. Ezt egy paranccsal, valamint a swap a bekapcsoláskor betöltött partíciók közüli eltávolításával lehet elérni.
A Docker telepítése után a Kubernetes rendszert kezelő csomagok telepítése szükséges hasonló módon. A klaszter létrehozásához a kubeadm-et választottam, ugyanis az a referencia implementációja a Kubernetesnek. Az ebben a lépésben szükséges csomagok nem elérhetőek az alapértelmezett csomaggyűjteményben, így mindenképpen szükség van a Kubernetes fejlesztői által fenntartott csomaggyűjtemény telepítésére. Fontos, hogy mivel a Docker legújabb verziója került telepítésre, meg kell adni a kubeadm-nek, hogy ne ellenőrizze a telepített Docker verzióját. Ez nem jelent problémát, ugyanis a Docker API Kubernetes által használt része nem változott a legfrissebb, valamint a Kubernetes által ellenőrzött legfrissebb verzió között. Szintén fontos, hogy pontosan az 1.15.4-es verzió került telepítésre, ugyanis a mérések kezdetekor kiadott legfrissebb verzió -1.16- annyira új, hogy sem a Knative, sem a Kubeless nem támogatják, nem is működtek, ha 1.16-os verziójú klaszterbe próbáltam őket telepíteni.
A Master node telepítése során a kubeadm futtatásán, valamint a klaszter eléréséhez szükséges fájlok a felhasználó könyvtárába másolásán kívül egyéb teendő nincs, ugyanis Weavenet hálózati modul kerül később telepítésre. Miután a Master node sikeresen települt, a kubeadm eszköz segítségével ki kell nyerni a Workerek csatlakozásához szükséges tokent, valamint az openssl eszköz segítségével a Master nyilvános kulcsának hashét.
A Worker node telepítése során a két kinyert értéket, valamint a Master IP címét meg kell adni a kubeadm-nek.
Miután a klaszter minden tagja telepítésre került a további lépéseket a kubectl eszközzel lehet végre hajtani, ami a Masterre került telepítésre. Ahhoz, hogy a klaszterben lévő Podok kommunikálni tudjanak, szükség van egy hálózati beépülő modulra. Több ilyen létezik, szakdolgozatom során a Weavenetet választottam egyszerűsége miatt. Telepítése egy YAML leíró állomány applikálásával lehetséges.
\subsection{Kubeless telep\'it\'ese}
A Kubeless telepítése négy lépésből áll. Először a metrics-server nevű komponens telepítésére kerül sor. Erre a Kubeless által használt Horizontal Pod Autoscaler miatt van szükség, ugyanis ez a komponens gyűjti számára a metrikákat a Podokról. Ennek telepítése nem csak a fejlesztők által elkészített YAML állomány applikálásából áll, ugyanis a metrics-server alapértelmezés szerint mutual TLS protokollal titkosítja a kommunikációját a Kubernetes klaszterrel. Erre nincs szükség ebben a klaszterben, ezért ki lehet kapcsolni ezt a viselkedést, amit egy kapcsolóval lehet megtenni. Ez jól automatizálható sed program használatával. A módosított YAML fájlt már applikálni lehet.
Ez után a második lépés az Nginx Ingress Controller telepítése. Itt nincs választási lehetőség, ugyanis a Kubelessbe ez a függőség erősen be van kötve. E komponens telepítéséhez két YAML állományt kell applikálni. Azért kettőt, mert van lehetőség menedzselt Kubernetesbe, valamint saját klaszterbe is telepíteni az Nginx Ingress Controllert. A két állomány közül az egyik minden Kubernetes környezet használata esetén alkalmazásra kell kerüljön, a másik pedig specifikus a felhasználó által használt Klaszter típusához, például Azure Kubernetes, vagy Google Container Engine és saját Kubernetes klaszterekhez külön-külön YAML állomány tartozik.
A Kubeless könnyebb kezelése érdekében a harmadik telepítésre kerülő komponens a kubeless parancssori interfész. Ezt a programot már a fejlesztők lefordították, így csupán a megfelelő verzió beszerzése szükséges, annak egy olyan könyvtárba mozgatása, ahol a bash parancssori értelmező keresi a futtatható programokat, például a /usr/local/bin/ könyvtárba.
Negyedik és utolsó lépésként a Kubeless klaszterbe telepítésére kerül sor. Ehhez létre kell hozni egy új névteret a kubectl segítségével. Ez után lehet applikálni a Kubeless fejlesztői által elkészített YAML állományt.
Az itt leírt lépések bash szkript segítségével automatizálhatók.
\subsection{Knative telep\'it\'ese}
A Knative telepítése kevesebb komponens feltelepítéséből áll, azok telepítése viszont bonyolultabb. A rendszer telepítése előtt installálni kell az Istiot. Ezt a helm nevű Kuberneteshez készített csomagkezelő rendszer segítségével lehet, viszont a helmet is installálni kell. Ez az Ubuntu rendszerben lévő snap csomagkezelővel telepíthető. A snap abban különbözik az apt-tól, hogy az általa telepített csomagok és a függőségeik a rendszercsomagoktól és a rendszerben jelen lévő osztott könyvtáraktól függetlenek, de hatással lehetnek a rendszerre.
A helm telepítése után inicializálni kell, amely az úgynevezett Tiller a Kubernetesbe telepítését, valamint információegyeztetést a Tiller és a helm között jelenti. Viszont ahhoz, hogy a Tiller a klaszterben a kívánt módosításokat el tudja végezni meg kell neki adni a megfelelő jogosultságokat. Erre úgy van lehetőség, hogy létre kell hozni egy új, úgynevezett Service Accountot, amely hasonlóan viselkedik a felhasználói fiókokhoz, viszont ezt Podokhoz lehet rendelni. A létrehozott Service Accounthoz pedig a cluster-admin jogosultságot kell rendelni. Ennél lehet kevesebb jogot adni a Tillernek, viszont egyetlen felhasználója lesz a klaszternek, így nincs szükség finomhangolt jogosultságkezelésre. Csak e két lépés után lehet inicializálni a helmet, valamint a Tillert.
Az Istio telepítésének megkezdése előtt létre kell hozni az általa bevezetett új objektumtípusokat, valamint egy külön névteret, ahova az Istio rendszer saját objektumai kerülhetnek. Ez számos YAML állomány applikálását jelenti. Ez után az Istio rendszert telepítő YAML állományt ki kell generáltatni a helmmel. A generálásnál lehetőség van megadni, az Istio mely komponensei ne települjenek. Nincs szükségünk például monitoring rendszerre, telemetria és jogosultságkezelő rendszerre. Ezeket parancssori paraméterrel lehet megadni. A generálás után létrehozott YAML fájl által leírt módosítások végrehajtását a megszokott módon kell végrehajtani.
Miután az Istio feltelepült, a Knative által bevezetett objektumtípusok létrehozása következik. Ezt a lépést kétszer kell végrehajtani egy a fejlesztők által ismert hiba miatt. Az első végrehajtás során néhány objektumtípus nem jön létre, másodszorra viszont ezek is létrejönnek, és a már létező objektumtípusok nem módosulnak. Végül a Knative rendszer telepíthető a fejlesztők által elkészített YAML állomány applikálásával hasonlóan a korábbi rendszerekhez.
\section{M\'er\'esi eszk\"oz\"ok kiv\'alaszt\'asa}
Számos http végpontok teljesítményének mérésére szolgáló eszköz létezik. A használt eszközök kiválasztása előtt fontos megnevezni a szempontokat, amik alapján a használt eszközök kiválasztásra kerültek.
A legfontosabb, hogy a ráta, amivel a kéréseket képes generálni legalább érje el a mérni kívánt http végpont áteresztőképességét. Amennyiben ez nem teljesül, az adott eszközt nem érdemes használni.
Szintúgy fontos szempont, hogy az eszköz képes legyen minden visszaérkező válaszról információt valamilyen automatikusan feldolgozható formátumban - például csv, vagy xml - menteni. Ez azért fontos, mert a mérések elvégzése és az adatok feldolgozásának automatizálása cél volt, ha ezt egy eszköz nem támogatja, nem használható a mérések során.
A végső szempont a megfelelő dokumentáció elérhetősége. Hiába felel meg egy eszköz mindkét korábban részletezett szempontnak, amennyiben nem érhető el hozzá dokumentáció, egyrészt a funkcióinak teljes tárháza sem feltétlen megismerhető, működésének elsajátítása pedig aránytalanul nehéz lehet.
A megfelelő mérési eszköz kiválasztásához számos eszközt megvizsgáltam.
\subsection{Wrk}
A wrk egy C-ben írt, nyílt forráskódú http teljesítménymérő szoftver. Többszálú designjának köszönhetően nagy sebességgel képes generálni a kéréseket. A használt kapcsolat objektumok és szálak száma parancssori kapcsoló segítségével beállítható, valamint működésének bizonyos aspektusai Lua szkriptnyelven testreszabhatók. Egyetlen hátránya, hogy bár a kimeneti formátumot Lua-ban írt szkript segítségével testre lehet szabni, nincs lehetőség minden kérés, vagy bizonyos időközönként átlagolt részeredmény exportálására. Mivel a wrk az általam vizsgált megoldások közül az egyik legrégebb óta fejlesztett, a hozzá elérhető dokumentáció kitér a gyakran előforduló problémákra, valamint a szkriptelést megkönnyítik a fejlesztők által előre elkészített példák. A wrk a mérés végeztével egyszer menti a másodpercenkénti átlagos kérések számát, amire érkezett valamilyen válasz, valamint egyebek mellett az átlagos kérleltetést, amivel a válasz megérkezett.
Emiatt a wrk nem volt alkalmas a mérések elvégzésére.
\subsection{Hey}
A hey egy Go nyelven írt, nyílt forráskódú http terhelés generáló. Eredetileg az ApacheBench cseréjére hozták létre, emiatt parancssori interfésze igen hasonló. Mivel Go-ban készült, az általa elérhető teljesítmény potenciálisan nagy. A használt kapcsolat objektumokat, valamint esetleges ráta limitet parancssori kapcsolóval meg lehet adni. A megadott limit kapcsolat objektumonként értelmezett. Tehát százas ráta limit esetén két kapcsolat használatával a hey által másodpercenként generált kérések száma kétszáz. Lehetőség van a hosztnév fejléc, valamint a kérés törzsének megadására, szintén parancssori kapcsolóval.
Alapértelmezés szerint a hey is hasonló összefoglalót generál, mint a wrk, viszont azzal ellentétben a hey képes minden kérésről exportálni többek között, hogy az indítástól kezdve mikor és milyen késleltetéssel ért vissza, valamint a szerver milyen http kóddal válaszolt. Hátránya viszont, hogy egyszerre csak tízmillió választ képes tárolni, amely hosszabb mérések esetén azt jelenti, több rövidebb almérésre kell bontani a mérést. Bár a hozzá elérhető dokumentáció csak az elérhető parancssori kapcsolók, valamint azok paramétereiig terjed ki, belső működése egyszerűsége okán ennél többre nincs szükség a használatához.
A leírtak miatt úgy döntöttetem, a mérések során a hey-t használom.
\subsection{Loadtest}
A Loadtest egy Javascript nyelven, Node.Js környezetben írt nyílt forráskódú http teljesítménymérő. Lényeges előnye a hey-jel szemben, hogy a kérések kiküldése előtt nem várja meg az adott konkurencia objektum, hogy megérkezzen a válasz. Jelentős hátrány, hogy csak egy szálat használ, így az általa generált másodpercenkénti kérések száma jelentősen alacsonyabb, mint az általam vizsgált többi eszközé. Emellett a Loadtest is csak a mérés végeztével generál egy összefoglaló riportot, nem képes a kérésekről adatok exportálására. A hozzá elérhető dokumentáció alapján használata egyszerű, valamint a belső működés könnyedén megérthető. Ezek miatt a Loadtestet nem találtam alkalmasnak a mérések elvégzésére.
\subsection{Apache Jmeter}
Az Apache Jmeter, vagy Jmeter egy Java 8-as verziójában íródott, nyílt forráskódú, testre szabható webes teljesítménymérő. Fő tulajdonsága, hogy saját mérési tervet lehet segítségével összeállítani, majd végrehajtani azt. A mérési tervet egy grafikus felületen lehet összeállítani. Lehetőség van definiálni több felhasználói csoportot, ahonnan a terhelés érkezik, valamint az egyes felhasználók által küldött paraméterek is testre szabhatók. Egy méréshez legalább egy felhasználói csoportot meg kell adni, valamint http végpont teljesítményének mérése esetén egy HTTP Request objektum definiálása szükséges. Ha az eredményeket látni akarjuk, akkor a megtekintés szerint kívánt formátumú Listenert kell definiálni. Fontos, hogy http fejlécek küldése esetén még hozzá kell adni egy HTTP Header Manager komponenst, amelyben tetszőleges számú fejlécet lehet definiálni kulcs-érték párban. A Jmeter képes grafikonon ábrázolni az érzékelt késleltetés időbeni alakulását, valamint minden kérésről exportálni tudja többek között a kapott http státusz kódot, a mért késleltetést, valamint a kérés küldésének pontos idejét. Mivel egy Javaban írt programról van szó, a teljesítménye jelentősen függ a Java virtuális gép számára elérhető memóriától, valamint a használt Garbage Collector algoritmustól.
A Jmeter igen elterjedt szoftver, viszont kifejezetten bonyolult, szerencsére a hozzá elérhető dokumentáció az összes általam vizsgált eszköz közül a legrészletesebb. Mivel a Jmeter működése eltér a hey-től, valamint a kritériumoknak megfelel, úgy döntöttem a méréseket mindkét eszközzel elvégzem.
\section{M\'er\'esek automatiz\'al\'asa}
A mérőeszközök kiválasztása után magukat a méréseket dolgoztam ki. Az egyértelmű volt, hogy konstans terhelésű mérést mindenképpen kell végezzek. A Kubeless esetén, mivel skálázása csak a cpu terheléstől függ, a skálázás megfigyelésére az ilyen típusú mérések elégségesek lehetnek. Ezzel szemben a Knative konkurencia alapú skálázásának megfigyelésére a bemeneti oldali konkurens kérések folyamatos növelése az előző típusú mérés mellett érdekesnek bizonyulhat.
Mivel a méréseket nem egyszerre végeztem, valamint a mérések elvégzéséhez a hey esetében a megfelelő parancssori kapcsolók lánca hosszú, szükségét láttam annak, hogy legalább a hey esetében egy bash szkript segítségével automatizáljam a mérések elvégzését. A Jmeter esetében erre nincs szükség, hála az előre elkészíthető mérési terveknek.
A bash szkript megírásánál a hey automatizált telepítése is fontos volt, ugyanis a munkám során több klaszteren is dolgoztam. Annak érdekében, hogy a mérések paraméterei testre szabhatók legyenek, a
\begin{itemize}
\item mérendő függvények nevét,
\item használandó connection objektumok számát,
\item a mérés időbeni hosszát,
\item másodpercenkénti kérések számára megszabott limitet,
\item valamint a cél IP címét és port számát külön változókban tároltam.
\end{itemize}
A mérendő függvények nevét egy tömbben tároltam, így egymás után több mérés is elvégezhető ugyanazon paraméterekkel. A mérés típusát egy parancssori kapcsolóval lehet kiválasztani. Annak érdekében, hogy a szkript használatát kényelmessé tegyem, úgy döntöttem, mindkét típusú mérést el lehet végezni egy futtatással. A szkript elkészítésénél igyekeztem figyelni arra, hogy új típusú mérés bevezetéséhez ne legyen szükséges olyan részeket módosítani, amik nem kapcsolódnak közvetlen az új funkcionalitáshoz.
%TODO
<bash szkript részlet, for típusú mérésről>
A fenti kódrészleten látszik, hogy a heyben lévő maximum lekérdezési limit miatt a konstans terhelést generáló méréshez a hey többszöri futtatására van szükség. Látható, hogy a Kubeless-be és a Knative-ba telepített függvények meghívása eltér nem csak az alkalmazott http metódusban és a hosztnév sémájában, de a Content-Type fejléc, melynek értékét a T kapcsolóval lehet megadni, megléte is különbözik.
%TODO
<bash szkript részlet, cilmb típusú mérésről>
Mint az a fenti kódrészleten látszik, a növekvő terhelésű mérés implementációja igen hasonló az egyenletes terhelésűhöz. A hey működését kihasználva, a rps kapcsoló segítségével beállított limit nem változik a mérés során, csupán a connection objektumok száma emelkedik.
\section{M\'er\'esi eredm\'enyek automatiz\'alt elemz\'ese}
Egy mérés eredményeként a mérés típusától függően akár több, nagy méretű csv állomány keletkezik. Ezen fájlok feldolgozása függ attól, hogy azt a Jmeter vagy a hey generálta. A fájlok kézi feldolgozása nyilvánvalóan lehetetlen. Az is előfordulhat, hogy már korábban feldolgozott méréseket egy új szempontból is fel kell dolgozni. Ez elő is fordult, ugyanis a program első verziója még nem volt képes az észlelt késleltetés feldolgozására. Szerencsére a Python programnyelv ilyen feladatok elvégzésére kiváló választás.
A program célja az volt, hogy az összes összegyűjtött mérésből generáljon diagrammokat, melyeken ábrázolja a függvény által feldolgozott kérések másodpercenkénti számát, valamint később a másodpercenkénti átlagos késleltetés időbeni alakulását a mérés során. Szintén a munka közben merült fel az igény, hogy a Knative Autoscaler komponensének naplófájlja alapján az általa érzékelt konkurencia és a létrehozott Podok számának alakulását is nyomon kövesse a program.
Mivel egy méréshez több állomány is tartozhat, az egybe tartozó állományok egy mappába kerültek. A mappa neve reflektálja a mérőeszköz nevét, a mért rendszer és függvény nevét. Például a jmeter-knative-hello-scale-1 egy lehetséges mappanév. Az így strukturált adatok feldolgozása nem függ másik méréstől. A program indulása után az adatokat tartalmazó mappákat kigyűjti, majd a jmeter kulcsszót tartalmazó mappák feldolgozását továbbítja a Jmeter kimenetét feldolgozni képes objektumnak. Az összes többi könyvtárat pedig a hey által generált állományok feldolgozásáért felelő objektumnak továbbítja. Mivel a Knative Autoscaler naplófájljainak feldolgozása, mint igény, később jelent meg, a könyvtárak neve nem jelzi, hogy az adott objektum számára tartalmaz-e releváns információt, ezért az minden mappa tartalmát megvizsgálja, tartalmaz-e általa feldolgozandó állományokat.
%TODO
<jmeter class részlet>
A kódrészleten látszik, hogy a Python eléggé megkönnyíti egy csv fájl feldolgozását. A csv.reader függvény egy generátorral tér vissza, melyen végig iterálva lehet soronként feldolgozni az állományt. Egy sort a Python egy tuple objektumként reprezentál. Az első sorban az oszlopok nevét adja meg a Jmeter, így azt külön tuple objektumba mentve a zip hívással egy dictionary-t kapunk. Ebből a kívánt oszlop nevét megadva lehet kinyerni a keresett mezőt.
A JmeterAnalyzer objektum létrejöttekor létrehoz egy dictionary objektumot, melyben a beolvasott fájl timeStamp mezője lesz a kulcs, az érték pedig az adott másodpercben érzékelt válaszok körbefordulási ideje. Mivel a Jmeter egy Java-ban írt szoftver, a timeStamp mező egy java.utils.Date objektum szerializálva. Ahhoz, hogy ebből Python datetime objektumot lehessen készíteni, az adott számot el kell osztani ezerrel. Az így kapott datetime már másodperc pontosan fogja tárolni az időt. Az adott másodpercben visszaérkezett válaszok számát pedig az adott másodpercben tárolt késleltetési értékek száma adja meg.
A feldolgozás végeztével egy-egy listába kigyűjti a másodpercenként összegyűjtött adatokat tartalmazó listák hosszát, valamint az értékek átlagát.
%TODO
<hey class részlet>
A hey esetében máshogy kell csinálni, ugyanis itt a mérés több fájlra bomlik, amelyekben viszont nem lehet feltételezni, hogy pontosan harminc másodpercnyi, vagy egyéb konstans időtartamnyi mérés adatát tartalmazza egy-egy fájl, ugyanis a munka során ez változott. Emiatt egy fájl feldolgozása után gyűjti ki két listába az összegyűjtött adatokat tartalmazó lista hosszát és a késleltetések átlagát.
Miután a Knative Autoscaler naplóállománya analizálásának igénye felmerült, a méréseket automatizáló bash szkript módosítva lett úgy, hogy minden mérés kezdetének és végeztének másodpercre pontos dátumát egy külön fájlba menti. Ez által a naplófájl bejegyzéseit lehet szűrni a két dátum köztire.
%TODO
<LogAnalyzer class részlet>
A Knative Autoscaler a naplóbejegyzéseket json objektumként menti, melyből a Python képes dictionary objektumot készíteni. Amennyiben az adott bejegyzés ts mezője a mérés kezdési és befejezési ideje közé esik, akkor az msg mezőben lévő üzenet feldolgozásra kerül. Az üzenetben kulcs-érték párok vannak szóközzel elválasztva egymástól. A kulcs és az érték között egyenlőségjel van. Ezt egy reguláris kifejezéssel listává lehet konvertálni. Sajnos a Python reguláris kifejezés API-jában nincs arra lehetőség, hogy ilyen esetben dictionary objektumot adjon vissza, így azt kézzel kell konvertálni kihasználva azt, hogy az értékek mindig egy kulcs után következnek. Ezután a Podok száma, valamint a megfigyelt stabil konkurencia érték letárolható.
A feldolgozott adatokból a matplotlib Python könyvtár segítségével készíthető grafikon úgy, hogy az adatokat tartalmazó listát átadjuk a megfelelő függvény számára. A grafikon mentése egy másik függvényhívással lehetséges. Szintén külön függvényhívással lehet a grafikon címét, valamint a tengelyek feliratát elhelyezni a grafikonon.
A méréseket elvégző szkript kis módosításával elértem, hogy a mérési eredmények egy általam üzemeltett számítógépre töltődjenek fel archiválásra és az itt részletezett program által feldolgozásra. A feltöltés után a szkript meghívott egy ugyanezen a szerveren futó REST-es végpontot, amely hatására elindult az adatok feldolgozása. Maga a program egy Docker konténerben futott. A kód verziókövetésére Git-et használtam, amelynek előnye az volt, hogy minden alkalommal, mikor egy állapotát mentettem a kódnak, abból a Travis szolgáltatás automatikusan elkészítette a Docker Image-et, valamint feltöltötte a Docker Hub-ra. Így a fejlesztéstől a mérésig teljesen automatizált munkafolyamatot dolgoztam ki. Felmerült ötletként, hogy ezt a Knative rendszerbe telepítsem, viszont szerettem volna, ha a méréseket feldolgozó folyamat független a mért rendszertől és a lehető leglazábban kapcsolódik hozzá. Ez által a két rendszerben történő folyamatok, esetleges hibák nem hatnak ki a másik működésére.
Miután a késleltetést is grafikonon akartam ábrázolni, számos mérési eredményt újra fel kellett dolgozni, ami az adatok nagy mennyisége miatt sok időt vett igénybe. Viszont felismerve, hogy a mérések között nincs függőség, minden könyvtár feldolgozását külön process-ekre bontottam. Kimondottan nem szálakat használtam, ugyanis a Pythonban közismert probléma a Global Interpreter Lock, ami miatt a Python egyszerre csak egy szál éppen futó kódját értelmezi. Amennyiben az adott feladat számára teljesen önálló process indul, annak saját GIL-je lesz, ezzel megoldva ezt a problémát. Ez által a feldolgozási idő kevesebb, mint felére csökkent.

105
src/content/results.tex Normal file
View File

@ -0,0 +1,105 @@
\chapter{M\'er\'esi eredm\'enyek ismertet\'ese}
Mielőtt elkezdtem a Knative és Kubeless rendszerek mérését, annak érdekében, hogy a mérőeszközök, illetve a Knative-hoz készített függvények teljesítményét kimérjem, mindkét mérőeszközzel megmértem mindkét függvényt Docker konténerként indítva. Itt a függvények a harmadik, a Kubernetes klaszterbe be nem csatlakoztatott számítógépen futottak a függvények, a mérések pedig az Kubernetes Masteren futottak. Mind a négy mérés esetében a használt connection objektumok száma negyvenöt.
%TODO
<jmeter és hey hello docker>
%TODO
<jmeter és hey isprime docker>
A két ábrából látszik, hogy a várakozásokkal ellentétben a Jmeter jobban teljesített, mint a hey. Ez azért van, mert a hey-re megszabtam connection objektumomként ötszáz kérés per másodperces korlátot. Erre a számra úgy jutottam, hogy a hey által használt connection objektumok számát egyre állítottam. Ez esetben a generált kérések száma másodpercenként 510 és 530 között ingadozott, viszont stabilan mindig 500 felett volt. A generált forgalom stabilizálása érdekében az 500-nál húztam meg a határt, melynek szükségességét a korábbi tapasztalatok alapján éreztem, ugyanis a hey teljesítménye megfigyeléseim szerint instabil, mikor nagy sebességgel kell generálja a kéréseket. Továbbá, úgy ítéltem, hogy két különbözően viselkedő mérőeszköz többet fed fel a skálázódási mechanizmusokról.
Az ábrákról szintén látszik, hogy a prím számoló függvény teljesítménye alulmarad a kis számításigényű függvényhez képest. Ez az előzetes várakozások szerint alakult. Mivel a Kubeless egy teljes Function as a Service rendszer, az oda telepített függvényeket önmagukban nem lehet kipróbálni.
%TODO
<knative-elso-coldstart és latency>
A fent látható ábra az első mérés volt, amit a Knative-ba telepített echo típusú függvényen végeztem. Az eredménye kifejezetten meglepett, ugyanis a két mérés között nem csak szignifikánsan nagy a különbség, de a hey harminc másodperces futásai közül az elsőben kifejezetten nagy a feldolgozott kérések rátája, csak utána csökken le ezer körüli értékre. Később a késleltetési értékeket megtekintve ahogy sejtettem, hogy az első harminc másodpercben a kérések nem értek el a Podig, ugyanis itt a késleltetés kifejezetten alacsony volt.
%TODO
<hatodik-hello-knative-cold részlet>
A korábbi mérést megismételve, hosszabb ideig futtatva a mért teljesítmény ingadozása megmarad, viszont az ezerig történő beesés nem tapasztalható.
%TODO
<jmeter-hatodik-go-cold>
%TODO
<jmeter-hatodik-go-hot>
A fenti két ábrán látható, hogy az nincs kihatással a függvény teljesítményére, hogy létezett-e a mérés indítása előtt. Érdekes jelenség, hogy a Jmeter által mért teljesítmény sokkal stabilabb. Igaz, hogy ez esetben nincs szükség a mérést fél perces szegmensekre bontani. Különösen furcsa a hey viselkedése, ugyanis a hiszterézis akkor nem volt megfigyelhető, ha a függvényt közvetlen Dockerben futtattam. Emiatt használatát nem vetettem el, de az általa mért feldolgozott kérési rátát fenntartással kezeltem.
%TODO
<jmeter-for-otodik>
%TODO
<knative-for-negyedik>
A fenti ábrákon látható a Knative-ba telepített echo típusú függvény skálázódása. A kettő közül először az alsó mérést végeztem el, ahol a hey instabil viselkedése szintén megfigyelhető. A mérés körülbelül felénél látható megemelkedett ráta konzisztensen megismételhető volt több, független Kubernetes klaszteren is. Az ábrák elején jól megfigyelhető a Knative pánik skálázása, amely gyorsan létrehoz öt Podot, majd a hatvan másodperces panic windows lejárta után a már nem szükséges podokat leállítja. Az ezután a Podok számában megfigyelhető hiszterézis a Jmeteres ábrán és egyéb Jmeteres mérések során nem volt tapasztalható. Ez betudható annak, hogy az ObservedStableConcurrency érték a döntési határértéken van. Szintén megfigyelhető, hogy a Podok kiszámításának korábban ismertetett formulája úgy tűnik nem volt helyes. Ez nem helyes következtetés, ugyanis a hey ábrán látható három, valamint a Jmeter ábrán látható kettő kiszámított Podszámhoz hozzáadódik az egy mindig létező Pod. Az ObservedStableConcurrency érték esése a Jmeter ábra esetén is látható, amire a Podok számának csökkentésével reagál a rendszer. Érdekes, hogy itt mind a Podok száma, mint az ObservedStableConcurrency sokkal stabilabbak, cserébe alacsonyabbak. Szintén különbség, hogy a hey esetében a mérés elején tapasztalható alacsony teljesítményű időszak időben hasonló, viszont nincs benne ugrás. Mindkét ábrán látszik, hogy az ObservedStableConcurrency érték mozgó átlag, emiatt lassan változik. Ennek következménye, hogy a terhelés megszűnése után nem szűnnek meg a létrehozott Podok.
A mérések alapján kíváncsi voltam, mi történik, ha alacsonyabb áteresztőképességű függvényre generált terhelés esetében vizsgálom meg a Knative belső működését.
%TODO
<hatodik-isprime-knative-for>
%TODO
<jmeter-hatodik-py>
A fenn látható két ábrán látható függvény teljesítményének karakterisztikája teljesen más, mint az echo típusú függvényé. Olyan szempontból hasonlítanak, hogy kell idő mindkét függvénynek, hogy a teljesítménye elérje a stabil értéket, viszont ellentétben az echo típusú függvénnyel, ezt nem egyik másodpercről a másikra teszi a prímszámoló függvény, hanem folyamatosan. Az ObservedStableConcurrency viszont a várakozásoknak nem megfelelően alakult. Intuíció alapján azt vártam el, hogy hasonló terhelés és kisebb áteresztő képesség miatt ez az érték megemelkedik, aminek következtében aztán a Podok száma is megnő. Ennek viszont az ellenkezője történt. Az alacsonyabb áteresztő képesség ellenére az ObservedStableConcurrency is alacsonyabb volt, így a Podok száma is alacsonyabb maradt. Ez betudható annak, hogy amíg a függvény vissza nem tér, foglalja az adott connection objektumot, amely meghívta.
%TODO
<hatodik-hello-knative-climb>
A fenti ábrán látható az echo típusú függvényre egyre növekvő terhelés, valamint a Knative Autoscaler rendszer e mérés alatti belső állapota. A terhelés növelését a hey mérőeszközben egyre több connection objektum használta által értem el. Jól látszik, hogy az ObservedStableConcurrency egy lassan változó érték, a mérés végére töredékét érte el annak az értéknek, amit az egyenletes terhelésű mérések során elért. Szintén látható a Podok számából, hogy pánik állapotot sem váltott ki a mérés. Erre nem is lehetett számítani, hiszen a használt konkurencia érték sosem növekedett duplájára hat másodperces időtartam alatt.
%TODO
<hatodik-isprime-knative-climb>
A korábbi mérések alapján számítottam rá, hogy a prímszámoló függvény újból máshogy fog viselkedni, de a csalódnom kellett, ugyanis a gyengébb csúcsteljesítményen kívül egyéb különbség nem figyelhető meg a két függvény típusa között.
%TODO
<istio és nginx egy ábrán>
Mivel a Knative és Kubeless rendszerek másik Ingress Controllert használtak, szerettem volna kimérni ezek áteresztőképességét is. Ezt úgy vittem véghez, hogy a mérőeszközzel mindkét Ingress Controller végpontját megcéloztam, mint ahogyan azt a függvények teljesítményének mérésénél is tettem, viszont ez esetben általuk nem ismert hosztnév fejlécet adtam meg. Ez által minden kérésre 404-es http kóddal válaszoltak. A fenti ábrákon látható teljesítmény az adott Ingress Controllerek által elérhető legjobb teljesítmény. A Kubeless által használt Nginx Ingress Controller teljesítménye majdnem négyszeresen meghaladja a Knative által használt Isitio.
%TODO
<valami kubeless cucc kell ide>
Ahogy az az ábrán látszik, a Kubeless skálázódása teljesen máshogy működik. Ez esetben a kötelezően meghatározott cpu használati limit miatt a skálázódáson a teljesítményben is érzékelhető a több Pod használata. Szintén látszik, hogy a csúcsteljesítmény, amit elért magasabb, mint a Knative esetében. Cserébe, viszont a skálázódás lassabb, a Horizontal Pod Autoscaler hatvan másodperces átlagolása miatt.
%TODO
<jmeter-kubeless-hello-go-hatodik-rps>
Sajnos, a Kubeless esetében többször előfordult, hogy csak egy Podot hozott létre az egész mérés során. Ez nem függött attól, hogy mennyi ideig tartott a mérés. Miután véget ért a terhelés, rövid időn belül létre jött a következő Pod. Ennek okát próbáltam kideríteni, egyik hipotézisem az volt, hogy nincs elég cpu ideje a számítógépnek létrehozni a Podot, de ezt kézi megfigyeléseim során elvetettem. Másik probléma a Kubeless esetében, hogy az Nginx Ingress Controller minden beérkező kérésről naplóbejegyzést ír. Ennek következményeképp a Podja Evictelődik, mert túl sok tárterületet használ.
Erre a problémára több megoldási lehetőség létezik, viszont egyik sem tökéletes. Egy lehetőség a konténerek kézi (vagy akár automatizált) naplójainak rotációja. Ez azért nem jó megoldás, mert nem csak a függvény podok kerülnek evicted állapotba, hanem akár a network plugin által használt Pod, hiszen a monitorozó rendszer minden Pod-tól lekérdezi az adatait, valamint a Kubernetes minden Pod-ot evicted állapotba tesz, ha túl sok ephemeral storage-ot használ. Ennél létezik egyszerűbb megoldás, ami jobb lehetőségnek tűnik. Ez a Docker logrendszerének átkonfigurálása, hogy ne a konténer fájljai között, json formátumban naplózzon, hanem például használja a gazda gép journald rendszer szolgáltatását. Ez meg is oldotta ezt a problémát, viszont felvetett egy másikat. Bár a naplóbejegyzések már nem kerülnek a konténerek mellé, valahol a fájlrendszeren kerülnek tárolásra, ahol egy idő után ugyan tömörítésre kerülnek, de addig jelentős helyet foglalnak a mérésből és a monitorozásból adódó bejegyzések. Ennek eredményeként a Kubernetes worker node-okon DiskPreassure állapot léphet fel, amely azt jelenti, hogy az adott Node fájlrendszerén kevés a fennmaradt szabad hely. Ez a szabály vonatkozik a Node root partíciójára, valamint a Docker konténereket tároló partícióra is. Ekkor a Node-on lévő Pod-ok kerülhetnek evicted állapotba, a Kubernetes megpróbálja azokat újraindítani, viszont ez már új konténer létrehozását jelenti. Erre két megoldási lehetőség létezik. Vagy a problémás Node kubelet konfigurációját átállítjuk, hogy a DiskPreassure állapot később lépjen fel, ezzel viszont csak elnapoltuk a problémát. Másik lehetőség a naplófájlok gyorsabb rotációja, illetve a Docker konténerek külön partíción tárolása, de ez esetben csak lelassítottuk a problémát. Az igazi megoldás a kettő módszer ötvözése. Naplóbejegyzések mindenképpen generálódni fognak, ezt megakadályozni nem tudjuk és nem is érdekünk, hiszen bármi probléma adódik, a naplóbejegyzések jelentős segítséget nyújtanak a diagnózisban, valamint akár a probléma megoldásában is segíthetnek.
Annak érdekében, hogy a Knative-ba telepített függvények skálázódása az általuk nyújtott teljesítményben is meglátszódjon, szerettem volna limitálni egy-egy Pod teljesítményét. Erre viszont a Knative által létrehozott objektum típusok esetében nincs lehetőség. Emiatt úgy döntöttem, hogy a Knative által létrehozott Kubernetes Deployment objektumot módosítom, ott hozom létre a limiteket. Ez sikerült is, a függvény működött tovább, a megadott korlátozások érvénybe léptek. Viszont az elvárások nem teljesültek, a Podok létrejöttével nem emelkedett meg a függvény teljesítménye. A lenti diagrammon látszik, hogy a függvény végig ezer kérést volt képes kiszolgálni másodpercenként.
%TODO
<jmeter-pillanat-junky>
Korábbi mérések során a prímszámoló függvény egy Python folyamatot használva nyolcszáz kérést szolgált ki másodpercenként. Tehát a mérés során létrejött öt Pod nagyjából négyezer kérést kellene kiszolgálnia másodpercenként az elvárásaink alapján. Ezzel szemben az egész mérés során olyan teljesítményt nyújt a függvény, melyet két Pod is ki tudna szolgálni.
Kíváncsi voltam, egyes mérések során milyen belső állapotai vannak a Knative egyes alegységeinek. Azért, hogy ezeket megfigyelhessem, telepítettem a Knative Monitoring egységét. Ez után újra elvégeztem bizonyos méréseket. Először a prímszámoló függvény viselkedését vizsgáltam meg. Az első ábrán a Podok CPU használata látható. Érdekes, hogy a Workeren elérhető húsz magból összesen hetet sem használnak. A második ábrán látható, hogy a függvényt kiszolgáló Podok és a Knative rendszer processzorhasználata, hogy alakul egymáshoz képest.
%TODO
<grafana-isprime-cpu>
%TODO
<grafana-isprime-controllvsdata>
Érdekes, hogy együtt is csupán körülbelül tíz processzormagot használnak. A Control Plane az ábrán a Knative Serving egyes komponenseit, az Istio-t, a monitoring eszközöket és a Kubernetes beépített részeit jelenti. A lenti ábrán látható, ezen komponensek között miként oszlik el a processzorhasználat.
%TODO
<grafana-isprime-controlplane-namespaces>
Látszik, hogy leginkább a Knative Serving komponense használja leginkább a processzort. A kubectl top parancsot használva azt is sikerült kideríteni, hogy pontosan az activator nevű komponens miatt emelkedik ki a Knative processzorhasználata. A Grafana által generált grafikonok egyikén megfigyelhető, hogy a pánik mód mikor kapcsolt be és meddig tartott. Ez a lenti grafikonon látszik. A pánik mód a specifikáltak szerint viselkedik, az xy ábrán az is látszik, miként alakult a Podok száma a mérés során.
%TODO
<grafana-isprime-panik>
%TODO
<grafana-isprime-podszam>
Másodikként az echo típusú függvény terhelése alatt vizsgáltam meg a Knative belső működését.

167
src/content/theory.tex Normal file
View File

@ -0,0 +1,167 @@
\chapter{Elméleti összefoglaló}
\label{sec:theory}
\section{Felhő alapú szolgáltatások rendszerezése}
A felhő alapú számítástechnikában a felhasználó elől elrejtve, a szolgáltató erőforrás halmazán elosztva megvalósított szolgáltatásokat értjük, amit jellemzően virtualizációs technológiára építenek. Négy szolgáltatási modellt különböztetünk meg: SaaS (Software as a Service, Szoftver, mint Szolgáltatás, például: Office 365), FaaS (Function as a Service, Függvény, mint Szolgáltatás, például: Amazon Lambda), PaaS (Platform as a Service, Platform, mint Szolgáltatás, például: Oracle Cloud Platform) és IaaS (Infrastructure as a Service, Infrastruktúra, mint Szolgáltatás, például: Microsoft Azure).
A Software as a Service szolgáltatási modellben a felhasználó egy kész szoftvercsomag használati jogát vásárolja meg vagy bérli. Ez azért felhő alapú szolgáltatás, mert a szoftver a szolgáltató infrastruktúráján fut. A végfelhasználóknak nincs rálátásuk a futó kódra vagy az infrastruktúrára. Ebből adódóan az üzemeltetési feladatok nem mérnöki jellegűek, legtöbbször csak a felhasználói fiókok adminisztrációjára van lehetőség.
A Function as a Service nem csak egy szolgáltatási modell, hanem megkövetel egy bizonyos szoftver architektúrát is. Az FaaS-t használó szoftverek függvényekből állnak. Ezek hasonlóak a tradicionális szoftverekben ismeretes függvényekhez, annyi különbséggel, hogy a bemeneti paraméterekre és a visszatérési értékre szabhat megkötéseket egy FaaS platform. A feltöltött függvények egy URL-en érhetők el, melyeket megnyitva az adott függvény lefut. Erre a futásra rálátása a felhasználónak nincs, csak a visszatért eredményt kapja meg. A felhasználó számára még a futtató környezet is ismeretlen. Emiatt a függvényeket csak a szolgáltató által nyújtott platformon lehet futtatni, tesztelni. Ez, valamint a nagyszámú komponensre bontott szoftver architektúra megnehezíti a hibakeresést, és a hibák előfordulási okának megtalálását.
Platform as a Service típusú szolgáltatások alatt értjük azon szolgáltatásokat, melyek lehetővé teszik egy elkészült alkalmazás futtatását egy, a szolgáltató által menedzselt platformon. A szolgáltatás felhasználójának csak a saját alkalmazásával felmerülő problémákat kell megoldania, a fizikai szervereket, operációs rendszert, valamint a middleware-t ami lehet például Java futtatókörnyezet, vagy Kubernetes konténer orkesztrációs platform - a szolgáltató biztosítja. Ezek mellett gyakran adatbázis szolgáltatást is igénybe lehet venni. Egy PaaS platformon telepített alkalmazásban hibák keresése külön megfontolásokat nem igényel, a helyben és távolban futtatott példányok között különbség nincsen.
Egy Infrastructure as a Service típusú szolgáltatás keretében a szolgáltató egy virtuális gépet nyújt a végfelhasználóknak. Erre a gépre tetszőleges operációs rendszer telepíthető. Ezt a szolgáltató legtöbb esetben legfeljebb monitoring lehetőségekkel bővíti. E szolgáltatási modell keretében üzemeltetett alkalmazással kapcsolatban fordul elő a legtöbb mérnöki probléma, ugyanis a hálózaton és a virtuális gépeket futtató szerverek nagy rendelkezésre állásán kívül a szolgáltató nem vállal semmilyen garanciát. Míg például a Platform as a Service szolgáltatások esetében az alkalmazás terheléstől függő skálázását a szolgáltató garantálta, erről és az ezzel kapcsolatban felmerülő problémák megoldásáról a felhasználónak kell gondoskodnia. Mindezért cserébe a felhasználónak behatása, illetve rálátása van a futtató környezetre.
\section{Konténerizáció}
A konténerizáció, vagy operációs rendszer szintű virtualizáció alatt egy fizikai vagy virtuális számítógépen futó operációs rendszer egymástól független partíciókra osztását értjük. Általában szerverek virtualizálására használják. Számítógépek virtualizációjától lényeges eltérés, hogy a kernel - az operációs rendszer hardware-t kezelő része - nem kell fusson minden példányon, viszont hasonlóság, hogy a dinamikusan csatolt osztott könyvtárak minden konténerben külön betöltésre kerülnek a memóriába.
Az elmúlt években kifejezetten népszerűvé vált, ugyanis a saját fejlesztésű szoftvercsomagokból gyorsan létrehozható egy nem módosítható konténer kép, ami ez után rövid idő alatt példányosítható. Ezáltal a fejlesztői és éles környezet teljesen ugyanaz lehet. További előnye, hogy egy szoftvercsomag gyorsan telepíthető, gyakran előre konfigurálva, anélkül, hogy bármi módosítást eszközölne a felhasználó a számítógépén. Természetesen erre van lehetőség virtuális gépekkel is, viszont egy-egy ilyen kép több helyet foglal, valamint futtatásához több erőforrásra van szükség.
\subsection{Docker}
A legnépszerűbb megvalósítása az operációs rendszer szintű virtualizációnak a Docker -melyet a szakdolgozatomban használt Kubernetes rendszer is használ. A Docker kihasználja a Linux operációs rendszer által nyújtott szolgáltatásokat az egyes konténerek izolálásához.
Konténer képek létrehozására két lehetőség van. Az egyik egy már meglévő konténer képből futó konténer létrehozása, a kívánt módosítások elvégzése, a leállt konténerről nem módosítható pillanatkép készítése. Másik lehetőség egy úgynevezett Dockerfile létrehozása, ahol a kiinduló konténer kép megadására, valamint a módosítások lépésenkénti megadására van lehetőség. Ezeket a lépéseket rétegezetten hajtja végre a Docker, azaz minden lépés eredménye egy kép, amit a rendszer példányosít, és elvégzi a következő lépést. Ez lehetővé teszi a konténer kép építésének gyorsítását, ugyanis azokat a lépéseket nem szükséges újra végrehajtani, melyek eredménye nem változott. Fontos, hogy amennyiben egy réteg változik, az arra épülő rétegekhez tartozó lépéseket is újra végre kell hajtani. A Dockerfile használata lehetővé teszi a konténer képek létrehozásának automatizálását, melyet a szakdolgozatomban is kihasználtam.
\section{Kubernetes}
A Kubernetes egy Go nyelven írt, nyílt forráskódú konténer orkesztrációs platform, amely képes konténerek automatikus konfigurációjára, skálázására, valamint bizonyos hibák automatikus elhárítására. Több konténer technológiát támogat, köztük a Dockert is. Nagyon népszerű, gyors fejlesztés alatt álló projekt. Emiatt felhasználói és programozói interfésze gyakran változik, megkövetelve a ráépülő megoldásoktól a hasonló sebességű fejlesztést. Jól definiált interfésze miatt sok ráépülő, azt kiegészítő projekt létezik. Egy ilyen a Kubeless, amely segítségével Function as a Service megoldásokat lehet készíteni Kubernetes környezetben.
Néhány fontosabb szolgáltatás, melyet a Kubernetes nyújt:
\begin{itemize}
\item Horizontális skálázás,
\item Konfiguráció és szenzitív adatok menedzsmentje,
\item Háttértár orkesztráció
\end{itemize}
\subsection{Kubernetes klaszter felépítése}
Egy Kubernetes klaszterben két típusú hosztgép lehet. Mindkettőből lehet több darab, de legalább egy-egy példány kötelező.
%TODO
<Szép, részletes ábra a K8s klaszter felépítéséről>
A Kubernetes Master felelős a klaszterben lezajló folyamatok irányításáért, a Slave-ek, vagy más néven Worker-ek, valamint az alkalmazások állapotának nyilvántartásáért. A klaszterben történő eseményekre válaszul klaszter szintű választ ad - például egy Pod elindítása.
Egy Master node számos komponensből áll, ezek a Master egy-egy feladatáért felelnek. Több Master node futtatása esetén - úgynevezett multi-master mode - csak az API Server és az etcd komponensekből jön létre több példány, a többiből egyszerre csak egy példány lehet aktív.
\subsection{API Server}
Az API-Server szolgálja ki a Kubernetes API-t, amelyen keresztül lehet interakcióba lépni a klaszterrel. A kiszolgált API REST alapú, JSON objektumokba csomagolva lehet az etcd-ben lévő információt lekérdezni vagy frissíteni. Ez egy kifejezetten fontos része egy klaszternek, meghibásodása esetén a klaszter konfigurációja igen nehézkes.
\subsection{Etcd}
A CoreOS által fejlesztett, nyílt forráskódú elosztott kulcs-érték tár. Itt kerül tárolásra, illetve innen lehet lekérdezni a klaszter, valamint az egyes komponensek állapotát. Egyes komponensek figyelik az itt található, nekik fontos kulcsokhoz tartozó értékeket, változás esetén elvégzik az esetleges módosításokat.
\subsection{Controller Manager}
Logikailag különböző kontrollereket összefoglaló komponens. Az alábbi kontrollereket a komplexitás csökkentése érdekében fordították egy binárisba:
\begin{itemize}
\item Node Controller: Egyes Node-ok elérhetetlenné válásának figyeléséért, erre történő reagálásért felelős.
\item Replication Controller: A klaszterben megfelelő számú Podok meglétéért felelős kontroller.
\item Endpoints Controller: Service-ek és Podok társításáért felelős.
\item Service Account \& Token Controllers: Alapértelmezett felhasználói fiókok és API tokenek létrehozását hajtja végre néhány Namespace-hez.
\end{itemize}
\subsection{Scheduler}
A Scheduler, vagy Ütemező figyeli, mely Podok még nincsenek egy Slave node-hoz sem rendelve, majd hozzárendeli egyhez olyan módon, hogy a hozzárendelt node-on lévő erőforrások kielégítsék a Pod igényeit, valamint a terhelés legyen lehetőség szerint egyenlően elosztva a node-ok között.
\subsection{Horizontal Pod Autoscaler}
A Horizontal Pod Autoscaler automatikusan skálázza a Podok számát egy Deploymentben a megfigyelt CPU használat alapján. Ez a megfigyelés 15 másodperces ciklusokban történik, majd a skálázási döntés a gyűjtött metrikák egy perces átlaga alapján zajlik.
\subsection{Slave Node}
A Kubernetes klaszter azon részét, ahol a telepített alkalmazások futnak Slave Node-nak, vagy bizonyos szakirodalomban Workernek hívják. Egy Slave Node az alábbi komponensekből áll:
\subsection{Container Runtime}
A konténerek futtatásáért felelős komponens. Képes használni többek között Docker, CRI-O és containerd konténer futtatási környezeteket.
\subsection{Kubelet}
Felelőssége, hogy a Podok specifikációjuk szerinti állapotban fussanak. A klaszter összes tagján kötelezően fut.
\subsection{Kube-Proxy}
UDP vagy TCP forgalom továbbítására képes komponens, amely minden Slave Node-on kötelezően fut.
\section{Kubernetesben létrehozható objektumok}
A Kubernetesben többek között az alábbi objektumok hozhatók létre:
\subsection{Pod}
A Pod egy vagy több konténert összefogó logikai hoszt. Egy Podon belül lévő konténerek osztoznak a hálózaton és a háttértáron, valamint azonos a futtatási specifikációjuk. Ez azt jelenti, hogy az egy Podon belüli konténerek localhost-ként megtalálják egymást, valamint van lehetőség, hogy a konténerekben futó alkalmazások lássák a másik konténerben futó folyamatokat. Egy Kubernetes rendszerben a Pod a legkisebb egység, amit futásra lehet ütemezni.
\subsection{Deployment}
A Deployment segítségével deklaratívan leírható egy alkalmazást felépítő Podok és azok kívánt állapota. Lehetőség van megadni, hány replikát hozzon létre a rendszer. Hasonló módon lehet Podok állapotát frissíteni vagy egy korábbi állapotra visszatérni. Egy Deploymentben lehetőség van több Pod definiálására, ami alkalmazás komponensek lazább csatolását teszi lehetővé.
\subsection{Service}
A Podok bármikor törlődhetnek, valamint új példány jöhet belőlük létre. Minden Pod saját IP címmel rendelkezik, viszont szükség van valamilyen módszerre, aminek segítségével nyomon lehet követni, hogy egy Pod által nyújtott szolgáltatás milyen címen érhető el. Erre a problémára nyújt megoldást a Service, ami absztrakciót jelent a Podok felett.
\subsection{Volume}
A perzisztens adattárolás gyakori igény, főleg valamilyen állapotot számontartó alkalmazások esetében. A Podok alapvetően nem alkalmasak erre, ezért szükség van a Volume-okra, ami lehetővé teszi a perzisztens adattárolást Kubernetes környezetben.
\subsection{Ingress}
Ingress erőforrás segítségével klaszteren belüli Service erőforrást lehet azon kívülre kiszolgálni. Ennek módját az Ingress erőforrás határozza meg, amelyet az Ingress Controller nevű klaszter szintű objektum szolgál ki.
\section{Kubeless}
A Kubeless egy Go nyelven írt, nyílt forr\'askódú, Kubernetes rendszerbe épülő Function as a Service megoldás. Számos ehhez hasonló rendszer létezik, a Kubeless különlegessége abban rejlik, hogy a funkcionalitásának kis részéhez használ újonnan bevezetett logikát, szinte mindent a Kubernetes API kiegészítésével ér el. A keretrendszer támogat számos népszerű programnyelvet, például a Go, Python, Java, Javascript és C\# nyelveket.
Egy telepített függvény lefutását több esemény - úgynevezett trigger - kiválthatja. Ezek közül egy a http kérés, amelyet a szakdolgozatomban vizsgáltam. Emellett van lehetőség eseményvezérelt műkődésre is, például Kafka rendszerben tárolt üzenetek feldolgozására is.
Lévén, hogy Function as a Service rendszerről van szó, a Kubeless-be telepítendő függvényeket sajátos módon kell megírni.
%TODO
<szép hello world kódrészlet>
Mint az a fenti kódrészleten is látszik, a függvény első paraméterben megkapja a kiváltott eseményt, a másodikban pedig a futási kontextust, a visszatérése pedig egy karakterlánc, opcionálisan pedig egy keletkezett kivétel. Minden úgynevezett eseménykezelőnek ilyen szignatúrával kell rendelkeznie. Az eseményt leíró, functions.Event típusú paraméterben, például http kérés esetén annak törzsében, található adat.
Egy megírt függvényt telepíteni két módon lehet. Egy lehetőség közvetlen a Kubernetes API-t használva. Alternatíva és könnyítésként a Kubeless fejlesztői elkészítettek egy parancssoros programot, amelyet használva egyszerűen lehet telepíteni függvényeket, létrehozni triggereket, valamint beállítani a skálázást. Fontos, hogy telepítés közben nem jön létre automatikusan CPU limit egy-egy függvénynek, akkor sem, ha skálázást kérünk hozzá. Skálázáshoz a Kubeless a Horizontal Pod Autoscalert használja.
Mivel a Kubernetesben Podokat van lehetőség futtatni és ütemezni, a Kubeless függvényekből is Podokat kell létrehozni. Ez a folyamat részleteiben eltér programnyelvenként azok sajátosságai miatt.
%TODO
<szép ábra a pod létrehozásáról>
A Podban futó konténer létrehozása során a Kubeless Controller a Debian nevű Docker képből indul ki. Először telepíti a programnyelv csomagjait, annak függőségeit és a kód binárissá fordításához szükséges eszközöket. Ez után felmásolja a kódot és a vele együtt, opcionálisan megadott függőségleíró állományt. A fordítási folyamat végén lefordítja a kódot. Ez a folyamat csak akkor lesz sikeres, ha a kód belepési függvényét tartalmazó fájlban meg van jelölve a Kubeless futtató környezet, mint függőség, ezáltal nincs szükség egyedi fordítóeszközre. Az elkészült, futtatható binárist megjelöli a rendszer, mint a képből futtatott konténer belépési pontját. Egy így készült Docker képet lehetőség van feltölteni a Docker Hubra, így későbbi használat során nincs szükség a folyamat újbóli futtatására.
Amennyiben http triggert hozunk létre egy függvényhez, létrejön egy Ingress objektum, amelyet kötelezően az NGINX Ingress Controller nevű Ingress Controller implementáció kell kiszolgálja, így annak telepítve kell lenni a klaszterben. Az Ingress Controller a megadott hosztnév - például function.example.com - alapján azonosítja, melyik függvényt kívánjuk meghívni.
Mivel a függvényekből Kubernetes objektumok lesznek, a terheléselosztás a rendszerben már létező mechanizmusokkal történik. Egy függvényt kiszolgáló Podok számának változása esetén a hozzájuk tartozó Ingress objektum nyomon követi a változást, így az NGINX Ingress Controller képes a beérkező kérések elosztására.
\section{Istio}
Az Istio egy nyílt forráskódú, Kubernetesbe épülő hálózati forgalom menedzselését elősegítő platform. Segítségével csökkenthető a nagy számú komponensből álló alkalmazások komplexitása.
Ezt a service mesh koncepciójának bevezetésével éri el. A service mesh egy alkalmazást felépítő mikroszervizek és ezek közötti interakciók összességét jelenti. Ahogy egy service mesh nő méretében és komplexitásában, egyre nehezebb átlátni és menedzselni. Az Isitio betekintést ad, és a belső működés irányítását nyújtja az egész service meshre.
Az Istio többek között képes:
\begin{itemize}
\item Forgalom irányítására,
\item Autentikáció, autorizáció és titkosítás biztosítására,
\item Házirendek definiálására, azok érvényesítésére,
\item Automatikus monitoring és naplózása alkalmazás komponenseknek futtatására.
\end{itemize}
Szakdolgozatomban, közvetve, az Istio terheléskiegyenlítő szolgáltatását is megvizsgálom, lévén, hogy a Knative azt használja, mint load balancert.
\section{Knative}
A Knative egy nyílt forráskódú, a Google által fejlesztett keretrendszer, amely a Kubernetesnél magasabb szintű absztrakciókat nyújt. Számos komponenséből a szakdolgozatban a serverless applikációk Kubernetes-be telepítését, futtatását megkönnyítő, úgynevezett Serving modult vizsgálom. Ezen kívül létezik még egy Eventing komponens, amely eseményvezérelt alkalmazások fejlesztéséhez biztosít segédeszközöket, valamint megold bizonyos gyakori problémákat.
Nem kifejezetten Function as a Service megoldásról van szó, a nullára skálázás miatt emlegetik a Platform as a Service infrastruktúrák következő generációjaként, de funkcionalitása és működése remekül illeszkedik a FaaS szolgáltatásmodellhez is. Emellett a Kubernetesben már futó alkalmazásokat Knative-ba átrakni nem jelent szignifikáns munkát. Az érintett komponensek módosítására nincs szükség, csupán a Deploymenteket kell Knative Service-ekre átírni. Ezzel szemben a plusz funkciók, melyeket az átállással ki lehet használni jelentős előnyt jelentenek.
Lényeges újítás a tradicionális Kubernetes-hez képest az egyes alkalmazáskomponensek nullára skálázása, valamint a konkurencia alapú skálázás. Mindkettőt a magasabb szintű absztrakció teszi lehetővé, ugyanis bár ezek Knative nélkül is elképzelhető funkciók, ezek megvalósítása számos extra komponens bevezetését igényelné. A nullára skálázáshoz szükséges egy perzisztensen létező egység, a Knative esetében az Istio, valamint a Knative Shared Gateway nevű komponens töltik be ezen egység szerepét. Konkurencia alapú skálázás esetében is ugyanez a komponens végzi a kérések elosztását. Az egy Podra eső átlagos konkurens kérések megfigyeléséért egy úgynevezett Knative Autoscaler felel. Ez az egység hozza a fel és leskálázási döntéseket, valamint a megfigyelt konkurencia érték alapján a pánik ablak kezdetét és végét.
A pánik ablak akkor lép érvénybe, ha rövid idő alatt nagy terhelés érkezik egy végpontra. Konkrétan a Service létrehozása során megadott célkonkurencia érték kétszerese, kevesebb, mint hat másodperc alatt. Csak a Knative által bevezetett, konkurencia - azaz egy Service-hez egyidőben beérkező kérések száma - alapú skálázás esetében értelmezhető a pánik ablak. Ekkor viszont nincs lehetőség nullára skálázásra, ugyanis legalább egy Podnak mindig léteznie kell. Pánik ablak során a Knative a konkurencia alapján kiszámolt szükséges Podok számának kétszeresét hozza létre. A terhelés stabilizálódása, vagy hatvan másodperc elteltével a Podok száma visszatér a megfigyelt stabil konkurencia alapján szükséges számúra. Az aktuális konkurencia kiszámítása a Service által létrehozott Podokra átlagolva kerül kiszámításra. Ebből a szükséges Podok számát az észlelt konkurenciát a Service létrehozása során megadott célkonkurenciával elosztva számolja ki a rendszer.
A Knative automatikusan elvégzi az Istio service mesh létrehozását minden telepített alkalmazáshoz, valamint a konfigurációjának frissen tartását, ezzel a felhasználóknak csak kivételes esetekben kell foglalkoznia. Lehetőség van Istio helyett Gloo használatára terheléskiegyenlítőként, de ilyenkor nem minden funkció érhető el. Előnye, hogy kevesebb erőforrást használ, mint az Istio. A szakdolgozatban azért döntöttem az előbbi használata mellett, mert úgy véltem a Knative fejlesztők azt helyezték fókuszba, azt támogatják. További kutatás tárgya lehet a két load balancer közti különbségek vizsgálata.
Opcionálisan telepíthető monitoring eszközök segítségével megfigyelhetők a rendszer belső folyamatai, állapotai. Például lehetőség van megfigyelni egyebek mellett egyes függvények és Knative rendszer elemek processzor és memóriahasználatát, a skálázást végző komponens állapotát. A Knative Monitoring rendszere a megfigyelésre a Prometheus-t, vizualizációra a Grafana nevű szoftver használja. A naplóállományok feldolgozására Logstash-t és Elasitsearch-öt, az ezekből kinyert metrikák vizualizálására Kibana-t használ a rendszer. Beállítástól függően, de alapértelmezetten másodperces gyakorisággal vesz a Prometheus mintát a Knative állapotáról. Ez, illetve a Logstash folyamatok számottevő Input/Output műveletet generál, amely a klaszter teljesítményére negatív hatással lehet.
A Serving komponens a Kubernetes és az Istio már meglévő szolgáltatásait felhasználva, azokra építve nyújtja többletszolgáltatásait. A Kubernetes API-t kiegészítve bevezet néhány új objektumtípust:
\subsection{Service}
Egy alkalmazás vagy egy alkalmazáskomponens leírására egyetlen absztrakciót biztosít. A Knative-ban a Service egy Route-ra és egy Configurationre képződik le, valamint ezek orkesztrálását végzi. E két objektummal teljesen kiváltható a használata. A belső objektumok állapotait a Service kontrollere továbbítja a Kubernetes API-n keresztül, mintha sajátja lenne.
\subsection{Route}
A Route, vagy útvonal egy hálózati végpontot biztosít egy alkalmazáshoz. Ez egy hosszú életű, stabil, http protokollon keresztül elérhető végpontot jelent, amelyet egy vagy több Revision szolgál ki. Alapértelmezés szerint a legfrissebb Revision felé irányítja a forgalmat a rendszer, de van lehetőség több ilyen objektum között elosztani a forgalmat bizonyos százalékos arányban. Hasonlóan, egy Route képes minden mögötte lévő Revision számára a rendszeren kívülről is elérhető aldomaint allokálni.
Ez a funkcionalitás hasonlít a Kubernetes Service objektuméra, valamint az Ingress objektum bizonyos funkcióit is tartalmazza, adaptálja a Knative rendszerre.
\subsection{Configuration}
Szükség van alkalmazások, azok komponenseinek elvárt állapotának leírására. Kubernetes rendszerben erre a Deployment szolgál, ennek párja a Knative-ban a Configuration. Emellett ez az objektum tartja számon és hozza létre a Revisionöket, ahogy az elvárt állapot módosul.
\subsection{Revision}
A Revision egy nem módosítható verziója egy alkalmazás kódjának, valamint konfigurációjának. Ez a gyakorlatban egy konténer képet jelent. Létrehozásuk a megfelelő Configuration objektum módosításával lehetséges.
Azok a Revisionök, melyek nem érhetők el egy Route-on keresztül sem, törlésre kerülnek. Viselkedésük hasonló a Podokéhoz, ilyen objektumokra képződnek le.

View File

@ -1,8 +0,0 @@
pdflatex --quiet %DOCUMENT%
bibtex -quiet %DOCUMENT%
pdflatex --quiet %DOCUMENT%
pdflatex --quiet %DOCUMENT%
@REM move %DOCUMENT%.pdf ../pdf/%DOCUMENT%.pdf
@del *.aux *.dvi *.thm *.lof *.log *.lot *.fls *.out *.toc *.bbl *.blg

View File

@ -73,11 +73,13 @@
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\pagenumbering{arabic} \pagenumbering{arabic}
%TODO import your own content %import your own content
\input{content/introduction} \input{content/introduction}
\input{content/latex-tools} \input{content/theory}
\input{content/thesis-format} \input{content/preparation}
\input{content/template-usage} \input{content/create-functions}
\input{content/results}
\input{content/closing}
% Acknowledgements % Acknowledgements