Kontajnery, mikroservisy a service mesh

Na internete kopu článkov o v službách mesh (service mesh), a tu je ďalšia. Hurá! Ale prečo? Pretože chcem vyjadriť svoj názor, že by bolo lepšie, keby služby mesh existovali pred 10 rokmi, pred vznikom kontajnerových platforiem ako Docker a Kubernetes. Nehovorím, že môj pohľad je lepší alebo horší ako iné, ale keďže služby mesh sú dosť zložitý fenomén, rôznorodosť názorov pomôže lepšie ich pochopiť.

Povieme si o platforme dotCloud, ktorá bola postavená na viac ako stovke mikroservisov a podporovala tisíce aplikácií v kontajneroch. Vysvetlím problémy, s ktorými sme sa stretli počas jej vývoja a spustenia, a ako by mohli služby mesh pomôcť (alebo nepomôcť).

História dotCloud

Už som písal o histórii dotCloud a výbere architektúry pre túto platformu, ale málo som hovoril o sieťovej úrovni. Ak sa nechcete zaoberať čítaním predchádzajúceho článku o dotCloud, tak v skratke: je to platforma ako služba PaaS, ktorá umožňuje zákazníkom spúšťať širokú škálu aplikácií (Java, PHP, Python…), s podporou širokého spektra databázových služieb (MongoDB, MySQL, Redis…) a pracovným tokom podobným Heroku: nahrajete svoj kód na platformu, tá vytvorí obrazy kontajnerov a nasadí ich.

Povieme si, ako sa smeroval traffic na platformu dotCloud. Nie preto, že by to bolo niečo zvláštne (aj keď pre svoj čas systém fungoval celkom dobre!), ale predovšetkým preto, že s pomocou moderných nástrojov môže skromný tím takýto dizajn realizovať za krátky čas, ak potrebujú spôsob, ako smerovať traffic medzi hromadou mikroservisov alebo aplikácií. Takže môžeme porovnať možnosti: čo dostanete, ak to celé vyviniete sami alebo použijete existujúcu službu mesh. Štandardná voľba: urobiť sami alebo kúpiť.

Smerovanie trafficu pre hostované aplikácie

Aplikácie na dotCloud môžu poskytovať HTTP a TCP koncové body.

HTTP koncové body dynamicky pridávajú do konfigurácie klastra vyrovnávačov záťaže Hipache. Je to podobné tomu, čo dnes robia prostriedky Ingress v Kubernetes a vyrovnávač záťaže ako Traefik.

Zákazníci sa pripájajú ku koncovým bodom HTTP prostredníctvom príslušných domén za predpokladu, že doménové meno ukazuje na vyrovnávače záťaže dotCloud. Nič špeciálne.

TCP koncové body súvisia s číslom portu, ktorý sa následne prenáša všetkým kontajnerom tohto zásobníka prostredníctvom premenných prostredia.

Klienti sa môžu pripojiť k koncovým bodom TCP pomocou príslušného názvu hostiteľa (niečo ako gateway-X.dotcloud.com) a čísla portu.

Tento názov hostiteľa sa rozpoznáva v klastroch serverov „nats“ (nemá nijaký vzťah k NATS), ktoré smerujú prichádzajúce TCP pripojenia do správneho kontajnera (alebo, v prípade služieb s vyvažovaním záťaže, do správnych kontajnerov).

Ak ste oboznámení s Kubernetes, pravdepodobne vám to pripomenie služby NodePort.

Na platforme dotCloud neexistoval ekvivalent služieb ClusterIP: pre jednoduchosť bol prístup k službám rovnaký, ako vnútri, tak aj mimo platformy.

Všetko bolo zorganizované celkom jednoducho: prvotné implementácie sietí smerovania HTTP a TCP, pravdepodobne len pár stoviek riadkov Pythonu. Jednoduché (povedal by som, naivné) algoritmy, ktoré sa zdokonaľovali s rastom platformy a objavovaním sa ďalších požiadaviek.

Rozsiahla refaktorizácia existujúceho kódu nebola potrebná. Najmä 12-faktorové aplikácie môžu priamo využívať adresu získanú prostredníctvom premenných prostredia.

Čím sa to líši od moderného servisného mesh?

Obmedzená prehľadnosť. Vôbec sme nemali žiadne metriky pre smerovanie TCP. Čo sa týka smerovania HTTP, v neskorších verziách boli zavedené podrobné HTTP metriky s chybovými kódmi a časom odozvy, ale moderné servisné mesh idú ešte ďalej, poskytujúc integráciu so systémami na zber metrík, ako je Prometheus.

Prehľadnosť je dôležitá nielen z operačného hľadiska (aby pomáhala pri odstraňovaní problémov), ale aj pri zavádzaní nových funkcií. Hovoríme o bezpečnom modro-zelenom nasadení a kanárskom nasadení.

Efektívnosť smerovania je tiež obmedzená. V sieťovom smerovaní dotCloud musel celý traffic prechádzať cez klaster vyhradených smerovacích uzlov. To znamenalo potenciálne prekročenie niekoľkých hraníc AZ (zóny dostupnosti) a významné zvýšenie latencie. Pamätám si, ako som riešil problémy s kódom, ktorý vykonával viac ako sto SQL dopytov na stránku a pre každý dopyt otváral nové spojenie so SQL serverom. Pri lokálnom spustení sa stránka načítava okamžite, ale v dotCloud načítanie trvá niekoľko sekúnd, pretože každé TCP spojenie (a následný SQL dopyt) vyžaduje desiatky milisekúnd. V tomto konkrétnom prípade problém vyriešili trvalé spojenia.

Moderné servisné mesh lepšie zvládajú takéto problémy. Predovšetkým overujú, že spojenia sú smerované do zdroja. Logický tok zostáva rovnaký: klient → mesh → služba, ale teraz mesh funguje lokálne, a nie na vzdialených uzloch, takže spojenie klient → mesh je lokálne a veľmi rýchle (mikroseundy namiesto milisekúnd).

Moderné servisné mesh tiež implementujú inteligentnejšie algoritmy vyváženia záťaže. Monitorovaním dostupnosti backendov môžu posielať viac trafficu na rýchlejšie backendy, čo vedie k zvýšeniu celkovej výkonnosti.

Bezpečnosť je tiež lepšie. Smerovacia sieť dotCloud pracovala výhradne na EC2 Classic a nešifrovala traffic (na základe predpokladu, že ak sa niekomu podarilo nainštalovať sniffer na sieťový traffic EC2, už máte veľké problémy). Moderné servisné mesh transparentne chránia celý náš traffic, napríklad pomocou vzájomnej TLS autentifikácie a následného šifrovania.

Smerovanie trafficu pre službu platformy

Dobre, diskutovali sme o trafficu medzi aplikáciami, ale čo samotná platforma dotCloud?

Samotná platforma pozostávala z približne sto mikroslužieb, ktoré zodpovedali za rôzne funkcie. Niektoré prijímali dopyty od iných, a niektoré boli pozadoví pracovníci, ktorí sa pripájali k iným službám, ale samy neprijímali spojenia. V každom prípade, každá služba musí vedieť koncové body adries, na ktoré sa má pripojiť.

Mnohé vysokorozmerné služby môžu využívať sieť smerovania, ako je popísané vyššie. V skutočnosti bolo mnoho z viac ako sto mikroslužieb dotCloud nasadených ako bežné aplikácie na samotnej platforme dotCloud. Avšak niekoľko nízkoúrovňových služieb (konkrétne tých, ktoré realizujú túto sieť smerovania) potrebovalo niečo jednoduchšie, s menšími závislosťami (pretože na svoju činnosť nemohli závisieť samy od seba — starý dobrý problém sliepky a vajíčka).

Tieto nízkoúrovňové, dôležité služby boli nasadené spustením kontajnerov priamo na niekoľkých kľúčových uzloch. Pri tom neboli zapojené štandardné služby platformy: kompozitor, plánovač a runner. Ak chcete porovnať so súčasnými kontajnerovými platformami, je to podobné ako spustenie riadiacej roviny s docker run priamo na uzloch, namiesto delegovania úlohy Kubernetes. To dosť pripomína koncept statických modulov (podov), ktorý používa kubeadm alebo bootkube pri spúšťaní autonómneho klastru.

Tieto služby boli exponované jednoduchým a hrubým spôsobom: v súbore YAML boli uvedené ich mená a adresy; každý klient si musel pre nasadenie vziať kópiu tohto YAML súboru.

Na jednej strane je to mimoriadne spoľahlivé, pretože to nevyžaduje podporu vonkajšieho úložiska kľúčov/hodnôt, ako je Zookeeper (nezabúdajte, vtedy ešte neexistoval etcd alebo Consul). Na druhej strane to sťažovalo premiestnenie služieb. Pri každom prenose museli všetci klienti získať aktualizovaný YAML súbor (a potenciálne sa reštartovať). Nie veľmi pohodlné!

Následne sme začali zavádzať novú schému, kde sa každý klient pripájal k miestnemu proxy serveru. Namiesto adresy a portu mu stačí poznať iba číslo portu služby, a pripojiť sa cez localhost. Miestny proxy server spracováva toto spojenie a smeruje ho na skutočný server. Teraz pri presune backendu na iný stroj alebo jeho škálovaní je potrebné aktualizovať iba všetky tieto miestne proxy; reštart už nie je potrebný.

(Taktiež sa plánovalo enkapsulovať prenos v TLS pripojeniach a umiestniť ďalší proxy server na prijímajúcej strane, ako aj overovať TLS certifikáty bez účasti prijímajúcej služby, ktorá je nastavená na prijímanie pripojení len na localhost. O tom neskôr).

To veľmi pripomína SmartStack od Airbnb, ale podstatný rozdiel je, že SmartStack je implementovaný a nasadený v produkcii, zatiaľ čo vnútorný systém smerovania dotCloud bol uložený do krabice, keď sa dotCloud premenil na Docker.

Osobne považujem SmartStack za jedného z predchodcov takýchto systémov, ako sú Istio, Linkerd a Consul Connect, pretože všetky nasledujú jeden vzor:

  • Spustenie proxy na každom uzle.
  • Klienti sa pripájajú k proxy.
  • Rovnako ako správa nastavuje konfiguráciu proxy servera pri zmene backendov.
  • … Zisk!

Moderná implementácia service mesh

Ak sa dnes potrebujeme implementovať podobnú sieť, môžeme použiť analogické princípy. Napríklad nastaviť internú DNS zónu, priradiť názvy služieb k adresám v priestore 127.0.0.0/8. Potom spustiť HAProxy na každom uzle klastrom, prijímajúce pripojenia na každú adresu služby (v tejto podsieti 127.0.0.0/8) a presmerovávať/rovnomerne zatížiť na príslušné backendy. Konfigurácia HAProxy môže byť spravovaná confd, pričom umožňuje uchovávať informácie o backendoch v etcd alebo Consul a automaticky posielať aktualizovanú konfiguráciu na HAProxy, keď je to potrebné.

Približne takto funguje Istio! Ale s niektorými rozdielmi:

  • Používa Envoy Proxy namiesto HAProxy.
  • Uchováva konfiguráciu backendu cez Kubernetes API namiesto etcd alebo Consul.
  • Službám sú pridelené adresy vo vnútornej podsieti (adresy Kubernetes ClusterIP) namiesto 127.0.0.0/8.
  • Má dodatočnú zložku (Citadel) pre pridanie vzájomného overovania pôvodu TLS medzi klientom a servermi.
  • Podporuje nové funkcie, ako sú circuit breaking, rozptýlené trasovanie, nasadzovanie kanárkov a ďalšie.

Poďme stručne preskúmať niektoré rozdiely.

Envoy Proxy

Envoy Proxy napísala spoločnosť Lyft [konkurenčný Uber na trhu taxi - pozn. prekl.]. Je veľmi podobná iným proxy (napríklad HAProxy, Nginx, Traefik…), ale Lyft napísal svoju, pretože potrebovali funkcie, ktoré chýbali v iných proxy, a rozumnejšie sa im zdalo vytvoriť nový, než rozširovať existujúci.

Envoy možno používať samostatne. Ak mám konkrétnu službu, ktorá sa má pripojiť k iným službám, môžem ju nastaviť na pripojenia k Envoy a potom dynamicky konfigurovať a prekonfigurovať Envoy s umiestnením iných služieb, pričom získam množstvo skvelých doplnkových funkcií, ako je prehľadnosť. Namiesto prispôsobenej klientskej knižnice alebo implementácie sledovacieho volania smerujeme prevádzku do Envoy, ktorý pre nás zbiera metriky.

Ale Envoy je tiež schopný fungovať ako dátová rovina (data plane) pre service mesh. To znamená, že teraz pre daný service mesh je Envoy konfigurovaný ovládacou rovinou (control plane).

Ovládacia rovina

V ovládacej rovine sa Istio spolieha na Kubernetes API. To sa veľmi nelíši od použitia confd, ktorý sa spolieha na etcd alebo Consul na prehliadanie súboru kľúčov v úložisku údajov. Istio prostredníctvom Kubernetes API prehliada sadu zdrojov Kubernetes.

Medzitým: osobne mi prišla užitočná táto definícia Kubernetes API, ktorá uvádza:

Server Kubernetes API je "hlúpy server", ktorý ponúka úložisko, správu verzií, overovanie, aktualizáciu a sémantiku API zdrojov.

Istio je navrhnuté na prácu s Kubernetes; a ak ho chcete používať mimo Kubernetes, musíte spustiť inštanciu servera Kubernetes API (a pomocnej služby etcd).

Adresa služieb

Istio sa spolieha na adresy ClusterIP, ktoré pridelí Kubernetes, takže služby Istio získavajú internú adresu (nie v rozsahu 127.0.0.0/8).

Prevádzka na adresu ClusterIP pre konkrétnu službu v Kubernetes klasteri bez Istio je zachytená kube-proxy a odoslaná na backend tejto proxy. Ak vás zaujímajú technické detaily, kube-proxy nastavuje pravidlá iptables (alebo vyvažovače záťaže IPVS, v závislosti od nastavenia), aby prepísal IP adresy cieľových spojení idúcich na adresu ClusterIP.

Po nainštalovaní Istio v Kubernetes klastri sa nič nemení, pokiaľ nie je explicitne povolené pre daného spotrebiteľa alebo dokonca celý priestor mien, zavedením kontajnera sidecar do prispôsobených podov. Tento kontajner spustí inštanciu Envoy a nastaví sériu pravidiel iptables na zachytávanie prevádzky smerujúcej k iným službám a presmerovanie tejto prevádzky na Envoy.

Pri integrácii s Kubernetes DNS to znamená, že náš kód môže pripojiť po názve služby a všetko „jednoducho funguje“. Inými slovami, náš kód vydáva požiadavky typu http://api/v1/users/4242, potom api rezolví požiadavku na 10.97.105.48, pravidlá iptables zachytávajú pripojenia z 10.97.105.48 a presmerovávajú ich na lokálny proxy Envoy, a tento lokálny proxy nasmeruje požiadavku na skutočný backend API. Uf!

Dodatočné vylepšenia

Istio tiež zabezpečuje koncové šifrovanie a autentifikáciu cez mTLS (vzájomný TLS). O to sa stará komponent s názvom Citadel.

Existuje tiež komponent Mixer, ktorý môže Envoy požiadať o každú požiadavku, aby prijal špeciálne rozhodnutie o tejto požiadavke na základe rôznych faktorov, ako sú hlavičky, zaťaženie backendu atď… (neobávajte sa: existuje množstvo prostriedkov na zabezpečenie funkčnosti Mixera, a aj keby sa pokazil, Envoy bude naďalej normálne fungovať ako proxy).

A samozrejme, spomenuli sme prehľadnosť: Envoy zhromažďuje obrovské množstvo metrík a zabezpečuje pritom distribuované trasovanie. V architektúre mikroservisov, ak jedna požiadavka API musí prejsť cez mikroservisy A, B, C a D, pri vstupe do systému distribuované trasovanie pridá k požiadavke jedinečný identifikátor a uchová tento identifikátor cez podpožiadavky k všetkým týmto mikroservisom, čo umožňuje zaznamenať všetky súvisiace volania, ich oneskorenia atď.

Vyvinúť alebo kúpiť

Istio má povesť zložitého systému. Naopak, vybudovať sieť smerovania, ktorú som opísal na začiatku tohto príspevku, je relatívne jednoduché s existujúcimi nástrojmi. Takže má zmysel namiesto toho vytvárať vlastný servisný mesh?

Ak máme skromné potreby (nie je potrebná prehľadnosť, prerušovač reťazca a iné detaily), prichádzajú myšlienky na vývoj vlastného nástroja. Ale ak používame Kubernetes, ten možno ani nebude potrebný, pretože Kubernetes už poskytuje základné nástroje na objavovanie služieb a vyvažovanie zaťaženia.

Ale ak máme pokročilé požiadavky, „nájsť“ servisný mesh sa zdá byť oveľa lepšou voľbou. (Niekedy to nie je presne „nákup“, pretože Istio je dodávané s otvoreným zdrojovým kódom, ale aj tak musíme investovať inžiniersky čas na to, aby sme pochopili jeho fungovanie, nasadili ho a spravovali ho).

Čo si vybrať: Istio, Linkerd alebo Consul Connect?

Doteraz sme hovorili len o Istio, ale to nie je jediný service mesh. Populárna alternatíva je Linkerd, existuje aj Consul Connect.

Čo si vybrať?

Úprimne povedané, neviem. V súčasnosti sa nepovažujem za dostatočne kompetentného na to, aby som odpovedal na túto otázku. Existuje niekoľko zaujímavých článkov porovnaní týchto nástrojov a dokonca aj benchmarkov..

Jeden z nádejných prístupov je použiť nástroj ako SuperGloo. Implementuje vrstvu abstrakcie na zjednodušenie a unifikáciu API poskytovaných service meshmi. Namiesto toho, aby sme skúmali konkrétne (a, podľa môjho názoru, relatívne zložité) API rôznych service meshov, môžeme používať jednoduchšie konštrukcie SuperGloo – a ľahko prechádzať z jedného na druhý, ako keby sme mali medziformát konfigurácie, ktorý opisuje HTTP rozhrania a backendy, schopný generovať skutočnú konfiguráciu pre Nginx, HAProxy, Traefik, Apache…

Trochu som si pohral s Istio a SuperGloo a v nasledujúcom článku chcem ukázať, ako pridať Istio alebo Linkerd do existujúceho klastrového systému pomocou SuperGloo a ako si posledný poradí so svojou prácou, teda umožní prechádzať z jedného service mesh na druhý bez prepisovania konfigurácií.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster