Kontejneri, mikroservisi i servisne mreže

Na Internetu gomila članci о servisna mreža (servisna mreža), a evo još jedne. hura! Ali zašto? Zatim, želim izraziti svoje mišljenje da bi bilo bolje da su se servisne mreže pojavile prije 10 godina, prije pojave kontejnerskih platformi kao što su Docker i Kubernetes. Ne kažem da je moje gledište bolje ili lošije od drugih, ali budući da su servisne mreže prilično složene životinje, više gledišta pomoći će da ih bolje razumijemo.

Govorit ću o dotCloud platformi koja je izgrađena na više od stotinu mikroservisa i podržava tisuće kontejnerskih aplikacija. Objasnit ću izazove s kojima smo se susreli u razvoju i pokretanju te kako mrežne mreže usluga mogu (ili ne mogu) pomoći.

Povijest dotClouda

Pisao sam o povijesti dotClouda i izboru arhitekture za ovu platformu, ali nisam puno govorio o mrežnom sloju. Ako ne želite uroniti u čitanje posljednji članak o dotCloudu, evo ukratko suštine: to je PaaS platforma-kao-usluga koja korisnicima omogućuje pokretanje širokog spektra aplikacija (Java, PHP, Python...), uz podršku za širok raspon podataka servisi (MongoDB, MySQL, Redis...) i tijek rada kao što je Heroku: Vi učitate svoj kod na platformu, ona izrađuje slike spremnika i postavlja ih.

Reći ću vam kako je promet usmjeren na dotCloud platformu. Ne zato što je bio posebno cool (iako je sustav dobro funkcionirao za svoje vrijeme!), nego prvenstveno zato što s modernim alatima takav dizajn može lako implementirati u kratkom vremenu skromni tim ako treba način za usmjeravanje prometa između gomile mikroservisa ili hrpe aplikacija. Na ovaj način možete usporediti opcije: što će se dogoditi ako sve sami razvijete ili koristite postojeći servisni mesh. Standardni izbor je da ga sami napravite ili kupite.

Usmjeravanje prometa za hostirane aplikacije

Aplikacije na dotCloudu mogu izložiti HTTP i TCP krajnje točke.

HTTP krajnje točke dinamički dodano u konfiguraciju klastera balansera opterećenja Hipache. To je slično onome što resursi rade danas Ulaz u Kubernetesu i balanseru opterećenja poput Traefik.

Klijenti se povezuju s HTTP krajnjim točkama putem odgovarajućih domena, pod uvjetom da naziv domene upućuje na dotCloud balansere opterećenja. Ništa posebno.

TCP krajnje točke povezan s brojem porta, koji se zatim prosljeđuje svim spremnicima u tom stogu putem varijabli okruženja.

Klijenti se mogu povezati s TCP krajnjim točkama pomoću odgovarajućeg naziva glavnog računala (nešto poput gateway-X.dotcloud.com) i broja priključka.

Ovo ime hosta rješava se klasterom poslužitelja "nats" (nije povezano s NATS), koji će usmjeriti dolazne TCP veze u ispravan spremnik (ili, u slučaju usluga s uravnoteženim opterećenjem, na ispravne spremnike).

Ako ste upoznati s Kubernetesom, ovo će vas vjerojatno podsjetiti na usluge Čvorni priključak.

Nije bilo ekvivalentnih usluga na platformi dotCloud KlasterIP: Radi jednostavnosti, uslugama se pristupalo na isti način unutar i izvan platforme.

Sve je bilo organizirano vrlo jednostavno: početne implementacije HTTP i TCP mreža za usmjeravanje bile su vjerojatno samo nekoliko stotina redaka Pythona. Jednostavni (rekao bih naivni) algoritmi koji su se usavršavali kako je platforma rasla i pojavljivali se dodatni zahtjevi.

Nije bilo potrebno opsežno refaktoriranje postojećeg koda. Posebno, 12 faktorskih aplikacija može izravno koristiti adresu dobivenu kroz varijable okoline.

Kako se ovo razlikuje od moderne servisne mreže?

Ograničeno vidljivost. Nismo uopće imali nikakve metrike za TCP mrežu usmjeravanja. Kada je riječ o HTTP usmjeravanju, kasnije verzije uvele su detaljne HTTP metrike s kodovima grešaka i vremenima odgovora, ali moderne mrežne mreže idu još dalje, pružajući integraciju sa sustavima za prikupljanje metrika kao što je Prometheus, na primjer.

Vidljivost je važna ne samo iz operativne perspektive (kako bi se pomoglo u rješavanju problema), već i kada se izdaju nove značajke. Radi se o sigurnom plavo-zeleni raspored и kanarski raspored.

Učinkovitost usmjeravanja također je ograničen. U mreži za usmjeravanje dotCloud sav je promet morao proći kroz klaster namjenskih čvorova za usmjeravanje. To je značilo potencijalno prelaženje višestrukih granica AZ (zone dostupnosti) i značajno povećanje latencije. Sjećam se koda za rješavanje problema koji je stvarao preko stotinu SQL upita po stranici i otvarao novu vezu sa SQL poslužiteljem za svaki upit. Kada se izvodi lokalno, stranica se učitava trenutno, ali u dotCloudu potrebno je nekoliko sekundi za učitavanje jer svaka TCP veza (i naknadni SQL upit) traje desetke milisekundi. U ovom konkretnom slučaju, stalne veze riješile su problem.

Moderne servisne mreže bolje se nose s takvim problemima. Prije svega, provjeravaju jesu li veze usmjerene u izvoru. Logički tok je isti: клиент → меш → сервис, ali sada mreža radi lokalno, a ne na udaljenim čvorovima, tako da veza клиент → меш je lokalna i vrlo brza (mikrosekunde umjesto milisekundi).

Moderne servisne mreže također implementiraju pametnije algoritme za uravnoteženje opterećenja. Praćenjem stanja pozadinskih sustava, oni mogu poslati više prometa bržim pozadinskim sustavima, što rezultira poboljšanom općom izvedbom.

sigurnosti bolje također. Mreža za usmjeravanje dotCloud radila je u potpunosti na EC2 Classic i nije šifrirala promet (temeljeno na pretpostavci da ako je netko uspio staviti njuškalo na EC2 mrežni promet, već ste bili u velikoj nevolji). Suvremene mrežne mreže transparentno štite sav naš promet, na primjer, međusobnom TLS autentifikacijom i naknadnom enkripcijom.

Usmjeravanje prometa za usluge platforme

U redu, razgovarali smo o prometu između aplikacija, ali što je sa samom platformom dotCloud?

Sama platforma sastojala se od stotinjak mikroservisa zaduženih za različite funkcije. Neki su prihvaćali zahtjeve drugih, a neki su bili pozadinski radnici koji su se povezivali s drugim uslugama, ali sami nisu prihvaćali veze. U svakom slučaju, svaki servis mora znati krajnje točke adresa na koje se treba spojiti.

Mnoge usluge visoke razine mogu koristiti gore opisanu mrežu usmjeravanja. Zapravo, mnoge od više od stotinu dotCloudovih mikroservisa postavljene su kao redovite aplikacije na samoj dotCloud platformi. Ali mali broj servisa niske razine (osobito onih koji implementiraju ovu mrežu usmjeravanja) trebao je nešto jednostavnije, s manje ovisnosti (budući da se nisu mogli osloniti na sebe da rade - dobri stari problem kokoši i jajeta).

Ove usluge niske razine, ključne za misiju, postavljene su pokretanjem spremnika izravno na nekoliko ključnih čvorova. U ovom slučaju nisu korišteni standardni servisi platforme: povezivač, planer i pokretač. Ako se želite usporediti s modernim kontejnerskim platformama, to je kao da upravljate kontrolnom ravninom docker run izravno na čvorovima, umjesto delegiranja zadatka Kubernetesu. Prilično je sličan po konceptu statički moduli (podovi), koje koristi kubeadm ili bootkube prilikom dizanja samostalnog klastera.

Te su usluge razotkrivene na jednostavan i grub način: YAML datoteka navodi njihova imena i adrese; i svaki je klijent morao uzeti kopiju ove YAML datoteke za implementaciju.

S jedne strane, izuzetno je pouzdan jer ne zahtijeva podršku eksternog ključa/vrijednosti kao što je Zookeeper (sjetite se, etcd ili Consul nisu postojali u to vrijeme). S druge strane, otežavalo je premještanje službi. Svaki put kad bi se pomaknuo, svi bi klijenti primili ažuriranu YAML datoteku (i potencijalno bi se ponovno pokrenuli). Nije baš ugodno!

Nakon toga, počeli smo implementirati novu shemu, gdje se svaki klijent povezivao na lokalni proxy poslužitelj. Umjesto adrese i porta, treba znati samo broj porta usluge i povezati se putem localhost. Lokalni proxy upravlja ovom vezom i prosljeđuje je stvarnom poslužitelju. Sada, kada pozadinu premještate na drugo računalo ili skalirate, umjesto ažuriranja svih klijenata, trebate samo ažurirati sve ove lokalne proxyje; i ponovno pokretanje više nije potrebno.

(Također je planirano enkapsulirati promet u TLS veze i staviti još jedan proxy server na prijemnu stranu, kao i verificirati TLS certifikate bez sudjelovanja primajućeg servisa koji je konfiguriran da prihvaća veze samo na localhost. Više o ovome kasnije).

Ovo je vrlo slično SmartStack od Airbnba, ali značajna razlika je u tome što je SmartStack implementiran i raspoređen u produkciju, dok je dotCloudov interni sustav usmjeravanja odbačen kada je dotCloud postao Docker.

Osobno smatram da je SmartStack jedan od prethodnika sustava kao što su Istio, Linkerd i Consul Connect jer svi slijede isti obrazac:

  • Pokrenite proxy na svakom čvoru.
  • Klijenti se spajaju na proxy.
  • Kontrolna ravnina ažurira proxy konfiguraciju kada se pozadina promijeni.
  • ... Profit!

Suvremena izvedba servisne mreže

Da danas trebamo implementirati sličnu mrežu, mogli bismo koristiti slična načela. Na primjer, konfigurirajte unutarnju DNS zonu preslikavanjem naziva usluga na adrese u prostoru 127.0.0.0/8. Zatim pokrenite HAProxy na svakom čvoru u klasteru, prihvaćajući veze na svakoj servisnoj adresi (u toj podmreži 127.0.0.0/8) i preusmjeravanje/balansiranje opterećenja na odgovarajuće pozadine. HAProxy konfiguracija se može kontrolirati konf, što vam omogućuje pohranjivanje pozadinskih informacija u etcd ili Consul i automatsko slanje ažurirane konfiguracije na HAProxy kada je to potrebno.

Otprilike ovako funkcionira Istio! Ali s nekim razlikama:

  • Koristi Izaslanik Proxy umjesto HAProxy.
  • Pohranjuje pozadinsku konfiguraciju putem Kubernetes API-ja umjesto etcd-a ili Consula.
  • Uslugama su dodijeljene adrese na internoj podmreži (Kubernetes ClusterIP adrese) umjesto 127.0.0.0/8.
  • Ima dodatnu komponentu (Citadel) za dodavanje međusobne TLS provjere autentičnosti između klijenta i poslužitelja.
  • Podržava nove značajke kao što su prekidanje strujnog kruga, distribuirano praćenje, implementacija Canary itd.

Pogledajmo na brzinu neke od razlika.

Izaslanik Proxy

Envoy Proxy je napisao Lyft [Uberov konkurent na taksi tržištu – cca. traka]. U mnogočemu je sličan drugim proxyjima (npr. HAProxy, Nginx, Traefik...), ali Lyft je napisao svoj jer su im trebale značajke koje drugim proxyjima nedostaju, a činilo se pametnijim napraviti novi nego proširiti postojeći.

Envoy se može koristiti samostalno. Ako imam određenu uslugu koja se treba povezati s drugim uslugama, mogu je konfigurirati da se poveže s Envoyem, a zatim dinamički konfigurirati i ponovno konfigurirati Envoy s lokacijom drugih usluga, dok dobivam mnogo sjajnih dodatnih funkcija, kao što je vidljivost. Umjesto prilagođene klijentske biblioteke ili ubacivanja tragova poziva u kod, šaljemo promet Envoyu, a on prikuplja metrike za nas.

Ali Envoy je također sposoban raditi kao podatkovna ravnina (podatkovna ravnina) za servisnu mrežu. To znači da je Envoy sada konfiguriran za ovu servisnu mrežu kontrolna ravnina (kontrolna ravnina).

Kontrolna ravnina

Za kontrolnu razinu, Istio se oslanja na Kubernetes API. Ovo se ne razlikuje puno od korištenja confd, koji se oslanja na etcd ili Consul za pregled skupa ključeva u pohrani podataka. Istio koristi Kubernetes API za pregled skupa Kubernetes resursa.

Između ovoga i tada: Osobno sam ovo smatrao korisnim Opis Kubernetes API-jakoji glasi:

Kubernetes API poslužitelj je "glupi poslužitelj" koji nudi pohranu, izradu verzija, provjeru valjanosti, ažuriranje i semantiku za API resurse.

Istio je dizajniran za rad s Kubernetesom; a ako ga želite koristiti izvan Kubernetesa, tada trebate pokrenuti instancu Kubernetes API poslužitelja (i etcd pomoćne usluge).

Adrese servisa

Istio se oslanja na ClusterIP adrese koje Kubernetes dodjeljuje, tako da Istio usluge primaju internu adresu (nije u rasponu 127.0.0.0/8).

Promet prema ClusterIP adresi za određenu uslugu u Kubernetes klasteru bez Istioa presreće kube-proxy i šalje ga u pozadinu tog proxyja. Ako ste zainteresirani za tehničke detalje, kube-proxy postavlja iptables pravila (ili IPVS load balancers, ovisno o tome kako je konfiguriran) za prepisivanje odredišnih IP adresa veza koje idu na ClusterIP adresu.

Jednom kada se Istio instalira na Kubernetes klaster, ništa se ne mijenja dok se eksplicitno ne omogući za danog potrošača, ili čak cijeli prostor imena, uvođenjem spremnika sidecar u prilagođene mahune. Ovaj će spremnik pokrenuti instancu Envoya i postaviti skup pravila iptables za presretanje prometa koji ide na druge usluge i preusmjeriti taj promet na Envoy.

Kada je integriran s Kubernetes DNS-om, to znači da se naš kod može povezati prema nazivu usluge i sve "jednostavno radi". Drugim riječima, naš kod šalje upite poput http://api/v1/users/4242tada api riješiti zahtjev za 10.97.105.48, pravila iptables će presresti veze s 10.97.105.48 i proslijediti ih lokalnom Envoy proxyju, a taj će lokalni proxy proslijediti zahtjev stvarnom backend API-ju. Fuj!

Dodatni ukrasi

Istio također nudi end-to-end enkripciju i autentifikaciju putem mTLS-a (uzajamni TLS). Komponenta tzv Citadela.

Tu je i komponenta Mikser, koje izaslanik može zatražiti svaki zahtjev za donošenje posebne odluke o tom zahtjevu ovisno o različitim čimbenicima kao što su zaglavlja, opterećenje pozadine, itd... (ne brinite: postoji mnogo načina da Mixer radi, čak i ako se sruši, Envoy će nastaviti raditi u redu kao opunomoćenik) .

I, naravno, spomenuli smo vidljivost: Envoy prikuplja ogromnu količinu metrike dok pruža distribuirano praćenje. U arhitekturi mikroservisa, ako jedan API zahtjev mora proći kroz mikroservise A, B, C i D, tada će nakon prijave distribuirano praćenje dodati jedinstveni identifikator zahtjevu i pohraniti ovaj identifikator kroz podzahtjeve svim tim mikroservisima, dopuštajući svi povezani pozivi koji se trebaju uhvatiti. kašnjenja itd.

Razviti ili kupiti

Istio ima reputaciju složenog. Nasuprot tome, izgradnja mreže za usmjeravanje koju sam opisao na početku ovog posta relativno je jednostavna korištenjem postojećih alata. Dakle, ima li smisla umjesto toga izraditi vlastitu servisnu mrežu?

Ako imamo skromne potrebe (ne trebamo vidljivost, prekidač i druge suptilnosti), onda razmišljamo o razvoju vlastitog alata. Ali ako koristimo Kubernetes, možda neće biti ni potreban jer Kubernetes već nudi osnovne alate za otkrivanje servisa i balansiranje opterećenja.

Ali ako imamo napredne zahtjeve, onda se “kupnja” servisne mreže čini puno boljom opcijom. (Ovo nije uvijek "kupnja" jer je Istio otvorenog koda, ali još uvijek trebamo uložiti inženjersko vrijeme da bismo ga razumjeli, implementirali i upravljali njime.)

Trebam li odabrati Istio, Linkerd ili Consul Connect?

Do sada smo govorili samo o Istiu, ali ovo nije jedini servisni mesh. Popularna alternativa - Linkerd, i ima još toga Consul Connect.

Što odabrati?

Iskreno, ne znam. Trenutno se ne smatram dovoljno kompetentnim odgovoriti na ovo pitanje. Ima ih nekoliko zanimljiv članci uz usporedbu tih alata i čak mjerila.

Jedan obećavajući pristup je korištenje alata poput SuperGloo. Implementira sloj apstrakcije za pojednostavljenje i objedinjavanje API-ja izloženih mrežama usluga. Umjesto učenja specifičnih (i, po mom mišljenju, relativno složenih) API-ja različitih uslužnih mreža, možemo koristiti jednostavnije konstrukcije SuperGlooa - i lako se prebacivati ​​s jedne na drugu, kao da imamo posredni konfiguracijski format koji opisuje HTTP sučelja i pozadinske sposobne generiranja stvarne konfiguracije za Nginx, HAProxy, Traefik, Apache...

Malo sam se bavio Istiom i SuperGlooom, au sljedećem članku želim pokazati kako dodati Istio ili Linkerd postojećem klasteru pomoću SuperGlooa i kako potonji obavlja posao, odnosno omogućuje vam da se prebacite s jedan mesh usluge na drugi bez prepisivanja konfiguracija.

Izvor: www.habr.com

Dodajte komentar