Niekto raz múdro povedal: “Ak chceš rozumieť stromom, najprv musíš vidieť les”. Preto je dobré poznať jeho základné koncepty a filozofiu na ktorých Kubernetes stojí.
Nieje tajmostvom, že Kubernetes je zmes viacerých komponentov. Ide vlastne o microservices. V tomto prípade ale o overené microservices. Jeho architektúra môže slúžiť ako inšpirácia alebo varovanie pre podobné systémy, ukazujúc potencionálne riziká. Preto je užitočne poznať jeho koncepty aj pre tých, čo priamo s Kubernetesom nepracujú.
Už tradične sa kreslí architektúra Kubernetesu z pohľadu nasadenia, ako je znázornené na tomto obrázku:
Kubernetes je rozdelený na Control plane a Data plane. Na control plane bežia kontrolné komponenty. Z pohľadu nasadenia často hovoríme o master strojoch. Data plane predstavuje druhú skupinu strojov, na ktorých sú orchestrované práve kontajnery aplikácii. Tento nákres architektúry Kubernetesu je stále relevantný, avšak stráca sa tu jeho filozofia a hlavná myšlienka.
Hub and spokes
Mne osobne pomohlo pozrieť sa na Kubernetes z trochu iného uhla - z pohľadu procesov a ich interakcií. Odosobním sa nachvíľu od toho, na akom stroji ktorý komponent beží. Zakreslím si komponenty tak, ako spolu interagujú. Výsledný obrázok tak začne náramne pripomínať architektúru, známu ako hub-and-spokes.
Hub-and-spokes je architektonický vzor, v ktorom jednotlivé komponenty nevedia o sebe navzájom a každá komponenta systému komunikuje výhradne cez centrálny hub. Komponenty nikdy nehovoria medzi sebou a nemajú vlastný stav. Centrálny hub si udržiava stav všetkých objektov.
Navyše, hub-and-spokes sa často označuje aj ako event-driven. To platí aj pre Kubernetes. Jeho komponenty môžu generovať a sledovať udalosti. Vďaka tomu sú komponenty nezávislé a oddelené. Spokes komponenty teda špecifikujú, ktoré objekty ich zaujímajú, sledujú udalosti týchto objektov a reaguju na ne svojou business logikou.
Hladinovo riadený systém
Prečo som však na obrázku architektúry znázornil šípky iba jedným smerom? Nemali by správne ísť šípky aj od API smerom k komponentám? Nemal by byť tok udalostí od producentov ku konzumentom? Nemal by teda “hub” notifikovať komponenty? Smer šípok nie je náhodný ani nesprávny. Práve poukazuje na ďalší dôležitý koncept - Kubernetes je tzv. hladinovo riadený systém (level-triggered event system).
Tento pojem je známy ľuďom, ktorí sa zaoberajú elektrotechnikou a sekvenčnými obvodmi. V tomto kontexte poznáme dva typy riadenia:
- Hranou riadené obvody (edge-triggered)
- Hladinovo riadené obvody (level-triggered)
Čo to znamena? Predstavme si drôt, cez ktorý prechádza tok bitov. Bity sú reprezentované zmenou napätia. Ide o klasické kmitanie napätia. Hranou riadené obvody reagujú na zmenu napätia. Hladinovo riadené obvody sledujú stav napätia v ľubovoľnom čase.
Tradičné event-driven systémy, kde máme producentov a konzumentov, sú založené na hranou riadenom princípe. To znamená, že konzument je pripojený k nejakému message systému a očakáva udalosti. Keď dorazí udalosť ako správa, producent zareaguje svojou business logikou.
Lenže čo keď udalosť z nejakého dôvodu nezaznamenáme? Čo ak napríklad zlyhá sieť a udalosť sa stratí? Čo ak zlyhá samotná komponenta?
Kubernetes sa k tomuto problému stavia trochu inak - ako hladinovo riadený obvod. Komponenty sledujú objekty, ich stav a reagujú na zmeny stavu. Komponenty teda nečakajú na udalosti. Taktiež ani nepoužívajú polling v nekonečnej slučke, čo by bolo neoptimálne. Komponenta najprv získa posledný známy stav objektu a až potom prijíma udalosti o zmenách stavu. Ak dôjde k výpadku, komponenta opäť získa posledný známy stav objektu a opäť prijíma udalosti. Tento mechanizmus sa nazýva watching.
Kubernetes nás učí jednu zaujímavú vec o event-driven systémoch. Hoci je založený na udalostiach, stav objektov sa ukazuje ako veľmi užitočný.
Základné komponenty
Teraz už vieme aká je základna filozofia architektúry a ako komponenty spolu iteragujú. Poďme sa pozrieť bližšie na to, z akých konkrétnych komponentov sa Kubernetes skladá.
Kube API Server
Kube API Server je v úlohe hub-u. Ide o jeden z najdôležitejších komponentov,
ktorý predstavuje centrálny bod celej architektúry. Je vstupným bodom pre kubectl
,
ale aj pre všetky ostatné komponenty.
Okrem toho, že ide o známe REST API, je toto API generické. To znamená, že je možné ho rozšíriť o vlastné objekty a endpointy. Okrem klasických RESTových metód, ako je PUT, GET atď., toto API tiež zavádza WATCH. Táto funkcionalita je kľúčová pre sledovanie udalostí - už spomínaný watching mechanizmus.
Samozrejmosťou je aj autorizácia a autentifikácia. API Server tiež validuje, či použivateľ má oprávnenia nad objetami. Ďalej je tu možnosť ako zmeniť chovanie pomocou tzv. Admission Webhooks. O týchto som už písal v článku Injektovanie sidecarov v Kubernetes.
Etcd
Ak je Kube API Server backend, Etcd je jeho databáza. Etcd je distribuovaná NoSQL databáza, kde sa uchováva stav objektov pomocou key-value párov. Etcd je jediný komponent, s ktorým Kube API Server priamo komunikuje. Je teda výnimkou v rámci konceptu “hub-and-spoke”.
Prečo ale Etcd a nie napríklad MySQL? Jednou z výhod Etcd databázy je jej schopnosť monitorovať zmeny kľúčov a notifikovať iné systémy. Túto vlastnosť využíva Kube API Server pri watching mechanizme.
Controller Manager
Ide o jednu zo “spoke” komponent, v rámci ktorej beží základná sada tzv.
kontrolérov. Tieto kontroléry sledujú objekty vyššej úrovne, ako sú
Deployment
a ReplicaSet
, a transformujú ich na objekty nižšej úrovne,
napríklad Pod
. Čiže tu je práve tá biznis logika, ktorá riadi Deployment
atď.
Scheduler
Úlohou Schedulera je sledovať objekty Pod
a Node
. Novovytvorené Pody
sú potom priradené na základe dostupných zdrojov najoptimalnejším Node
strojom. Scheduler nie je zodpovedný za samotné spúšťanie Podov a kontajnerov.
Kubelet
Ide o neoddeliteľnú súčasť každého Node
stroja. Jeho úlohou je manažovať
všetku pracovnú záťaž na danom stroji. Jednoducho povedané, Kubelet je
zodpovedný za vytváranie podov na danom stroji. Je prepojený s tzv. container
management systémom (ContainerD, Docker) pomocou CRI rozhrania. Okrem toho sa
stará o sieť pomocou CNI rozhrania a úložiská (tzv. volumes)
pomocou CSI rozhrania. Tieto rozhrania si zaslúžia samostatný článok.
Kubeproxy
Podobne ako Kubelet, Kubeproxy je súčasťou každého Node
stroja. Jeho úlohou
je spravovať určitú časť sieťovej komunikácie, konkrétne Service
. Čoraz
častejšie sa však môžeme stretnúť s klastermi, kde Kubeproxy nie je prítomný.
Ako komponenty interagujú
Aby sme lepšie pochopili, ako táto architektúra funguje, je dobré sa pozrieť na to, ako jednotlivé komponenty navzájom interagujú. Základom sú udalosti, ktoré sledujú komponenty a objekty v systéme.
Toto môžeme názorne ukázať na jednoduchom príklade vytvorenia objektu Deployment
.
Zmena existujúceho Deployment
-u je o niečo komplikovanejšia, keďže sa potrebujeme
vysporiadať s existujúcim ReplicaSet
-om. Výsledkom nového objektu
Deployment
sú ďalšie objekty: ReplicaSet
, a potom samotné Pod
-y.
Čo sa teda udeje?
-
Pomocou kubectl pošleme nový objekt
Deployment
ako YAML na API server. API Server požiadavku zvaliduje a perzistuje nový objekt v ETCD databáze. -
V rámci Controller Managera beží špecialne určený kontrolér, ktorý sa stará o celú business logiku
Deployment
objektu. Ten sleduje všetkyDeployment
objekty a zaznamená udalosť, že bol vytvorený nový objekt. Následne zareaguje a vytvoríReplicaSet
. -
Iný kontrolér v rámci Controll Managera sleduje udalosti pre
ReplicaSet
. Zareaguje na udalosť vytvoreniaReplicaSet
svojou business logikou a začne vytvárať požadovaný počet podov.
Dostávame sa k objektu nižšej úrovne, k Podu. Ten je zaujimavý hlavne z pohľadu interakcie ďalších komponent.
-
Udalosť, že bol vytvorený nový Pod teraz zachytí Scheduler. Pod ešte nemá priradený žiaden
Node
stroj. Scheduler rozhodne na akom stroji bude pod bežať. Zapíše túto informáciu do objektu Podu cez API server. -
Kubelet na danom
Node
stroji zachytí udalosť, žePod
má priradený práve tento stroj. Kubelet následne vytvorí kontajner Podu pomocou tzv. kontajner manažera. To môže byťcontainerd
atď.
Záver
Dlho som sa vyhýbal písať o Kubernetese. Myslel som si, že nemám čo k tejto téme povedať. Kubernetes sa ale stal neodmysliteľnou súčasťou sveta kontajnerov. A stal sa aj neodmysliteľnou súčasťou mojho pracovného života. Začal som teda aj ja tráviť veľa času s Kubernetesom a jeho vnútorným svetom. Tento článok je preto začiatkom novej etapy blogu.
Podobne ako pri kontajneroch, aj pri Kubernetese (ale aj iných témach) sa budem snažiť viac pozerať “pod kapotu”. Verím, že takýto prístup si nájde u nás svoj priestor. Nechcem sa veľmi rozpisovať o základných veciach ako Pod a podobne. Ak je ale pre teba Kubernetes novým pojmom, odporúčam začať napríklad s kurzom od Fera Volára.