Kubernetes Architektúra

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:

img

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.

img

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:

Č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.

img

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.

img

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?

img

Dostávame sa k objektu nižšej úrovne, k Podu. Ten je zaujimavý hlavne z pohľadu interakcie ďalších komponent.

img

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.

<