Kubernetes 3 óra alatt: részletes útmutató – 3. Rész: Kubernetes

A Kubernetes a konténerizált szoftver világ nyertes karmestere. Cikksorozatunkban bemutatjuk, hogy hogyan rakhatunk egy “hagyományos”, többkomponensű alkalmazást konténerekbe és a konténereket a Kubernetes segítségével hogyan vezérelhetjük.

Kubernetes cikksorozatunkat Rinor Maloku (http://rinormaloku.com) “Learn Kubernetes in Under 3 Hours: A Detailed Guide to Orchestrating Containers” posztjának fordítására alapozzuk, a szerző engedélyével. Az eredeti angol nyelvű poszt itt olvasható: https://medium.freecodecamp.org/learn-kubernetes-in-under-3-hours-a-detailed-guide-to-orchestrating-containers-114ff420e882

Cikksorozatunk 2. részét azzal zártuk, hogy sikeresen konténerizáltuk az alkalmazásunk konténereit és lokálisan ki is próbáltuk.

Felmerült a kérdés, hogy ha minden működik szépen, miért is van szükség Kubernetes-re?

Nos, képzeljük el, hogy konténerizált alkalmazásunk hirtelen világsiker lett. Percenként több millió kérést kapunk, hiszen mindenki kíváncsi a saját mondata érzelmi töltetére. Ugyan alkalmazásunk jól szervezett és jól felépített, ekkora mennyiségű kérés kiszolgálásával nem tud megküzdeni. Egy-egy példányban egyszerűen összeomlik.

Ekkor lép a képbe a Kubernetes.

Esetünkben az alábbi kérdéseket tehetjük fel:

Kérdés: Hogyan skálázzuk a konténerizált alkalmazásunkat?

Válasz: Hát egyszerűen mindegyik konténerből elindítunk egy második példányt.

Kérdés: Jó, jó, de hogyan osztjuk el a terhelést közöttük? Mi történik, ha az alkalmazás alatti hardver éri el a fizikai kereteit? Hogyan számíthatjuk ki a legoptimálisabb hardver kihasználást?

Válasz: Őőőőőő, na ezt meg kell gugliznom….

Kérdés: Hogyan váltunk verziót anélkül, hogy bármit is eltörnénk? Hogyan tudunk visszaváltani egy korábbi verzióra?

Nos, a Kubernetes az összes fenti kérdésre választ ad (sőt, még ennél többre is képes!).

Ha egy rövid mondatba kéne összesűrítenem, hogy mi is a Kubernetes, az a következőképpen szólna:

“A Kubernetes egy konténer vezérlő, amely elfedi a konténerek alatti infrastruktúrát (a használója elől).”

A konténerek alatti infrastruktúra elfedése

OK, de mit is jelent pontosan az, hogy “elfedi a konténerek alatti infrastruktúrát”?

A Kubernetes ezt úgy oldja meg, hogy egy API-t kínál felénk, amelyen keresztül kéréseket küldhetünk neki. Ezeket a kéréseket a Kubernetes a számára elérhető erőforrások alapján szolgálja ki.

Annyira egyszerű kérésekre kell gondolni, mint pl. “Kubernetes, ebből az image-ből kérek 4 példányt”. Erre a Kubernetes úgy reagál, hogy megkeresi az alulterhelt node-okat és azokon hozza létre a 4 új példányt.

Mit is jelent ez a fejlesztőknek? Egyszerűen azt, hogy a fejlesztőnek nem kell foglalkoznia a node-ok számával, hogy a konténerek pontosan hol indulnak el, és hogyan kommunikálnak egymással. Egyáltalán nem kell a hardver réteggel foglalkoznia és azzal, ha egyes node-okat elveszítünk menet közben – majd létrejönnek új példányok máshol. Minderről a Kubernetes gondoskodik.

 

A fenti árbáról az alábbi fontosabb elemeket emelném ki:

  • API szerver: az egyetlen mód, ahogy a cluster-rel kommunikálhatunk, legyen szó konténerek (őőőőőő, inkább “*pod”-ok) elindításáról, leállításáról, aktuális státuszok figyeléséről, log-ok lekérdezéséről, stb.
  • Kubelet: a konténereket (őőőőő, inkább “*pod”-okat) monitorozza egy-egy node-on belül és jelent a mester node-nak
  • *Pod-ok: kezdetben gondolj a pod-ra mint konténerre

És itt meg is állunk, hiszen nem akarjuk elveszíteni a fókuszunkat ezen a ponton.

A felhő alapú szolgáltatásokat nyújtó cégek egységesítése

A Kubernetes egy másik erőssége a felhő alapú szolgáltatásokat nyújtó cégek egységesítése. Ez egy eléggé súlyos kijelentés, nézzük meg, mit is jelent ez pontosan:

  • Vegyük azt a példát, hogy egy Azure, vagy éppen Google Cloud Platform szakértőnek egy új projekten kell dolgoznia egy teljesen más felhő szolgáltatónál, amelyre vonatkozóan nincs korábbi tapasztalata. Ez több problémát is felvethet, pl. hogy a projekt határidőre nem fog elkészülni, vagy újabb erőforrásokat kell bevonni, betanítani stb.

Ezzel szemben a Kubernetes-szel áthidalható ez a probléma, hiszen az API szerver felé ugyanazokat a parancsokat küldöd, nem számít, hogy a háttérben éppen ki a felhő szolgáltató. API szinten csupán megfogalmazos a kéréseidet, hogy pontosan mit is akarsz elérni, és a Kubernetes ezeket végrehajtja a számára elérhető erőforrásokon. Vagyis Te megmondod, hogy MIT akarsz, a Kubernetes pedig gondoskodik a HOGYAN-ról.

Más szemszögből nézve kimondható az is, hogy aki Kubernetes-re épülő technológiával dolgozik, az nincs egy konkrét felhő szolgáltatóhoz kötve. Egyszerűen kiszámolják a költségeiket egy másik felhő szolgáltatóra vetítve és ha kedvezőbb, egyszerűen átköltöznek oda, ahol olcsóbb az üzemeltetés.

Mindezek után nézzük meg a Kubernetes gyakorlati oldalát.

Kubernetes a gyakorlatban – Pod-ok

Cikksorozatunk előző két részében vettük az alkalmazásunk komponenseit és ezekből egyenként konténerizált elemeket készítettünk, majd egyszerre futtattuk ezeket. Nem volt egyszerű folyamat, de a dolog működik. A skálázási problémával viszont egészen eddig nem is foglalkoztunk. Itt jön be a Kubernetes. Ebben a részben az elkészült konténerizált elemeket migráljuk egy Kubernetes alapú platformra. Ezt mutatja be az alábbi ábra.

Ahhoz, hogy mindez lokálisan is működjön és meglegyen a sikerélmény, a Minikube nevű alkalmazást fogjuk használni. Fontos megjegyezni, hogy mindez akár az Azure-ban, akár a Google Cloud Platform-on is ugyanígy működne.

A Minikube telepítése és indítása

A Minikube telepítéséhez követsd a hivatalos leírását: https://kubernetes.io/docs/tasks/tools/install-minikube/

A telepítés során a Kubectl nevű komponenst is telepíteni fogod. Ez az az eszköz, amelyen keresztül a Kubernetes API szerverét hívni fogjuk.

A Minikube elindításához egyszerűen add ki a minikube start parancsot. Ha ez megtörtént a kubectl get nodes paranccsal ellenőrizhetjük, hogy eddig minden rendben haladt-e.

A Minikube egy 1 node-ból álló Kubernetes cluster-t hoz létre, amely tanulási célokra teljesen megfelel. Továbbá ugye nem felejtettük el, hogy nekünk fejelsztőknek voltaképpen nem is fontos tudni, hogy hány node fut, ezt a Kubernetes elfedi előlünk.

Ezután végre elindíthatjuk első Kubernetes-es erőforrásunkat, egy Pod-ot! Yeah!

Pod-ok

Én eddig is szerettem a konténereket, mostanra már biztosan Te is megszeretted őket. Miért döntött vajon a Kubernetes úgy, hogy legkisebb egységnek nem a konténereket, hanem a pod-okat tekinti? Mit tud egy pod? Egy pod egy vagy több konténert is tartalmazhat, amelyek azonos futtatókörnyezetben működnek.

De valójában szükséges két konténert futtatnunk egy pod-ban? Hát…. őőőő… rendszerint csak egy konténert futtatunk, a példáinkban is ez látható. Viszont, ha például konténerek megosztott filerendszereket használnak, vagy bármilyen módon szorosan, processz szinten kommunikálnak egymással, vagy nagyon szorosan együtt kell működniük, akkor a pod-ok jelentik a megoldást.

A pod-ok egy másik előnye, hogy rajtuk keresztül nem vagyunk még a Docker technológiához kötve sem, vagyis más konténerizáló technológiákat is használhatunk, például Rkt-t (https://coreos.com/rkt/).

Összefoglalva tehát a pod-ok az alábbi tulajdonságokkal rendelkeznek:

  1. Minden egyes pod-nak saját Kubernetes cluster-en belüli IP címe van
  2. Egy pod egynél több konténert is tartalmazhat. A pod-on belüli konténerek osztoznak a kiosztható port-okon, e mellett viszont kommunikálhatnak a locahost-on keresztül. Ha pod-ok közötti kommunikációról van szó, akkor a pod IP címét kell használniuk.
  3. Egy pod-on belüli konténerek osztoznak a megosztott filerendszeren*, egy IP címen, a kiosztható port-okon és az IPC névtéren.

 *A konténereknek saját izolált filerendszerük van, viszont képesek adatokat megosztani a Kubernetes-es Volume-okon keresztül.

A fentiek ismeretében lépjünk tovább.

A Pod definíciója

Hogyan is néz ki egy pod leírása? Az alábbi példa az sa-frontend pod-unk leírása:

Nézzük sorban:

  1. kind: itt adjuk meg a Kubernetes erőforrásunk típusát, jelen esetben a típusunk: pod.
  2. name: az erőforrás nevét adjuk meg, jelen esetben sa-frontend
  3. spec: ez egy objektum, amely az erőforrás kívánt állapotát írja le. A legfontosabb tulajdonság a konténer halmaz (array of containers)
  4. image: a pod-ban futtatandó konténer image-et adjuk meg itt
  5. name: a pod-ban futó konténer egyedi nevét adjuk meg itt
  6. container port: az a port, amelyen a konténer figyel

Az sa-frontend pod létrehozása

Magát a pod definíciós file-t megtalálhatod a

file-ban. Az alábbi parancs ezt a file-t használja fel:

Ellenőrizzük le, hogy a pod-unk valóban fut-e:

Ha esetleg a ContainerCreating státuszt látod, semmi gond. Futtasd le a fenti parancsot a –watch kapcsolóval, és akkor láthatod, hogy mikor éri el a pod-od a Running állapotot.

Az alkalmazás elérése “kívülről”

Ahhoz, hogy az alkalmazásunkat a pod-on kívülről is elérjük szükségünk lesz egy Service típusú erőforrásra is. Ezt majd a következő részben létre is hozzuk, most viszont, hogy egy gyors belső ellenőrzést futtassunk egy egyszerű port-forward is megteszi:

Nyissuk meg a böngészőnkben a http://127.0.0.1:88 -at és ott látnunk kell a frontend alkalmazásunk felületét.

Ha nem megfelelően skálázódunk fel

Korábban azt mondtuk, hogy a Kubernetes egyik fő előnye a skálázásban nyújtott szerepe. Ezt bizonyítandó indítsunk el egy másik pod-ot is. Hozzunk létre egy másik pod erőforrást az alábbi leírást követve:

 

Majd hozzuk létre a pod-ot az alábbi paranccsal:

 

Ellenőrizzük, hogy a második pod-unk is fut-e:

No, most már 2 pod-unk fut!

Figyelem: ez nem a végleges megoldás, ráadásul számos gyenge pontja is van. Később kijavítjuk ezeket a hiányosságokat a “Deployments” Kubernetes-es részben.

Összefoglaló a Pod-okról

Az Nginx web szerverünk a statikus file-okkal jelenleg két pod-on belül fut. Ezzel kapcsolatban a következő kérdések merülnek fel:

  • Hogyan tesszük kívülről is elérhetővé egy URL-en keresztül, és
  • Hogyan osztjuk el a terhelést közöttük?

Erre a Kubernetes a “Services” erőforrás típust adja megoldásként. Ezzel folytatjuk a következő részben.