Kontejneri, mikrosluzbe i servisne mreže

Na internetu je veliko članov o servisnih mreža (service mesh), i evo još jedne. Hura! Ali zašto? Zato što želim izložiti svoje mišljenje da bi bilo bolje da su servisne mreže nastale pre 10 godina, pre nego što su se pojavile platforme kao što su Docker i Kubernetes. Ne tvrdim da je moje gledište bolje ili lošije od drugih, ali pošto su servisne mreže prilično složene, različite perspektive će pomoći da ih bolje razumemo.

Govoriću o platformi dotCloud, koja je izgrađena na više od stotinu mikroservisa i podržavala je hiljade aplikacija u kontejnerima. Objasniću probleme sa kojima smo se suočili tokom njenog razvoja i pokretanja, i kako bi servisne mreže mogle pomoći (ili ne).

Istorija dotCloud

Već sam pisao o istoriji dotCloud i izboru arhitekture za ovu platformu, ali malo sam govorio o mrežnom nivou. Ako ne želite da se upuštate u čitanje prejšnje objave o dotCloud-u, evo ukratko: ovo je platforma kao usluga PaaS, koja omogućava klijentima da pokreću širok spektar aplikacija (Java, PHP, Python…), uz podršku raznolikih baza podataka (MongoDB, MySQL, Redis…) i radni tok kao kod Herokua: učitavate svoj kod na platformu, ona gradi slike kontejnera i raspoređuje ih.

Govoriću o tome kako je saobraćaj bio usmeren na platformu dotCloud. Ne zato što je to bilo posebno sjajno (iako je sistem u svoje vreme dobro radio!), već pre svega zato što savremeni alati omogućavaju malo timovima da lako implementiraju takav dizajn u kratkom vremenu ako im je potreban način za usmeravanje saobraćaja između mnoštva mikroservisa ili aplikacija. Tako se mogu uporediti opcije: šta se dešava ako sve razvijate sami ili koristite postojeću servisnu mrežu. Standardan izbor: napraviti sami ili kupiti.

Upravljanje saobraćajem za hosted aplikacije

Aplikacije na dotCloud mogu pružati HTTP i TCP krajnje tačke.

HTTP krajnje tačke dinamički se dodaju u konfiguraciju klastera balansirača opterećenja Hipache. Ovo je slično onome što danas rade resursi Ingress u Kubernetes-u i balansiraču opterećenja kao što je Traefik.

Klijenti se povezuju na HTTP krajnje tačke putem odgovarajućih domena pod uslovom da domena usmerava na balansirače opterećenja dotCloud. Ništa posebno.

TCP krajnje tačke so povezani s številko vrat, ki se nato prenese vsem kontejnerjem tega kupa preko okoljskih spremenljivk.

Stranke se lahko povežejo na TCP končne točke, tako da uporabijo ustrezno ime gostitelja (nekaj takega kot gateway-X.dotcloud.com) in številko vrat.

To ime gostitelja se razreši na grozd strežnikov 'nats' (ni povezano z NATS), ki bodo usmerjali prihajajoče TCP povezave v pravi kontejner (ali, v primeru storitev z obremenitvenim ravnoteženjem, v prave kontejnerje).

Če ste seznanjeni s Kubernetesom, vas bo to verjetno spomnilo na storitve NodePort.

Na platformi dotCloud ni bilo ekvivalenta storitvam ClusterIP: za enostavnost je bil dostop do storitev enak znotraj in zunaj platforme.

Vse je bilo organizirano dovolj preprosto: prvotne implementacije omrežne usmeritve HTTP in TCP so verjetno imele le nekaj sto vrstic Pythona. Enostavni (bi rekel, naivni) algoritmi, ki so se dopolnjevali z rastjo platforme in z novimi zahtevami.

Obsežno prenavljanje obstoječega kode ni bilo potrebno. Še posebej, 12-faktorske aplikacije lahko neposredno uporabljajo naslov, prejet preko okoljskih spremenljivk.

Kako se to razlikuje od sodobnega servisa mesh?

Omejene preglednosti. Nismo imeli nobenih metričnih podatkov za TCP usmerjanje. Kar se tiče HTTP usmerjanja, so kasnejše različice prinesle podrobne HTTP metrike z napakami in časom odziva, vendar sodobni servisi mesh gredo še dlje in zagotavljajo integracijo z sistemi za zbiranje metrik, kot je na primer Prometheus.

Preglednost je pomembna ne le z operativnega vidika (da pomaga pri reševanju težav), ampak tudi pri uvajanju novih funkcij. Govorimo o varnem modro-zelenskem uvajanju in uvajanju kanarčkov.

Učinkovitost usmerjanja je omejena. V omrežju usmerjanja dotCloud je moral skozi vozlišče specializiranih usmerjevalnikov preiti ves promet. To je pomenilo potencialno prečkanje več meja AZ (območij dostopnosti) in znatno povečanje zamude. Spomnim se, kako sem odpravljal težave s kodo, ki je na stran izvajala več kot sto poizvedb SQL in za vsako poizvedbo odprla novo povezavo s strežnikom SQL. Pri lokalnem zagonu se stran naloži takoj, a v dotCloudu nalaganje traja nekaj sekund, ker za vsako TCP-povezavo (in naslednjo SQL-poizvedbo) potrebujemo desetine milisekund. V tem konkretnem primeru je težavo rešila stalna povezava.

Sodobni storitveni meshi se bolje spopadajo s takšnimi težavami. Predvsem preverjajo, ali so povezave usmerjene v vir. Logični tok je enak: odjemalec → mesh → storitev, vendar zdaj mesh deluje lokalno, ne na oddaljenih vozliščih, zato je povezava odjemalec → mesh lokalna in zelo hitra (mikrosekunde namesto milisekund).

Sodobni storitveni meshi prav tako uresničujejo pametnejše algoritme za uravnoteženje obremenitve. S spremljanjem delovanja zadnjih delov lahko pošljejo več prometa na hitrejše zadnje dele, kar poveča skupno zmogljivost.

Sigurnost tudi bolje. Mreža usmerjanja dotCloud je delovala povsem na EC2 Classic in ni šifrirala prometa (na podlagi predpostavke, da imate že velike težave, če je nekdo uspešno vgradi sniffer za omrežni promet EC2). Sodobni storitveni meshi prozorno zaščitijo ves naš promet, na primer z medsebojno avtentikacijo TLS in nadaljnjim šifriranjem.

Usmerjanje prometa za storitve platforme

Dobro, govorili smo o prometu med aplikacijami, vendar kaj pa sama platforma dotCloud?

Sama platforma je bila sestavljena iz približno sto mikroservisov, ki so odgovorni za različne funkcije. Nekateri so sprejemali zahtevke od drugih, nekateri pa so bili ozadni delavci, ki so se povezovali z drugimi storitvami, vendar sami niso sprejemali povezav. V vsakem primeru mora vsaka storitev vedeti ciljne točke naslovov, s katerimi se je treba povezati.

Mnoge visoke usluge mogu koristiti mrežu usmjeravanja opisanu iznad. U stvarnosti, mnoge od više od stotinu mikroservisa dotCloud su implementirane kao obične aplikacije na samoj platformi dotCloud. No, mali broj niskonivskih usluga (posebno onih koje implementiraju ovu mrežu usmjeravanja) zahtijevao je nešto jednostavnije, s manje ovisnosti (jer nisu mogle ovisiti same o sebi — stara dobra problem piletine i jajeta).

Ove niskonivske, važne usluge su implementirane pokretanjem kontejnera direktno na nekoliko ključnih čvorova. Pri tome nisu korištene standardne usluge platforme: kompilator, planirnik i runner. Ako želite usporediti s modernim kontejnerskim platformama, to je slično pokretanju upravljačke ravni s docker run direktno na čvorovima, umjesto da delegiraju zadatak Kubernetesu. To je prilično slično konceptu statičkih modula (podova)koje koristi kubeadm ili bootkube pri pokretanju autonomnog klastera.

Ove su usluge izložene jednostavno i grubo: u YAML datoteci su navedena njihova imena i adrese; a svaki klijent trebao je uzeti kopiju ove YAML datoteke za implementaciju.

S jedne strane, to je izuzetno pouzdano, jer ne zahtijeva podršku vanjskog skladišta ključeva/vrijednosti, kao što je Zookeeper (ne zaboravite, tada još nije postojao etcd ili Consul). S druge strane, otežavalo je premještanje usluga. Svaki put kada bi se usluga premjestila, svi klijenti bi morali dobiti ažuriranu YAML datoteku (i potencijalno se ponovo pokrenuti). Nije baš praktično!

Kasnije smo počeli implementirati novu shemu, gdje se svaki klijent povezivao na lokalni proxy-server. Umjesto adrese i porta, bilo mu je dovoljno znati samo broj porta usluge, i povezivati se putem localhost. Lokalni proxy-server obrađuje ovu vezu i preusmjerava je na stvarni server. Sada, prilikom premještanja backend-a na drugu mašinu ili skaliranja, umjesto ažuriranja svih klijenata, potrebno je ažurirati samo te lokalne proxy-e; i ponovno pokretanje više nije potrebno.

(Prav tako je bilo načrtovano, da se promet enkapsulira v TLS-povezavah in doda še en proxy strežnik na sprejemni strani, poleg tega pa tudi preveriti TLS certifikate brez sodelovanja sprejemne storitve, ki je nastavljena za sprejem povezav le na localhost. O tem kasneje).

To je zelo podobno SmartStack podjetja Airbnb, vendar je bistvena razlika v tem, da je SmartStack implementiran in uveden v produkcijo, medtem ko je bila notranja sistemska usmeritev dotCloud umaknjena v predal, ko je dotCloud postal Docker.

Osebno menim, da je SmartStack eden od predhodnikov sistemov, kot so Istio, Linkerd in Consul Connect, ker vsi sledijo istemu vzorcu:

  • Zagon proxyja na vsakem vozlišču.
  • Stranke se povezujejo na proxy.
  • Upravna raven posodobi konfiguracijo proxy strežnika, ko se spremenijo zadnjič.
  • … Dobiček!

Sodobna realizacija servisne mreže

Če bi danes želeli реализировать tako mrežo, bi lahko uporabili podobna načela. Na primer, nastaviti interno DNS območje, ki povezuje imena storitev z naslovi v prostoru 127.0.0.0/8. Nato zagnati HAProxy na vsakem vozlišču grozda, ki sprejema povezave na vsak naslov storitve (v tem podomrežju 127.0.0.0/8) in preusmerjati/balansirati obremenitev na ustrezne zadnje storitve. Konfiguracija HAProxy se lahko upravlja confd, kar omogoča shranjevanje informacij o zadnjih storitvah v etcd ali Consul in samodejno potisniti posodobljeno konfiguracijo na HAProxy, ko to postane potrebno.

Takole deluje Istio! Vendar s nekaterimi razlikami:

  • Uporablja Envoy Proxy namesto HAProxy.
  • Ohranja konfiguracijo zadnjih storitev prek Kubernetes API namesto etcd ali Consul.
  • Storitvam dodeljuje naslove v notranjem podomrežju (naslovi Kubernetes ClusterIP) namesto 127.0.0.0/8.
  • Ima dodatno komponento (Citadel) za dodajanje medsebojne avtentikacije TLS med stranko in strežniki.
  • Podpira nove funkcionalnosti, kot so prekinitev verige (circuit breaking), razdeljena sleditev, namestitev kanarčkov itd.

Poglejmo na kratko nekatere razlike.

Envoy Proxy

Envoy Proxy je napisal podjetje Lyft [konkurent Uberja na trgu taksijev – op. prev.]. Je zelo podoben drugim proxyjem (kot so HAProxy, Nginx, Traefik…), vendar ga je Lyft napisal, ker so potrebovali funkcije, ki jih drugi proxyji niso imeli, in se je zdelo smiselno izdelati novega, kot pa širiti obstoječega.

Envoy se lahko uporablja samostojno. Če imam določeno storitev, ki se mora povezati z drugimi storitvami, jo lahko nastavim za povezovanje z Envoyem, nato pa dinamično nastavljam in prilagajam Envoy z lokacijami drugih storitev, pri čemer dobim številne odlične dodatne funkcije, kot so preglednost. Namesto po meri izdelane odjemalske knjižnice ali vgrajevanja sledenja klicem usmerimo promet v Envoy, ki zbere metrike za nas.

Toda Envoy je tudi zmožen delovati kot podatkovna plast (data plane) za storitveni mrežni sistem. To pomeni, da je zdaj za ta storitveni mrežni sistem Envoy nastavljen nadzorne plasti (control plane).

Nadzorna plast

V nadzorni plasti Istio zanaša na Kubernetes API. To se ne razlikuje prav dosti od uporabe confd, ki se zanaša na etcd ali Consul za pregled sklopa ključev v podatkovnem skladišču. Istio prek Kubernetes API pregleduje nabor Kubernetes virov.

Medtem: osebno se mi je to opisovanje Kubernetes API, ki pravi:

Kubernetes API strežnik je 'pokriven strežnik', ki ponuja shranjevanje, upravljanje različic, preverjanje, posodobitve in semantiko API virov.

Istio je zasnovan za delo s Kubernetes; in če ga želite uporabiti zunaj Kubernetes, morate zagnati instanco Kubernetes API strežnika (in pomožne storitve etcd).

Naslovi storitev

Istio se zanaša na naslove ClusterIP, ki jih dodeli Kubernetes, zato storitve Istio dobijo notranji naslov (ne v razponu 127.0.0.0/8).

Promet na naslov ClusterIP za določeno storitev v Kubernetes klasterju brez Istio preusmeri kube-proxy in ga pošlje na serversko stran tega proxyja. Če vas zanimajo tehnične podrobnosti, kube-proxy nastavi pravila iptables (ali IPVS usmerjevalnike prometa, odvisno od tega, kako je nastavljen), da prepiše destinacijske IP naslove povezav, ki potujejo po naslovu ClusterIP.

Po namestitvi Istio v Kubernetes klasterju se nič ne spremeni, dokler ni izrecno omogočen za določenega uporabnika ali celo za celotno prostor imen, s tem da vstavite kontejner sidecar v prilagojene pod. Ta kontejner bo zagnal instanco Envoy in vzpostavil niz pravil iptables za prestrezanje prometa, ki gre do drugih storitev, in preusmeril ta promet na Envoy.

При интеграции с Kubernetes DNS это означает, что наш код может подключаться по имени службы, и всё «просто работает». Другими словами, наш код выдаёт запросы типа http://api/v1/users/4242, тогда api резолвит запрос на 10.97.105.48, правила iptables перехватывают соединения с 10.97.105.48 и перенаправляют их на локальный прокси Envoy, а этот локальный прокси направит запрос на фактический бэкенд API. Фух!

Дополнительные рюшечки

Istio также обеспечивает сквозное шифрование и аутентификацию через mTLS (mutual TLS). За это отвечает компонент под названием Citadel.

Также есть компонент Mixer, который Envoy может запросить для svaki запроса, чтобы принять специальное решение об этом запросе в зависимости от различных факторов, таких как заголовки, загрузка бэкенда и т. д… (не волнуйтесь: есть много средств обеспечить работоспособность Mixer, и даже если он слетит, Envoy продолжит нормально работать как прокси).

И, конечно, мы упомянули обзорность: Envoy собирает огромное количество метрик, обеспечивая при этом распределённую трассировку. В архитектуре микросервисов, если один запрос API должен пройти через микросервисы A, B, C и D, то при входе в систему распределённая трассировка добавит к запросу уникальный идентификатор и сохранит данный идентификатор через подзапросы ко всем этим микросервисам, позволяя фиксировать все связанные вызовы, их задержки и т. д.

Разрабатывать или купить

У Istio репутация сложной системы. Напротив, построение сетки маршрутизации, которую я описал в начале этого поста, относительно просто с помощью существующих инструментов. Итак, есть ли смысл вместо этого создавать собственный сервис-меш?

Если у нас скромные потребности (не нужна обзорность, прерыватель цепи и другие тонкости), то приходят мысли о разработке собственного инструмента. Но если мы используем Kubernetes, он может даже не понадобиться, потому что Kubernetes уже предоставляет базовые инструменты для обнаружения служб и балансировки нагрузки.

Но если у нас продвинутые требования, то «покупка» сервис-меша представляется намного лучшим вариантом. (Это не всегда именно «покупка», поскольку Istio поставляется с открытым исходным кодом, но нам всё равно нужно инвестировать инженерное время, чтобы разобраться в его работе, задеплоить и управлять им).

Kaj izbrati: Istio, Linkerd ali Consul Connect?

Do zdaj smo govorili le o Istiu, vendar to ni edini servisni mesh. Priljubljena alternativa je Linkerd, poleg tega pa obstajajo še Consul Connect.

Kaj izbrati?

Iskreno, ne vem. Trenutno se ne čutim dovolj usposobljenega, da bi odgovoril na to vprašanje. Obstaja nekaj zanimivih članov primerjav teh orodij in celo benchmarkov.

Eden od obetavnih pristopov je uporaba orodja, kot je SuperGloo. To implementira plast abstrakcije za poenostavitev in unifikacijo API-jev, ki jih ponujajo servisni meshi. Namesto da bi se učili specifičnih (in, po mojem mnenju, razmeroma zapletenih) API-jev različnih servisnih meshov, lahko uporabimo preprostejše konstrukcije SuperGloo - in enostavno preklapljamo z enega na drugega, kot da imamo vmesni format konfiguracije, ki opisuje HTTP vmesnike in backende, sposoben generirati dejansko konfiguracijo za Nginx, HAProxy, Traefik, Apache...

Malce sem se igral z Istio in SuperGloo, v naslednjem članku pa želim pokazati, kako dodati Istio ali Linkerd v obstoječi klaster s pomočjo SuperGloo, in kako se zadnji upravičuje, kar pomeni, da omogoča preklaplanje z enega servisnega mesha na drugega brez prepisovanja konfiguracij.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster