Tinder se oorgang na Kubernetes

Let wel. vertaal.: Die personeel van die wêreldbekende diens Tinder het onlangs 'n paar tegniese besonderhede gedeel oor die migreer van hul infrastruktuur na Kubernetes. Die proses het byna twee jaar geduur en het gelei tot die bekendstelling van 'n baie grootskaalse platform op K8s, bestaande uit 200 dienste wat op 48 XNUMX houers aangebied is. Watter interessante probleme het Tinder-ingenieurs in die gesig gestaar en met watter resultate hulle vorendag gekom het - lees in hierdie vertaling.

Tinder se oorgang na Kubernetes

Зачем?

Byna twee jaar gelede het Tinder besluit om sy platform na Kubernetes te migreer. Kubernetes sal die Tinder-span in staat stel om met minimale moeite in 'n houer te sit en regstreeks te gaan deur onveranderlike ontplooiing (onveranderlike ontplooiing). In hierdie geval sal die samestelling van toepassings, hul ontplooiing en die infrastruktuur self uniek deur die kode gedefinieer word.

Ons was ook op soek na 'n oplossing vir die probleem van skaalbaarheid en stabiliteit. Wanneer skaal krities geword het, moes ons dikwels 'n paar minute wag vir nuwe EC2-gevalle om te begin. Die idee om houers te loods en verkeer binne sekondes in plaas van minute te begin bedien, het vir ons baie aantreklik geword.

Die proses blyk moeilik te wees. Tydens ons vroeë 2019-migrasie het die Kubernetes-kluster kritieke massa bereik en ons het verskeie probleme begin raakloop weens verkeersvolume, groepgrootte en DNS. Langs die pad het ons baie interessante probleme opgelos wat verband hou met die migreer van 200 dienste en die instandhouding van 'n Kubernetes-kluster wat bestaan ​​uit 1000 nodusse, 15000 peule en 48000 lopende houers.

Hoe werk dit?

Sedert Januarie 2018 het ons deur verskeie stadiums van migrasie gegaan. Ons het begin deur al ons dienste te hou en dit te ontplooi om Kubernetes-wolkomgewings te toets. Vanaf Oktober het ons alle bestaande dienste metodies na Kubernetes begin migreer. Teen Maart volgende jaar het ons die "verskuiwing" voltooi en nou loop die Tinder-platform uitsluitlik op Kubernetes.

Bou beelde vir Kubernetes

Ons het meer as 30 bronkode-bewaarplekke vir mikrodienste wat op 'n Kubernetes-kluster loop. Die kode in hierdie bewaarplekke is in verskillende tale geskryf (byvoorbeeld Node.js, Java, Scala, Go) met verskeie looptyd-omgewings vir dieselfde taal.

Die boustelsel is ontwerp om 'n volledig aanpasbare "boukonteks" vir elke mikrodiens te verskaf. Dit bestaan ​​gewoonlik uit 'n Dockerfile en 'n lys dopopdragte. Hul inhoud is volledig aanpasbaar, en terselfdertyd word al hierdie samestellingskontekste volgens 'n gestandaardiseerde formaat geskryf. Die standaardisering van boukontekste laat een enkele boustelsel toe om alle mikrodienste te hanteer.

Tinder se oorgang na Kubernetes
Figuur 1-1. Gestandaardiseerde bouproses via Builder Container

Vir maksimum konsekwentheid oor looptyd-omgewings (looptyd omgewings) dieselfde bouproses word tydens ontwikkeling en toetsing gebruik. Ons het voor 'n baie interessante uitdaging te staan ​​gekom: ons moes 'n manier ontwikkel om 'n konsekwente bou-omgewing oor die hele platform te waarborg. Om dit te doen, word alle monteringsprosesse in 'n spesiale houer uitgevoer. Builder.

Sy houerimplementering het gevorderde Docker-truuks vereis. Bouer erf die plaaslike gebruikers-ID en geheime (soos SSH-sleutel, AWS-bewyse, ens.) wat nodig is om toegang tot private Tinder-bewaarplekke te verkry. Dit plaas plaaslike gidse wat bronne bevat om bou-artefakte natuurlik te stoor. Hierdie benadering verbeter werkverrigting omdat dit die behoefte uitskakel om bou-artefakte tussen die Bouer-houer en die gasheer te kopieer. Gestoorde bou-artefakte kan hergebruik word sonder bykomende konfigurasie.

Vir sommige dienste moes ons 'n ander houer skep om die samestellingsomgewing na die looptydomgewing te karteer (byvoorbeeld, tydens installasie genereer die Node.js bcrypt-biblioteek platformspesifieke binêre artefakte). Tydens samestelling kan die vereistes vir verskillende dienste verskil, en die finale Dockerfile word dadelik saamgestel.

Kubernetes cluster argitektuur en migrasie

Trosgrootte beheer

Ons het besluit om te gebruik kube-aws vir outomatiese tros-ontplooiing op Amazon EC2-gevalle. Heel aan die begin het alles in een gemeenskaplike poel nodusse gewerk. Ons het vinnig die behoefte besef om werkladings volgens instansiegrootte en tipe te skei om hulpbronne meer doeltreffend te gebruik. Die logika was dat die gebruik van 'n paar gelaaide multi-draad peule meer voorspelbaar was in prestasie as om saam met 'n groot aantal enkel-threaded peule te bestaan.

Op die ou end het ons geëindig met:

  • m5.4x groot - vir monitering (Prometheus);
  • c5.4xgroot - Vir Node.js-werklading (enkeldraadwerklading)
  • c5.2xgroot - vir Java en Go (multi-threaded workload);
  • c5.4xgroot - vir die beheerpaneel (3 nodusse).

Migrasie

Een van die voorbereidende stappe vir die migreer van die ou infrastruktuur na Kubernetes was om die bestaande direkte interaksie tussen dienste na die nuwe Elastic Load Balancers (ELB's) te herlei. Hulle is geskep op 'n spesifieke virtuele private wolk (VPC) subnet. Hierdie subnet is aan 'n Kubernetes VPC gekoppel. Dit het ons in staat gestel om modules inkrementeel te migreer sonder om die spesifieke volgorde van diensafhanklikhede in ag te neem.

Hierdie eindpunte is geskep deur gebruik te maak van 'n geweegde stel DNS-rekords met CNAME's wat na elke nuwe ELB wys. Om oor te skakel, het ons 'n nuwe inskrywing bygevoeg wat na die nuwe Kubernetes-diens ELB wys met 'n gewig van 0. Toe stel ons die Time To Live (TTL) van die rekordstel op 0. Daarna het die ou en nuwe gewigte stadig aangepas, en uiteindelik is 100% van die vrag na die nuwe bediener gestuur. Nadat die oorskakeling voltooi is, het die TTL-waarde na 'n meer voldoende vlak teruggekeer.

Die Java-modules wat ons gehad het, het die lae TTL DNS hanteer, maar die Node-toepassings was nie. Een van die ingenieurs het 'n deel van die verbindingspoelkode herskryf en dit in 'n bestuurder toegedraai wat die swembaddens elke 60 sekondes opgedateer het. Die gekose benadering het baie goed gewerk en sonder merkbare prestasie-agteruitgang.

Die lesse

Netwerk Fabriekslimiete

In die vroeë oggendure van 8 Januarie 2019 het die Tinder-platform skielik gedaal. In reaksie op 'n onverwante toename in platformvertraging vroeër daardie oggend, het die aantal peule en nodusse in die groepering toegeneem. Dit het veroorsaak dat die ARP-kas op al ons nodusse uitgeput is.

Daar is drie Linux-opsies wat verband hou met die ARP-kas:

Tinder se oorgang na Kubernetes
(bron)

gc_dors3 is 'n harde limiet. Die verskyning van "buurtafel-oorloop"-inskrywings in die log het beteken dat selfs na sinchronous garbage collection (GC), daar nie genoeg spasie in die ARP-kas was om die naburige inskrywing te stoor nie. In hierdie geval het die kern eenvoudig die pakkie heeltemal laat val.

Ons gebruik flanel as 'n netwerkstof in Kubernetes. Pakkies word oor VXLAN gestuur. VXLAN is 'n L2-tonnel wat oor 'n L3-netwerk gelig is. Die tegnologie gebruik MAC-in-UDP (MAC Address-in-User Datagram Protocol)-inkapseling en laat jou toe om laag 2-netwerksegmente uit te brei. Die vervoerprotokol op die fisiese datasentrumnetwerk is IP plus UDP.

Tinder se oorgang na Kubernetes
Figuur 2-1. Flanel grafiek (bron)

Tinder se oorgang na Kubernetes
Figuur 2-2. VXLAN pakket (bron)

Elke Kubernetes-werkernodus ken 'n /24-gemaskerde virtuele adresruimte vanaf 'n groter /9-blok toe. Vir elke nodus, hierdie beteken een inskrywing in die roeteringtabel, een inskrywing in die ARP-tabel (op koppelvlakflanel.1), en een inskrywing in die skakeltabel (FDB). Hulle word bygevoeg die eerste keer dat 'n werkernodus begin word of elke nuwe nodus ontdek word.

Boonop gaan node-peul (of pod-pod) kommunikasie uiteindelik deur die koppelvlak et0 (soos getoon in die flenniegrafiek hierbo). Dit lei tot 'n bykomende inskrywing in die ARP-tabel vir elke ooreenstemmende gasheerbron en bestemming.

In ons omgewing is hierdie tipe kommunikasie baie algemeen. Vir diensvoorwerpe in Kubernetes word 'n ELB geskep en Kubernetes registreer elke nodus by die ELB. ELB weet niks van peule nie en die geselekteerde nodus is dalk nie die eindbestemming van die pakkie nie. Die feit is dat wanneer 'n nodus 'n pakkie van ELB ontvang, dit dit volgens die reëls beskou iptables vir 'n spesifieke diens en kies ewekansig 'n peul op 'n ander nodus.

Ten tyde van die mislukking was daar 605 nodusse in die groepie. Om die redes hierbo genoem, was dit voldoende om die waarde te oorkom gc_dors3, by verstek gestel. Wanneer dit gebeur, word nie net pakkies laat val nie, maar Flannel se hele /24 virtuele adresruimte verdwyn van die ARP-tabel. Die peul-tot-peul-kommunikasie en DNS-navrae is gebreek (DNS word in 'n groepering gehuisves; sien besonderhede later in hierdie artikel).

Om hierdie probleem op te los, moet jy die waardes verhoog gc_dors1, gc_dors2 и gc_dors3 en herbegin Flannel om die vermiste netwerke te herregistreer.

Onverwagte DNS-skaal

Tydens die migrasieproses het ons DNS aktief gebruik om verkeer te bestuur en dienste geleidelik van die ou infrastruktuur na Kubernetes oor te dra. Ons het relatief lae TTL-waardes gestel vir die geassosieerde rekordstelle in Route53. Toe die ou infrastruktuur op EC2-gevalle geloop het, het ons oplosserkonfigurasie na Amazon DNS gewys. Ons het dit as vanselfsprekend aanvaar en die impak van lae TTL op ons dienste en Amazon-dienste (bv. DynamoDB) het byna ongemerk gebly.

Terwyl ons dienste na Kubernetes migreer, het ons gevind dat DNS 250K versoeke per sekonde verwerk. As gevolg hiervan, het toepassings konstante en ernstige time-outs op DNS-navrae begin ervaar. Dit het gebeur ten spyte van 'n ongelooflike poging om die DNS-verskaffer te optimaliseer en oor te skakel na CoreDNS (wat 1000 peule bereik het wat op 120 kerne loop met pieklading).

Terwyl ons ander moontlike oorsake en oplossings ondersoek het, het ons gevind 'n artikel, wat die rastoestande beskryf wat die pakkiefiltreerraamwerk beïnvloed netto filter in linux. Die timeouts wat ons waarneem, saam met 'n toenemende teller invoeg_misluk in die Flannel-koppelvlak het ooreengestem met die gevolgtrekkings van die artikel.

Die probleem kom voor in die stadium van Bron- en Bestemmingsnetwerkadresvertaling (SNAT en DNAT) en daaropvolgende inskrywing in die tabel verbind. Een van die oplossings wat intern bespreek en deur die gemeenskap voorgestel is, was om DNS na die werkernodus self te migreer. In hierdie geval:

  • SNAT is nie nodig nie omdat die verkeer binne die gasheer bly. Dit hoef nie deur die koppelvlak gestuur te word nie et0.
  • DNAT is nie nodig nie, want die bestemmings-IP is plaaslik tot die nodus, en nie lukraak gekies deur die peul volgens die reëls nie iptables.

Ons het besluit om hierdie benadering te volg. CoreDNS is as 'n DaemonSet in Kubernetes ontplooi en ons het 'n plaaslike gasheer-DNS-bediener geïmplementeer in resolve.conf elke pod'a deur 'n vlag te stel --cluster-dns opdragte kubelet . Hierdie oplossing het geblyk doeltreffend te wees vir DNS-time-outs.

Ons het egter steeds pakkieverlies en toonbankinkremente gesien. invoeg_misluk in die Flanell-koppelvlak. Dit het voortgeduur selfs nadat die oplossing geïmplementeer is, aangesien ons slegs SNAT en/of DNAT vir DNS-verkeer kon uitskakel. Wedlooptoestande is vir ander soorte verkeer gehou. Gelukkig is die meeste van die pakkies wat ons het, TCP, en as 'n probleem opduik, word dit eenvoudig weer versend. Ons probeer steeds om 'n geskikte oplossing vir alle soorte verkeer te vind.

Gebruik Envoy vir beter lasbalansering

Soos backend-dienste na Kubernetes gemigreer het, het ons begin ly aan ongebalanseerde lading tussen peule. Ons het gevind dat HTTP Keepalive ELB-verbindings aan die eerste gereed peule van elke ontplooide ontplooiing laat hang het. Dus het die grootste deel van die verkeer deur 'n klein persentasie van die beskikbare peule gegaan. Die eerste oplossing wat ons getoets het, was om MaxSurge op 100% te stel op nuwe ontplooiings vir die ergste gevalle. Die effek het geblyk onbeduidend en onbelowend te wees in terme van groter ontplooiings.

Nog 'n oplossing wat ons gebruik het, was om hulpbronversoeke vir kritieke dienste kunsmatig te verhoog. In hierdie geval sal nabygeleë peule meer beweegruimte hê in vergelyking met ander swaar peule. Op die lange duur sou dit ook nie werk nie weens ’n vermorsing van hulpbronne. Boonop was ons Node-toepassings enkeldraad en kon gevolglik net een kern gebruik. Die enigste werklike oplossing was om beter lasbalansering te gebruik.

Ons wou lankal ten volle waardeer gesant. Die huidige situasie het ons toegelaat om dit op 'n baie beperkte manier te ontplooi en onmiddellike resultate te kry. Envoy is 'n oopbron-hoëprestasie Laag XNUMX-instaanbediener wat ontwerp is vir groot SOA-toepassings. Dit weet hoe om gevorderde lasbalanseringstegnieke toe te pas, insluitend outomatiese herprobasies, stroombrekers en globale tempobeperking. (Let wel. vertaal.: Jy kan meer hieroor lees in Hierdie artikel oor Istio, wat op Envoy gebaseer is.)

Ons het met die volgende konfigurasie vorendag gekom: om 'n Envoy-syspan vir elke peul en 'n enkele roete te hê, en die groep om plaaslik per hawe aan die houer te koppel. Om potensiële waterval te minimaliseer en die doodsradius klein te hou, het ons 'n vloot van Envoy front-proxy peule gebruik, een per Beskikbaarheidsone (AZ) vir elke diens. Hulle het 'n eenvoudige diensontdekkingsmeganisme gebruik wat deur een van ons ingenieurs geskryf is, wat eenvoudig 'n lys peule in elke AZ vir 'n gegewe diens teruggestuur het.

Die diensfrontgesante het toe hierdie diensontdekkingsmeganisme met 'n enkele stroomop-groepering en roete gebruik. Ons het voldoende uitteltyd gestel, alle stroombrekerinstellings verhoog, en 'n minimale herprobeerkonfigurasie bygevoeg om te help met enkele mislukkings en gladde ontplooiings te verseker. Voor elkeen van hierdie diensfrontgesante het ons 'n TCP ELB geplaas. Selfs al het die keepalive van ons hoof-instaanbedienerlaag aan sommige van die Envoy-peule gehang, kon hulle steeds die vrag baie beter hanteer en was hulle gekonfigureer om deur die minste_versoek in die agterkant te balanseer.

Vir ontplooiings het ons die preStop-haak op beide die toepassings- en syspan-peule gebruik. Die haak het 'n statuskontrolefout veroorsaak op die admin-eindpunt wat op die syspanhouer geleë is en het vir 'n rukkie gaan slaap om aktiewe verbindings te laat voltooi.

Een van die redes waarom ons so vinnig kon vorder, is as gevolg van die gedetailleerde statistieke wat ons maklik in 'n tipiese Prometheus-installasie kon integreer. Dit het ons in staat gestel om presies te sien wat aangaan terwyl ons die konfigurasie-opsies aangepas het en die verkeer herverdeel het.

Die resultate was onmiddellik en duidelik. Ons het begin met die mees ongebalanseerde dienste, en op die oomblik funksioneer dit reeds voor die 12 belangrikste dienste in die kluster. Hierdie jaar beplan ons om na 'n volledige diensnetwerk oor te gaan met meer gevorderde diensontdekking, stroombaanbreking, uitskietbespeuring, tempobeperking en opsporing.

Tinder se oorgang na Kubernetes
Figuur 3-1. Enkeldiens SVE-konvergensie tydens oorgang na Envoy

Tinder se oorgang na Kubernetes

Tinder se oorgang na Kubernetes

Finale uitslag

Deur ondervinding opgedoen en bykomende navorsing het ons 'n sterk infrastruktuurspan gebou met sterk vaardighede in die ontwerp, ontplooiing en bedryf van groot Kubernetes-klusters. Nou het alle Tinder-ingenieurs die kennis en ervaring oor hoe om houers te verpak en toepassings op Kubernetes te ontplooi.

Toe die ou infrastruktuur bykomende kapasiteit benodig, moes ons etlike minute wag vir nuwe EC2-gevalle om te begin. Nou begin houers en begin verkeer binne sekondes in plaas van minute verwerk. Die skedulering van veelvuldige houers op 'n enkele EC2-instansie bied ook verbeterde horisontale konsentrasie. Gevolglik voorspel ons in 2019 'n aansienlike verlaging in EC2-koste vergeleke met verlede jaar.

Die migrasie het byna twee jaar geneem, maar ons het dit in Maart 2019 voltooi. Die Tinder-platform loop tans uitsluitlik op 'n Kubernetes-kluster van 200 dienste, 1000 15 nodusse, 000 48 peule en 000 XNUMX lopende houers. Infrastruktuur is nie meer die eksklusiewe domein van operasionele spanne nie. Al ons ingenieurs deel hierdie verantwoordelikheid en beheer die proses van die bou en ontplooiing van hul toepassings deur kode alleen.

PS van vertaler

Lees ook in ons blog 'n reeks artikels:

Bron: will.com

Voeg 'n opmerking