Konteineri, mikropakalpojumi un servisa tīklotāji

Internets ir daudz rakstus o pakalpojumu mezglu (service mesh), un šeit ir vēl viens. Jēdziens! Bet kāpēc? Tāpēc, ka vēlos izteikt savu viedokli, ka būtu bijis labāk, ja pakalpojumu mezgli būtu parādījušies pirms 10 gadiem, pirms konteineru platformu, piemēram, Docker un Kubernetes, parādīšanās. Neapgalvoju, ka mana viedokļa vērtība ir labāka vai sliktāka par citām, bet, ņemot vērā, ka pakalpojumu mezgli ir diezgan sarežģīti jēdzieni, dažādām perspektīvām palīdzēs tos labāk saprast.

Pastāstīšu par dotCloud platformu, kas tika izveidota uz vairāk nekā simts mikroservisiem un atbalstīja tūkstošiem lietojumprogrammu konteineros. Izskaidrošu problēmas, ar kurām saskārāmies tās izstrādes un palaišanas laikā, un kā pakalpojumu mezgli varētu palīdzēt (vai nepalīdzēt).

dotCloud vēsture

Es jau esmu rakstījis par dotCloud vēsturi un arhitektūras izvēli šai platformai, bet maz stāstīju par tīkla līmeni. Ja nevēlaties iegrimt lasīšanā iepriekšējās raksta par dotCloud, īsumā tas ir: PaaS platforma, kas ļauj klientiem darbināt plašu lietojumprogrammu klāstu (Java, PHP, Python…), ar atbalstu plašam datu pakalpojumu klāstam (MongoDB, MySQL, Redis…) un darba plūsmu līdzīgi kā Heroku: jūs augšupielādējat savu kodu uz platformu, tā veido konteineru attēlus un izvieto tos.

Stāstīšu, kā tika novirzīta trafika uz dotCloud platformu. Nevis tāpēc, ka tā bija īpaši izcila (lai gan tā laika sistēma darbojās labi!), bet galvenokārt tāpēc, ka mūsdienu rīki ļauj nelielai komandai īsā laikā viegli īstenot šādu dizainu, ja viņiem ir nepieciešams veids, kā maršrutēt trafiku starp daudziem mikroservisiem vai lietojumprogrammām. Tādējādi var salīdzināt variantus: kas notiek, ja viss tiek izstrādāts pašiem vai tiek izmantots esošais pakalpojumu mezgls. Standarta izvēle: izstrādāt pašiem vai iegādāties.

Trafika maršrutēšana hostētām lietojumprogrammām

Lietojumprogrammas dotCloud var nodrošināt HTTP un TCP galapunktus.

HTTP galapunkti dinamiskā veidā pievienoti slodzes balansētāja klustera konfigurācijai Hipache. Tas ir līdzīgi tam, ko šodien dara resursi Egress Kubernetes un slodzes balansētājs kā Traefik.

Klienti pieslēdzas HTTP galapunktiem caur attiecīgajiem domēniem, ja domēna nosaukums norāda uz dotCloud slodzes balansētājiem. Nekas īpašs.

TCP galapunkti saistīti ar porta numuru, kas pēc tam tiek pārsūtīts visiem šī steka konteineriem caur vides mainīgajiem.

Klienti var savienoties ar TCP galapunktiem, izmantojot atbilstošo viesdatora vārdu (kas ir kaut kas līdzīgs gateway-X.dotcloud.com) un porta numuru.

Šis viesdatora nosaukums tiek izšķirts klastera serveriem "nats" (nav attiecināms uz NATS), kuri maršrutēs ienākošos TCP savienojumus pareizajam konteineram (vai, ja ir slodzes balancēšanas pakalpojumi, pareizajiem konteineriem).

Ja esat iepazinies ar Kubernetes, iespējams, tas jums atgādinās par pakalpojumiem. NodePort.

DotCloud platformā nebija ekvivalentu pakalpojumiem ClusterIP: vienkāršības labad piekļuve pakalpojumiem notika vienādi gan no iekšpuses, gan ārpuses platformas.

Viss bija organizēts diezgan vienkārši: sākotnējās HTTP un TCP maršrutēšanas tīklu īstenojumi, iespējams, sastāvēja no pāris simtiem Python rindiņu. Vienkārši (es teiktu, naivi) algoritmi, kas tika uzlaboti, pieaugot platformai un parādoties papildu prasībām.

Ievērojama esošā koda pārstrukturēšana nebija nepieciešama. Īpaši 12 faktoru lietotnes var tieši izmantot adresi, kas iegūta caur vides mainīgajiem.

Kā tas atšķiras no mūsdienu pakalpojumu mezgliem?

Ierobežota pārredzamība. Mums vispār nebija nekādu metrikas TCP maršrutēšanas tīkliem. Attiecībā uz HTTP maršrutēšanu vēlākajās versijās parādījās detalizētas HTTP metrikas ar kļūdu kodiem un atbildes laiku, bet mūsdienu pakalpojumu mezgli iet vēl tālāk, nodrošinot integrāciju ar metrikas vākšanas sistēmām, piemēram, Prometheus.

Pārredzamība ir svarīga ne tikai operatīvā līmenī (lai palīdzētu problēmu novēršanā), bet arī izstrādājot jaunus funkcionalitātes. Runājot par drošu zilzaļo izpildi un kanāriešu izpildi.

Maršrutēšanas efektivitāte arī ir ierobežota. DotCloud maršrutizācijas tīklā viss trafiks bija jāpārsūta caur atsevišķo maršrutizācijas mezglu klasteri. Tas nozīmēja potenciālu robežu jeb AZ (pieejamības zonu) pārkāpšanu un ievērojamu aizturi. Atceros, kā risināju problēmas ar kodu, kas veica vairāk nekā simts SQL vaicājumus uz lapu un katram vaicājumam atvēra jaunu savienojumu ar SQL serveri. Vietējā palaišanā lapa ielādējas acumirklī, bet dotCloud ielāde aizņem dažas sekundes, jo katram TCP savienojumam (un attiecīgajam SQL vaicājumam) nepieciešamas desmitiem milisekunžu. Šajā konkrētajā gadījumā problēmu atrisināja pastāvīgie savienojumi.

Mūsdienu servisu mašas labāk risina šādas problēmas. Pirmkārt, tās pārbauda, vai savienojumi tiek maršrutizēti avotā. Loģiskais plūsmas struktūra ir tāda pati: klients → maša → pakalpojums, taču tagad maša strādā lokāli, nevis attālos mezglos, tādēļ savienojums klients → maša ir lokāls un ļoti ātrs (mikrosekonžu vietā milisekundes).

Mūsdienu servisu mašas arī īsteno gudrākus slodzes līdzsvarošanas algoritmus. Uzraugot fona pakalpojumu darbību, tās var nosūtīt vairāk trafika uz ātrākiem fona pakalpojumiem, kas palielina kopējo veiktspēju.

Drošība arī ir labāki. DotCloud maršrutizācijas tīkls darbojās pilnībā uz EC2 Classic un nešifrēja trafiku (pamatot kādu pieņēmumu, ka, ja kādam izdevās uzstādīt sniffers uz EC2 tīkla trafika, jums jau ir lieli problemi). Mūsdienu servisu mašas caurskatāmi aizsargā visu mūsu trafiku, piemēram, ar abpusēju TLS autentifikāciju un sekojošo šifrēšanu.

Trafika maršrutizācija platformas pakalpojumiem

Labi, mēs apspriedām trafiku starp lietojumprogrammām, bet kā ir ar pašu dotCloud platformu?

Paša platforma sastāvēja aptuveni no simta mikropakalpojumiem, kas atbildēja par dažādām funkcijām. Daži pieņēma pieprasījumus no citiem, bet daži bija fona darbinieki, kas pieslēdzās citiem pakalpojumiem, bet paši nepieņēma savienojumus. Katrā gadījumā katram pakalpojumam jāzina galapunktu adreses, uz kurām jāpieslēcas.

Daudzas augstas klases pakalpojumi var izmantot iepriekš aprakstīto maršrutēšanas tīklu. Patiesībā daudzas no vairāk nekā simts dotCloud mikropakalpojumiem tika izvietotas kā parastas lietojumprogrammas pašā dotCloud platformā. Taču neliels skaits zema līmeņa pakalpojumu (īpaši tie, kas īsteno šo maršrutēšanas tīklu) nepieciešams kaut kas vienkāršāks, ar mazākām atkarībām (jo tie nevarēja paļauties uz pašu sevi - vecā labā vistas un ola problēma).

Šie zema līmeņa, svarīgie pakalpojumi tika izvietoti, palaižot konteinerus tieši uz vairākiem galvenajiem mezgliem. Tajā pašā laikā netika izmantoti standarta platformas pakalpojumi: kompozitārs, plānotājs un palaidējs. Ja vēlaties salīdzināt ar mūsdienu konteineru platformām, tas atgādina vadības plaknes palaišanu $ docker-compose up tieši mezglos, nevis deleģējot uzdevumu Kubernetesam. Tas diezgan līdzīgs koncepcijai stāstiskajiem moduļiem (podiem), ko izmanto kubeadm vai bootkube autonomā klastera palaišanai.

Šie pakalpojumi tika izplatīti vienkāršā un rupjā veidā: YAML failā tika uzskaitīti to nosaukumi un adreses; un katram klientam bija jāpārvieto šī YAML faila kopija, lai veiktu izvietošanu.

Vienā pusē tas ir ārkārtīgi uzticams, jo neprasa atbalstu ārējam atslēgu/vērtību krātuves risinājumam, piemēram, Zookeeper (neaizmirstiet, ka tajā laikā vēl neeksistēja etcd vai Consul). No otras puses, tas apgrūtināja pakalpojumu pārvietošanu. Katru reizi, kad pakalpojums tika pārvietots, visiem klientiem bija jāsaņem atjaunināts YAML fails (un potenciāli jārestartē). Ne pārāk ērti!

Vēlāk mēs sākām ieviest jaunu shēmu, kur katrs klients savienojās ar lokālo starpserveri. Vietā, kur jāzina adrese un ports, pietiek ar to, lai zinātu tikai pakalpojuma portu, un savienoties caur localhost. Lokālais starpservers apstrādā šo savienojumu un nosūta to uz faktisko serveri. Tagad, pārvietojot backend uz citu mašīnu vai mēģinot to palielināt, jāatjaunina tikai visi šie lokālie starpserveri; un restartēšana vairs nav nepieciešama.

(Tika bija paredzēts iepakot trafiku TLS savienojumos un pievienot vēl vienu starpniekserveri pieņemšanas pusē, kā arī pārbaudīt TLS sertifikātus bez pieņemšanas pakalpojuma līdzdalības, kas ir konfigurēts tikai savienojumu pieņemšanai uz localhost. Par to vēlāk).

Tas ir ļoti līdzīgi SmartStack no Airbnb, bet būtiska atšķirība ir tā, ka SmartStack ir ieviests un izvietots ražošanā, kamēr iekšējā maršrutēšanas sistēma dotCloud tika izņemta kastē, kad dotCloud pārvērtās par Docker.

Es personīgi uzskatu, ka SmartStack ir viens no priekšgājējiem tādām sistēmām kā Istio, Linkerd un Consul Connect, jo visas tās seko vienam šablonam:

  • Palaist starpniekserveri katrā mezglā.
  • Klienti pieslēdzas starpniekserverim.
  • Vadības plāns atjaunina starpniekservera konfigurāciju, mainoties backend-iem.
  • … Peļņa!

Mūsdienu servisa režģa realizācija

Ja mums ir jāīsteno līdzīgs režģis šodien, mēs varam izmantot līdzīgus principus. Piemēram, konfigurēt iekšējo DNS zonu, sasaistot pakalpojumu nosaukumus ar adresēm telpā 127.0.0.0/8. Tad palaist HAProxy katrā klastera mezglā, pieņemot savienojumus no katras pakalpojuma adreses (šajā apakštīklā 127.0.0.0/8) un novirzot/izplatot slodzi uz attiecīgajiem backend-iem. HAProxy konfigurāciju var pārvaldīt confd, ļaujot saglabāt informāciju par backend-iem etcd vai Consul un automātiski sūtīt atjaunoto konfigurāciju uz HAProxy, kad tas nepieciešams.

Aptuveni tā darbojas Istio! Bet ar dažām atšķirībām:

  • Izmanto Envoy Proxy nevis HAProxy.
  • Saglabā backend-a konfigurāciju caur Kubernetes API, nevis etcd vai Consul.
  • Pakalpojumiem tiek piešķirtas adreses iekšējā apakštīklā (Kubernetes ClusterIP adreses) nevis 127.0.0.0/8.
  • Iegūst papildu komponentu (Citadel), lai pievienotu abpusēju TLS autentifikāciju starp klientu un serveriem.
  • Atbalsta jaunas funkcijas, piemēram, ķēdes pārtraukšanu (circuit breaking), izkliedēto izsekošanu, kanāriju izvietošanu u.c.

Apskatīsim īsumā dažas atšķirības.

Envoy Proxy

Envoy Proxy izstrādāja uzņēmums Lyft [konkurents Uber taksometru tirgū - piezīme tulkotājam]. Tas daudzējādā ziņā ir līdzīgs citiem starpniekserveriem (piemēram, HAProxy, Nginx, Traefik...), bet Lyft izstrādāja savu, jo viņiem bija nepieciešamas funkcijas, kas nebija pieejamas citiem starpniekserveriem, un likās saprātīgāk izstrādāt jaunu, nevis paplašināt esošo.

Envoy var izmantot arī patstāvīgi. Ja man ir konkrēta serviss, kas jākonfigurē līdz citiem servisiem, es varu to iestatīt uz savienojumiem ar Envoy, un pēc tam dinamiski konfigurēt un pārkonfigurēt Envoy ar citu servisu atrašanās vietu, iegūstot daudz lieliskas papildu funkcionalitātes, piemēram, pārskatāmību. Vietā, lai izmantotu pielāgotu klienta bibliotēku vai iebūvēt izsaukumu izsekošanu kodā, mēs novirzām satiksmi uz Envoy, un tas apkopo metrikas mums.

Tomēr Envoy arī spēj darboties kā datu plūsma (data plane) servisu režģim. Tas nozīmē, ka tagad šim servisu režģim Envoy tiek konfigurēts vadības plānā (control plane).

Vadības plāns

Vadības plānā Istio balstās uz Kubernetes API. Tas nav ļoti atšķirīgs no confd izmantošanas, kas paļaujas uz etcd vai Consul, lai apskatītu atslēgu kopumu datu krātuvē. Istio izmanto Kubernetes API, lai apskatītu Kubernetes resursu kopumu.

Pa ceļam: personīgi man šķita noderīga šī Kubernetes API apraksts, kas saka:

Kubernetes API serveris ir "stulbs servers", kas piedāvā uzglabāšanu, versiju pārvaldību, verifikāciju, atjaunināšanu un API resursu semantiku.

Istio ir izstrādāts, lai strādātu ar Kubernetes; un ja vēlaties to izmantot ārpus Kubernetes, jums ir jāpalaiž Kubernetes API servera instances (un palīgpakalpojuma etcd).

Servisu adreses

Istio paļaujas uz ClusterIP adresēm, kuras piešķir Kubernetes, tādēļ Istio servisi iegūst iekšēju adresi (ne diapazonā 127.0.0.0/8).

Satiksme uz ClusterIP adresi konkrētai servici Kubernetes klasterī bez Istio tiek pārņemta ar kube-proxy un nosūtīta uz šī proksi servera daļu. Ja jūs interesē tehniskie sīkumi, kube-proxy iestata iptables noteikumus (vai IPVS slodzes balansētājus, atkarībā no tā, kā to ir konfigurējuši), lai pārrakstītu savienojumu galamērķa IP adreses, kas dodas caur ClusterIP adresi.

Pēc tam, kad Istio ir uzstādīts Kubernetes klasterī, nekas nemainās, kamēr tas nav skaidri aktivizēts konkrētam patērētājam vai pat visam nosaukumam, ieviešot konteineru sidecar pielāgotajos podos. Šis konteiners palaidīs Envoy instanci un iestatīs virkni iptables noteikumu, lai pārņemtu satiksmi, kas dodas uz citiem servisiem, un novirzītu šo satiksmi uz Envoy.

Integrējoties ar Kubernetes DNS, tas nozīmē, ka mūsu kods var savienoties pēc pakalpojuma nosaukuma, un viss "vienkārši darbojas". Citiem vārdiem sakot, mūsu kods ieraksta pieprasījumus, kas līdzīgi http://api/v1/users/4242, tad api rezolvē pieprasījumu uz 10.97.105.48, iptables noteikumi nozvejo savienojumus ar 10.97.105.48 un novirza tos uz vietējo proksi Envoy, un šis vietējais proksi nosūtīs pieprasījumu uz faktisko API aizmuguri. Uf!

Papildu krāšņas detaļas

Istio arī nodrošina galveno šifrēšanu un autentifikāciju, izmantojot mTLS (savstarpējā TLS). Par to atbild komponents, kurš tiek saukts par Citadel.

Ir arī komponents Mixer, kuru Envoy var pieprasīt, lai katram pieprasītu, lai pieņemtu īpašu lēmumu par šo pieprasījumu atkarībā no dažādiem faktoriem, piemēram, galvenēm, aizmugures noslodzi utt... (nerakstiet par to: ir daudz rīku, lai nodrošinātu Mixer darbību, un pat ja tas neizdodas, Envoy turpinās normāli darboties kā proksi).

Un, protams, mēs pieminējām iespējamību: Envoy apkopo milzīgu metrikas apjomu, nodrošinot sadalītu izsekošanu. Mikroservisu arhitektūrā, ja viens API pieprasījums jādod cauri mikroservisiem A, B, C un D, tad, iebraucot sistēmā, sadalītā izsekošana pievieno pieprasījumam unikālu identifikatoru un saglabā šo identifikatoru zemapgādē visiem šiem mikroservisiem, ļaujot fiksēt visus saistītos izsaukumus, to aizkavi utt.

Izstrādāt vai iegādāties

Istio ir reputācija kā sarežģīta sistēma. Gluži pretēji, maršrutēšanas tīkla izveide, ko es aprakstīju šī raksta sākumā, ir salīdzinoši vienkārša, izmantojot esošos rīkus. Tātad, vai ir jēga izveidot savu servisa tīklu?

Ja mums ir pieticīgas vajadzības (nav nepieciešama iespējām, daudz pārtraukumu un citas nianses), tad rodas domas par sava rīka izstrādi. Bet, ja mēs izmantojam Kubernetes, tas var pat nebūt nepieciešams, jo Kubernetes jau nodrošina pamata rīkus pakalpojumu atklāšanai un slodzes sadalīšanai.

Bet, ja mums ir progresīvas prasības, tad "iegādāties" servisa tīklu izskatās daudz labāks variants. (Tas nav vienmēr tieši "iegādāties", jo Istio tiek piegādāts ar atvērtā koda, bet mums joprojām ir jāiegulda inženierijas laiks, lai saprastu tā darbību, izvietotu to un pārvaldītu).

Ko izvēlēties: Istio, Linkerd vai Consul Connect?

Līdz šim mēs runājām tikai par Istio, bet tas nav vienīgais servisu maiss. Populāra alternatīva ir Linkerd, un ir arī vēl Consul Connect.

Ko izvēlēties?

Godīgi sakot, nezinu. Šobrīd neuzskatu sevi par pietiekami kompetentu, lai atbildētu uz šo jautājumu. Ir vairāki interesanti rakstus salīdzinājumi starp šiem rīkiem un pat veiktspējas testi.

Viens no daudzsološajiem pieejām ir izmantot rīku, piemēram, SuperGloo. Tas īsteno abstrakcijas slāni, lai vienkāršotu un harmonizētu API, ko nodrošina servisu maisi. Vietā, lai mācītos par konkrētām (un, manuprāt, salīdzinoši sarežģītām) dažādu servisu maisu API, mēs varam izmantot vienkāršākas SuperGloo konstrukcijas – un viegli pārslēgties no viena uz otru, it kā mums būtu starpstāvokļa konfigurācijas formāts, kas apraksta HTTP saskarnes un backendus, spējīgi ģenerēt faktisko konfigurāciju Nginx, HAProxy, Traefik, Apache...

Es nedaudz spēlējos ar Istio un SuperGloo, un nākamajā rakstā gribu parādīt, kā pievienot Istio vai Linkerd esošajam klasterim, izmantojot SuperGloo, un cik labi tas spēs paveikt savu darbu, proti, ļaut pārslēgties no viena servisu maisa uz otru bez konfigurāciju pārrakstīšanas.

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster