Tindera pārcelšanās uz Kubernetes

Raksta: Kriss O'Braiens, inženierzinātņu vadītājs | Kriss Tomass, inženierzinātņu vadītājs | Jinyong Lee, vecākais programmatūras inženieris | Rediģēja: Kūpers Džeksons, programmatūras inženieris

Kāpēc

Gandrīz pirms diviem gadiem Tinder nolēma pārcelt savu platformu uz Kubernetes. Kubernetes deva mums iespēju virzīt Tinder Engineering uz konteineru veidošanu un darbību ar zemu pieskārienu, izmantojot nemainīgu izvietošanu. Lietojumprogrammu veidošana, izvietošana un infrastruktūra tiek definēta kā kods.

Mēs arī meklējām risināt mēroga un stabilitātes problēmas. Kad mērogošana kļuva kritiska, mēs dažu minūšu laikā bieži gaidījām jaunu EC2 gadījumu parādīšanos tiešsaistē. Ideja par konteineru plānošanu un satiksmi dažu sekunžu laikā, nevis minūtēm, mūs iepriecināja.

Tas nebija viegli. Migrācijas laikā 2019. gada sākumā Kubernetes klasterī mēs sasniedzām kritisko masu un sākām sastapties ar dažādām problēmām, kas saistītas ar trafika apjomu, klastera lielumu un DNS. Mēs atrisinājām interesantus izaicinājumus 200 pakalpojumu migrēšanai un Kubernetes klastera vadīšanai mērogā, kurā kopumā ir 1000 mezgli, 15 000 podi un 48 000 darbojas konteineri.

Sākot ar 2018. gada janvāri, mēs strādājām dažādos migrācijas centienu posmos. Mēs sākām ar visu mūsu pakalpojumu konteineru izvietošanu un izvietošanu virknē Kubernetes mitinātu inscenēšanas vidi. Sākot ar oktobri, mēs sākām metodiski pārvietot visus savus mantotos pakalpojumus uz Kubernetes. Līdz nākamā gada martam mēs pabeidzām mūsu migrāciju, un Tinder platforma tagad darbojas tikai Kubernetes.

Kubernetes celtniecības attēli

Mikropakalpojumiem, kas darbojas Kubernetes klasterī, ir vairāk nekā 30 avota kodu krātuvju. Kods šajās krātuvēs ir uzrakstīts dažādās valodās (piemēram, Node.js, Java, Scala, Go) ar vairākām runtime vidēm vienai un tai pašai valodai.

Izveidošanas sistēma ir izstrādāta darbībai ar pilnībā pielāgojamu katra mikropakalpojuma “veidošanas kontekstu”, kas parasti sastāv no Dockerfile un četru komandu sērijas. Lai gan to saturs ir pilnībā pielāgojams, visi šie konteineri tiek rakstīti, ievērojot standartizētu formātu. Izveidošanas kontekstu standartizācija ļauj ar vienu sastādīšanas sistēmu rīkoties ar visiem mikropakalpojumiem.

1–1. Attēls. Standartizēts būvniecības process caur Builder konteineru

Lai sasniegtu maksimālu konsekvenci starp izpildlaika vidēm, izstrādes un testēšanas posmā tiek izmantots viens un tas pats veidošanas process. Tas radīja unikālu izaicinājumu, kad mums bija jāizdomā veids, kā visā platformā garantēt konsekventu būves vidi. Rezultātā visi veidošanas procesi tiek izpildīti īpašā konteinerā “Builder”.

Builder konteinera ieviešanai bija vajadzīgas vairākas uzlabotas Docker tehnikas. Šis veidotājs konteiners manto vietējo lietotāja ID un noslēpumus (piemēram, SSH atslēga, AWS akreditācijas dati utt.), Kas nepieciešami, lai piekļūtu Tinder privātajām krātuvēm. Tajā tiek uzstādīti vietējie direktoriji, kas satur avota kodu, lai dabiski varētu uzbūvēt artefaktus. Šī pieeja uzlabo veiktspēju, jo novērš iebūvētu artefaktu kopēšanu starp Builder konteineru un resursdatoru. Saglabātie celtniecības artefakti tiek atkārtoti izmantoti nākamreiz bez turpmākas konfigurācijas.

Dažiem pakalpojumiem mums veidotājā Builder bija jāizveido vēl viens konteiners, lai kompilācijas laika vide atbilstu izpildes laika videi (piemēram, instalējot bcrypt bibliotēku Node.js, tiek ģenerēti platformai specifiski bināri artefakti). Sastādīšanas laika prasības dažādiem pakalpojumiem var atšķirties, un galīgais Dockerfile tiek sastādīts lidojuma laikā.

Kubernetes klastera arhitektūra un migrācija

Klasteru lieluma noteikšana

Mēs nolēmām izmantot kube-aws automatizētai klasteru nodrošināšanai Amazon EC2 gadījumos. Sākumā mēs visu vadījām vienā vispārējā mezglu fondā. Mēs ātri identificējām nepieciešamību sadalīt darba slodzes dažāda lieluma un tipu gadījumos, lai labāk izmantotu resursus. Iemesls bija tāds, ka, palaižot mazāk smagi vītņotus pāksti, mums tika doti paredzamāki veiktspējas rezultāti, nekā ļaujot tiem līdzāspastāvēt ar lielāku skaitu vītņoto pākšu.

Mēs apņēmāmies:

  • m5.4xx palielinājums monitoringam (Prometheus)
  • c5.4xlarge par Node.js darba slodzi (vienas vītnes slodze)
  • c5.2xlarge for Java and Go (vairāku vītņu slodze)
  • c5.4xplāksne vadības plaknei (3 mezgli)

Migrācija

Viens no sagatavošanās posmiem pārejai no mūsu mantotās infrastruktūras uz Kubernetes bija mainīt esošo pakalpojumu savstarpējo komunikāciju, lai norādītu uz jauniem elastīgās slodzes līdzsvarotājiem (ELB), kas tika izveidoti noteiktā virtuālā privātā mākoņa (VPC) apakštīklā. Šis apakštīkls tika piesaistīts Kubernetes VPC. Tas ļāva mums detalizēti migrēt moduļus, neņemot vērā konkrētu pasūtījumu pakalpojumu atkarībām.

Šie parametri tika izveidoti, izmantojot svērtās DNS ierakstu kopas, kurām CNAME norādīja uz katru jauno ELB. Lai pārslēgtu, mēs pievienojām jaunu ierakstu, norādot uz jauno Kubernetes pakalpojumu ELB, kura svars ir 0. Pēc tam mēs ierakstam Time To Live (TTL) ierakstu, kas iestatīts uz 0. Pēc tam veco un jauno svaru lēnām pielāgojām galu galā jaunajā serverī nonāk 100%. Pēc pārejas pabeigšanas TTL tika iestatīts uz kaut ko saprātīgāku.

Mūsu Java moduļi cienīja zemo DNS TTL, bet mūsu Mezglu programmas to nedarīja. Viens no mūsu inženieriem pārrakstīja daļu savienojuma baseina koda, lai iesaiņotu to pārvaldniekā, kurš atjauninātu baseinus ik pēc 60. gadiem. Tas mums darbojās ļoti labi, bez ievērojama snieguma.

Mācības

Tīkla auduma ierobežojumi

2019. gada 8. janvāra agrā rīta stundā Tinder's Platform cieta pastāvīgu pārtraukumu. Reaģējot uz nesaistītu platformas latentuma palielināšanos agrāk tajā pašā rītā, klasterī tika samazināts balsu un mezglu skaits. Tā rezultātā visiem mūsu mezgliem tika izsmelta ARP kešatmiņa.

ARP kešatmiņai ir trīs Linux vērtības:

Kredīts

gc_thresh3 ir ciets vāciņš. Ja saņemat “kaimiņu tabulas pārpildes” žurnāla ierakstus, tas norāda, ka pat pēc ARP kešatmiņas sinhronās atkritumu savākšanas (GC) nebija pietiekami daudz vietas kaimiņa ieraksta glabāšanai. Šajā gadījumā kodols vienkārši pilnībā nomet paketi.

Mēs izmantojam Flannel kā savu tīkla audumu Kubernetes. Paketes tiek pārsūtītas, izmantojot VXLAN. VXLAN ir 2. slāņa pārklājuma shēma 3. slāņa tīklā. Tas izmanto MAC adreses-lietotāja datu diagrammas (MAC-in-UDP) iekapsulēšanu, lai nodrošinātu līdzekļus 2. slāņa tīkla segmentu paplašināšanai. Transportēšanas protokols fiziskā datu centra tīklā ir IP plus UDP.

2–1. Attēls. Flaneļa diagramma (kredīts)

Attēls 2–2 VXLAN pakete (kredīts)

Katrs Kubernetes darbinieka mezgls piešķir sev / 24 virtuālās adrešu telpas no lielākas / 9 bloka. Katrā mezglā tas rada 1 maršruta tabulas ierakstu, 1 ARP tabulas ierakstu (uz flannel.1 saskarnes) un 1 ekspedīcijas datu bāzes (FDB) ierakstu. Tie tiek pievienoti, kad darbinieka mezgls tiek palaists pirmo reizi vai kad tiek atklāts katrs jauns mezgls.

Turklāt komunikācija no mezgla-pa-pod (vai no pod-to-pod) galu galā plūst pāri eth0 saskarnei (parādīta flaneļa diagrammā iepriekš). Tas radīs papildu ierakstu ARP tabulā katram atbilstošajam mezgla avotam un mezgla mērķim.

Mūsu vidē šāda veida komunikācija ir ļoti izplatīta. Mūsu Kubernetes pakalpojumu objektiem tiek izveidots ELB, un Kubernetes reģistrē katru mezglu ELB. ELB nav informēts par podziņu, un izvēlētais mezgls var nebūt paketes gala mērķis. Tas ir tāpēc, ka tad, kad mezgls saņem paketi no ELB, tas novērtē tā iptables noteikumus pakalpojumam un nejauši izvēlas podi citā mezglā.

Izslēgšanas brīdī klasterī bija 605 mezgli. Iepriekš aprakstīto iemeslu dēļ tas bija pietiekami, lai aizēnotu noklusējuma vērtību gc_thresh3. Kad tas notiek, ARP tabulā trūkst ne tikai pakešu, bet arī visas virtuālās adrešu vietas Flannel / 24. Neizdodas izveidot savienojumu ar mezglu un DNS meklēšanu. (DNS tiek mitināts klasterī, kā sīkāk tiks paskaidrots vēlāk šajā rakstā.)

Lai atrisinātu, tiek paaugstinātas vērtības gc_thresh1, gc_thresh2 un gc_thresh3, un flalanelis ir jārestartē, lai atkārtoti reģistrētu trūkstošos tīklus.

Negaidīti darbojas DNS mērogā

Lai pielāgotos mūsu migrācijai, mēs lielā mērā izmantojām DNS, lai mūsu pakalpojumiem atvieglotu datplūsmas veidošanu un pakāpenisku pāreju no mantojuma uz Kubernetes. Mēs iestatījām samērā zemas TTL vērtības saistītajā Route53 RecordSets. Kad mēs izmantojām savu mantoto infrastruktūru EC2 instancēs, mūsu izšķirtspējas konfigurācija norādīja uz Amazon DNS. Mēs to uzskatījām par pašsaprotamu, un salīdzinoši zemās TTL izmaksas par mūsu pakalpojumiem un Amazon pakalpojumiem (piemēram, DynamoDB) gandrīz nepalika pamanītas.

Iegādājoties arvien vairāk pakalpojumu Kubernetes, mēs atradāmies darbam DNS pakalpojumā, kas atbildēja uz 250 000 pieprasījumiem sekundē. Mēs savās lietojumprogrammās saskārāmies ar pārtraukumiem un ietekmīgiem DNS meklēšanas taimautiem. Tas notika, neraugoties uz izsmeļošajiem noregulēšanas centieniem un DNS nodrošinātāja pārslēgšanos uz CoreDNS izvietošanu, kas vienā reizē sasniedza maksimumu 1000 podi, kas patērēja 120 serdeņus.

Pētot citus iespējamos cēloņus un risinājumus, mēs atradām rakstu, kurā aprakstīti sacensību apstākļi, kas ietekmē Linux pakešu filtrēšanas ietvara netfilter. DNS taimauti, kurus mēs redzējām, kā arī pieaugošais insert_failed skaitītājs flaneļa saskarnē, kas saskaņoti ar raksta atradumiem.

Problēma rodas avota un mērķa tīkla adrešu tulkošanas (SNAT un DNAT) laikā un pēc tam ievietojot to konsoles tabulā. Viens no iekšēji apspriestiem un sabiedrības ierosinātajiem risinājumiem bija pārvietot DNS uz pašu darba mezglu. Šajā gadījumā:

  • SNAT nav nepieciešams, jo satiksme lokāli atrodas mezglā. Tas nav jāpārraida visā eth0 saskarnē.
  • DNAT nav nepieciešams, jo mērķa IP ir lokāls mezglā, nevis nejauši izvēlēts pods iptable kārtulām.

Mēs nolēmām virzīties tālāk ar šo pieeju. CoreDNS Kubernetes tika izvietots kā DaemonSet, un mēs katra pults rezolv.conf ievadījām mezgla vietējo DNS serveri, konfigurējot kubelet - cluster-dns komandu karogu. Risinājums bija efektīvs DNS noildzes gadījumā.

Tomēr joprojām mēs redzam nomestās paketes un flaneļa saskarnes insert_failed skaitītāja pieaugumu. Tas saglabāsies arī pēc iepriekšminētā risinājuma, jo DNS trafikā mēs izvairījāmies tikai no SNAT un / vai DNAT. Sacensību apstākļi joprojām būs spēkā cita veida satiksmei. Par laimi, lielākā daļa mūsu pakešu ir TCP, un, kad rodas šāds apstāklis, paketes tiks veiksmīgi pārsūtītas. Visu veidu trafika ilgtermiņa labojums ir kaut kas, par ko mēs joprojām diskutējam.

Izmantojot sūtni, lai panāktu labāku slodzes līdzsvarošanu

Migrējot savus aizmugures pakalpojumus uz Kubernetes, mēs sākām ciest no nesabalansētas slodzes starp podi. Mēs atklājām, ka HTTP Keepalive dēļ ELB savienojumi pielīp pie katras ritošās izvietošanas pirmajiem gataviem podiem, tāpēc lielākā daļa trafika plūda caur nelielu daļu no pieejamajiem podziņiem. Viens no pirmajiem mazināšanas mēģinājumiem bija izmantot 100% MaxSurge jauniem izvietojumiem vissliktākajiem likumpārkāpējiem. Tas bija nedaudz efektīvs un nebija ilgtspējīgs ilgtermiņā ar dažiem lielākiem izvietojumiem.

Cita veida mazināšana, kuru mēs izmantojām, bija mākslīgi palielināt pieprasījumu pēc resursiem kritiskajos pakalpojumos, lai izvietotiem pākstiem būtu vairāk vietas līdzās citiem smagajiem pākstiem. Resursu izšķērdēšanas dēļ to ilgtermiņā arī nevarēs izmantot, un mūsu mezglu lietojumprogrammas bija vītņotas ar vienu vītni un tādējādi efektīvi tika ierobežotas vienā kodolā. Vienīgais skaidrais risinājums bija labākas slodzes līdzsvarošana.

Mēs iekšēji bijām lūguši novērtēt sūtni. Tas deva mums iespēju to izmantot ļoti ierobežotā veidā un gūt tūlītējus ieguvumus. Envoy ir atvērtā pirmkoda, augstas veiktspējas Layer 7 starpniekserveris, kas paredzēts lielām uz pakalpojumiem orientētām arhitektūrām. Tas spēj ieviest uzlabotas slodzes līdzsvarošanas tehnikas, ieskaitot automātiskus atkārtotus mēģinājumus, ķēdes pārtraukšanu un globālo likmju ierobežošanu.

Konfigurācija, ar kuru mēs nāca klajā, bija tāda, ka blakus katram pjedestālam bija Envoy blakusvāģis, kuram bija viens maršruts un kopas, lai sasniegtu vietējo konteineru ostu. Lai samazinātu iespējamo kaskādes pakāpi un saglabātu nelielu sprādziena rādiusu, mēs izmantojām priekšējā starpniekservera Envoy pults, vienu izvietojumu katrā pieejamības zonā (AZ) katram pakalpojumam. Tie skāra nelielu pakalpojumu atklāšanas mehānismu, kuru izveidoja viens no mūsu inženieriem, kurš vienkārši atdeva podi sarakstu katrā AZ par doto pakalpojumu.

Pēc tam dienesta priekšējie sūtņi izmantoja šo pakalpojumu atklāšanas mehānismu ar vienu augšupēju kopu un maršrutu. Mēs konfigurējām saprātīgus noildzes periodus, veicinājām visus ķēdes pārtraucēja iestatījumus un pēc tam ievietojām minimālu atkārtotas konfigurācijas konfigurāciju, lai palīdzētu īslaicīgu kļūmju gadījumā un vienmērīgu izvietošanu. Mēs katru no šiem priekšējā sūtņa pakalpojumiem slēdzām ar TCP ELB. Pat ja mūsu galvenā priekšējā starpniekservera slāņa aizturēšana tika iesprausta noteiktos sūtņa pults, tie daudz labāk izturēja slodzi un tika konfigurēti, lai līdzsvarotu caur backend vismazāko pieprasījumu.

Izvietošanai mēs izmantojām preStop āķi gan lietojumprogrammā, gan blakusvāģa pākstam. Šis āķis, ko sauca par blakusvāģa veselības pārbaudes neveiksmīgu administratora galapunktu, kopā ar nelielu gulēšanu, lai dotu laiku, lai lidojuma savienojumi varētu pilnībā izveidoties un iztukšoties.

Viens no iemesliem, kāpēc mēs varējām tik ātri pārvietoties, bija bagātīgās metrikas dēļ, kuras mēs viegli varējām integrēt ar parasto Prometheus iestatījumu. Tas ļāva precīzi redzēt notiekošo, atkārtojot konfigurācijas iestatījumus un pārtraucot trafiku.

Rezultāti bija tūlītēji un acīmredzami. Mēs sākām ar visnebalansētākajiem pakalpojumiem, un šobrīd tas darbojas divpadsmit svarīgāko pakalpojumu priekšā mūsu klasterī. Šogad mēs plānojam pāriet uz pilna servisa sietu ar progresīvāku pakalpojumu atklāšanu, ķēžu pārtraukšanu, ārēju noteikšanu, ātruma ierobežošanu un izsekošanu.

3–1. Attēls. Viena dienesta CPU konverģence sūtņa pārsūtīšanas laikā

Gala rezultāts

Izmantojot šīs mācības un papildu pētījumus, mēs esam izveidojuši spēcīgu iekšējās infrastruktūras komandu, kurai ir lielas zināšanas par to, kā plānot, izvietot un darbināt lielās Kubernetes kopas. Visai Tinder inženiertehniskajai organizācijai tagad ir zināšanas un pieredze, kā konteineros izmantot un izvietot viņu lietojumprogrammas Kubernetes.

Kad tika pieprasīta papildu mēroga izmantošana mūsu mantotajā infrastruktūrā, mēs bieži cieta vairākas minūtes, gaidot jaunu EC2 gadījumu parādīšanos tiešsaistē. Tagad konteineri plāno un apkalpo satiksmi dažu sekunžu laikā, nevis minūtes. Vairāku konteineru plānošana vienā EC2 instancē nodrošina arī uzlabotu horizontālo blīvumu. Tā rezultātā mēs prognozējam ievērojamu EC2 izmaksu ietaupījumu 2019. gadā, salīdzinot ar iepriekšējo gadu.

Pagāja gandrīz divi gadi, bet mēs pabeigām migrēšanu 2019. gada martā. Tinder platforma darbojas tikai uz Kubernetes klasteru, kas sastāv no 200 pakalpojumiem, 1000 mezgliem, 15 000 podiem un 48 000 darbojas konteineriem. Infrastruktūra vairs nav mūsu operāciju komandu uzdevums. Tā vietā inženieri visā organizācijā dalās šajā atbildībā un kontrolē, kā viņu lietojumprogrammas tiek veidotas un ieviestas, izmantojot visu kā kodu.