Tinderi üleminek Kubernetesile

Märge. tõlge: Maailmakuulsa Tinderi teenuse töötajad jagasid hiljuti mõningaid tehnilisi üksikasju oma infrastruktuuri üleviimise kohta Kubernetesesse. Protsess kestis peaaegu kaks aastat ja selle tulemusel käivitati K8s väga laiaulatuslik platvorm, mis koosnes 200 teenusest, mis on hostitud 48 tuhandel konteineril. Milliste huvitavate raskustega Tinderi insenerid kokku puutusid ja milliste tulemusteni nad jõudsid? Lugege seda tõlget.

Tinderi üleminek Kubernetesile

Miks?

Peaaegu kaks aastat tagasi otsustas Tinder oma platvormi Kubernetesesse kolida. Kubernetes võimaldaks Tinderi meeskonnal muutumatu juurutamise kaudu minimaalse pingutusega konteinerisse paigutada ja tootmisse üle minna (muutmatu kasutuselevõtt). Sel juhul oleks rakenduste komplekt, nende juurutamine ja infrastruktuur ise koodiga üheselt määratletud.

Samuti otsisime lahendust mastaapsuse ja stabiilsuse probleemile. Kui skaleerimine muutus kriitiliseks, pidime sageli mitu minutit ootama, kuni uued EC2 eksemplarid ilmuvad. Idee konteinerite käivitamisest ja liikluse teenindamise alustamisest minutite asemel sekunditega muutus meile väga ahvatlevaks.

Protsess osutus keeruliseks. Meie migratsiooni ajal 2019. aasta alguses saavutas Kubernetese klaster kriitilise massi ja me hakkasime kokku puutuma mitmesuguste liiklusmahu, klastri suuruse ja DNS-i probleemidega. Selle käigus lahendasime palju huvitavaid probleeme, mis on seotud 200 teenuse migreerimise ja 1000 sõlmest, 15000 48000 kaustast ja XNUMX XNUMX töötavast konteinerist koosneva Kubernetese klastri hooldamisega.

Kuidas?

Alates 2018. aasta jaanuarist oleme läbinud erinevaid rändetappe. Alustuseks koondasime kõik oma teenused konteinerisse ja juurutasime need Kubernetese testpilvekeskkondadesse. Alates oktoobrist alustasime kõigi olemasolevate teenuste metoodilist üleviimist Kubernetesesse. Järgmise aasta märtsiks saime migratsiooni lõpule ja nüüd töötab Tinderi platvorm ainult Kubernetes.

Kubernetese piltide loomine

Meil on Kubernetese klastris töötavate mikroteenuste jaoks üle 30 lähtekoodihoidla. Nendes hoidlates olev kood on kirjutatud erinevates keeltes (näiteks Node.js, Java, Scala, Go) ja sama keele jaoks on mitu käituskeskkonda.

Koostamissüsteem on loodud pakkuma iga mikroteenuse jaoks täielikult kohandatavat "ehituskonteksti". Tavaliselt koosneb see Dockerfile'ist ja shellikäskude loendist. Nende sisu on täielikult kohandatav ja samal ajal on kõik need ehituskontekstid kirjutatud standardvormingus. Järgukontekstide standardimine võimaldab ühel ehitussüsteemil käsitleda kõiki mikroteenuseid.

Tinderi üleminek Kubernetesile
Joonis 1-1. Standardiseeritud ehitusprotsess Builderi konteineri kaudu

Et saavutada maksimaalne järjepidevus käitusaegade vahel (käituskeskkonnad) arenduse ja testimise ajal kasutatakse sama ehitusprotsessi. Meie ees seisis väga huvitav väljakutse: pidime välja töötama viisi, kuidas tagada ehituskeskkonna järjepidevus kogu platvormil. Selle saavutamiseks viiakse kõik montaažiprotsessid läbi spetsiaalses konteineris. Ehitaja.

Tema konteinerite rakendamine nõudis täiustatud Dockeri tehnikaid. Builder pärib privaatsetele Tinderi hoidlatele juurdepääsuks vajalikud kohaliku kasutaja ID ja saladused (nt SSH-võti, AWS-i mandaadid jne). See ühendab kohalikud kataloogid, mis sisaldavad allikaid, et loomulikult salvestada ehitusartefakte. See lähenemisviis parandab jõudlust, kuna see välistab vajaduse kopeerida ehitusartefakte Builderi konteineri ja hosti vahel. Salvestatud ehitusartefakte saab ilma täiendava konfiguratsioonita uuesti kasutada.

Mõne teenuse jaoks pidime koostama teise konteineri, et vastendada kompileerimiskeskkond käituskeskkonnaga (näiteks Node.js bcrypt teek genereerib installimise ajal platvormipõhiseid binaarartefakte). Koostamise käigus võivad nõuded teenuste lõikes erineda ja lõplik Dockeri fail koostatakse käigu pealt.

Kubernetese klastri arhitektuur ja migratsioon

Klastri suuruse juhtimine

Otsustasime kasutada kube-aws klastri automatiseeritud juurutamiseks Amazon EC2 eksemplaridel. Alguses töötas kõik ühes ühises sõlmede kogumis. Saime kiiresti aru, et ressursside tõhusamaks kasutamiseks on vaja töökoormused suuruse ja eksemplari tüübi järgi eraldada. Loogika seisnes selles, et mitme laaditud mitme keermega kausta käivitamine osutus jõudluse osas prognoositavamaks kui nende kooseksisteerimine suure hulga ühe keermega kaustadega.

Lõpuks leppisime kokku:

  • m5.4xsuur — seireks (Prometheus);
  • c5.4xsuur - Node.js töökoormuse jaoks (ühe lõime töökoormus);
  • c5.2xsuur - Java ja Go jaoks (mitmelõimeline töökoormus);
  • c5.4xsuur — juhtpaneeli jaoks (3 sõlme).

Ränne

Üks ettevalmistavaid samme vanalt taristult Kubernetesele üleminekuks oli olemasoleva teenustevahelise otsesuhtluse ümbersuunamine uutele koormuse tasakaalustajatele (Elastic Load Balancers (ELB). Need loodi virtuaalse privaatpilve (VPC) kindlas alamvõrgus. See alamvõrk oli ühendatud Kubernetes VPC-ga. See võimaldas meil mooduleid järk-järgult üle viia, arvestamata teenuse sõltuvuste konkreetset järjekorda.

Need lõpp-punktid loodi DNS-kirjete kaalutud komplektide abil, mille CNAME-id osutasid igale uuele ELB-le. Ümberlülitamiseks lisasime uue kirje, mis osutab Kubernetese teenuse uuele ELB-le kaaluga 0. Seejärel määrasime kirjekomplekti Time To Live (TTL) väärtuseks 0. Pärast seda määrati vana ja uus kaal. aeglaselt kohandatud ja lõpuks saadeti 100% koormusest uude serverisse. Pärast ümberlülitamise lõpetamist naasis TTL väärtus adekvaatsemale tasemele.

Meil olevad Java moodulid said madala TTL DNS-iga hakkama, kuid Node rakendused ei saanud hakkama. Üks inseneridest kirjutas osa ühenduse basseini koodist ümber ja pakkis selle haldurisse, mis värskendas basseine iga 60 sekundi järel. Valitud lähenemisviis töötas väga hästi ja ilma märgatava jõudluse halvenemiseta.

Õppetunnid

Võrgukanga piirangud

8. jaanuari 2019 varahommikul jooksis Tinderi platvorm ootamatult kokku. Vastuseks platvormi latentsusaja sõltumatusele suurenemisele hommikul, suurenes klastris olevate kaunade ja sõlmede arv. See põhjustas ARP-vahemälu ammendumise kõigis meie sõlmedes.

ARP-vahemäluga on seotud kolm Linuxi valikut:

Tinderi üleminek Kubernetesile
(allikas)

gc_thresh3 - see on karm piir. "Naabertabeli ületäitumise" kirjete ilmumine logisse tähendas, et isegi pärast sünkroonset prügikoristust (GC) ei olnud ARP-vahemälus piisavalt ruumi naaberkirje salvestamiseks. Sel juhul viskas tuum paketi lihtsalt täielikult ära.

Me kasutame Flanell võrgukangana Kubernetesis. Paketid edastatakse VXLAN-i kaudu. VXLAN on teise taseme tunnel, mis on tõstetud L2 võrgu peale. Tehnoloogia kasutab MAC-in-UDP (MAC Address-in-User Datagram Protocol) kapseldamist ja võimaldab 3. kihi võrgusegmente laiendada. Füüsilise andmekeskuse võrgu transpordiprotokoll on IP pluss UDP.

Tinderi üleminek Kubernetesile
Joonis 2–1. Flanelldiagramm (allikas)

Tinderi üleminek Kubernetesile
Joonis 2–2. VXLAN pakett (allikas)

Iga Kubernetese töötaja sõlm eraldab suuremast /24 plokist /9 maskiga virtuaalse aadressiruumi. Iga sõlme jaoks on see vahendid üks kirje marsruutimistabelis, üks kirje ARP tabelis (liideses flannel.1) ja üks kirje kommutatsioonitabelis (FDB). Need lisatakse töötaja sõlme esmakordsel käivitamisel või iga kord, kui avastatakse uus sõlm.

Lisaks läbib sõlme-podi (või pod-podi) suhtlus lõpuks liidese eth0 (nagu on näidatud ülaltoodud flanelli diagrammil). Selle tulemuseks on täiendav kirje ARP-tabelis iga vastava lähte- ja sihthosti kohta.

Meie keskkonnas on selline suhtlus väga levinud. Kubernetese teenindusobjektide jaoks luuakse ELB ja Kubernetes registreerib iga sõlme ELB-ga. ELB ei tea kaustadest midagi ja valitud sõlm ei pruugi olla paketi lõppsihtkoht. Asi on selles, et kui sõlm saab ELB-lt paketi, arvestab ta seda reegleid arvesse võttes iptables konkreetse teenuse jaoks ja valib juhuslikult teises sõlmes oleva podi.

Rikke ajal oli klastris 605 sõlme. Eespool nimetatud põhjustel piisas sellest tähtsuse ületamiseks gc_thresh3, mis on vaikeseade. Kui see juhtub, ei hakata mitte ainult pakette välja langema, vaid kaob ARP-tabelist kogu Flanelli virtuaalne aadressiruum koos /24 maskiga. Sõlme-poodide side ja DNS-päringud on katkenud (DNS-i hostitakse klastris; üksikasju leiate sellest artiklist hiljem).

Selle probleemi lahendamiseks peate väärtusi suurendama gc_thresh1, gc_thresh2 и gc_thresh3 ja taaskäivitage Flannel puuduvate võrkude uuesti registreerimiseks.

Ootamatu DNS-i skaleerimine

Migratsiooniprotsessi ajal kasutasime aktiivselt DNS-i liikluse haldamiseks ja teenuste järkjärguliseks ülekandmiseks vanast infrastruktuurist Kubernetesesse. Seadsime Route53 seotud kirjekomplektide jaoks suhteliselt madalad TTL-väärtused. Kui vana infrastruktuur töötas EC2 eksemplaridel, osutas meie lahendaja konfiguratsioon Amazon DNS-ile. Pidasime seda enesestmõistetavaks ja madala TTL-i mõju meie teenustele ja Amazoni teenustele (nt DynamoDB) jäi suures osas märkamatuks.

Teenuste üleviimisel Kubernetesesse avastasime, et DNS töötles 250 tuhat päringut sekundis. Selle tulemusena hakkasid rakendused kogema DNS-päringute jaoks pidevaid ja tõsiseid ajalõpusid. See juhtus vaatamata uskumatutele jõupingutustele optimeerida ja lülitada DNS-i pakkuja CoreDNS-ile (mis tippkoormusel jõudis 1000 kaunani, mis töötavad 120 tuumal).

Uurides muid võimalikke põhjuseid ja lahendusi, avastasime artiklit, mis kirjeldab pakettide filtreerimise raamistikku mõjutavaid võistlustingimusi netfilter Linuxis. Täheldatud ajalõpud koos kasvava loenduriga sisestamine_ebaõnnestunud Flanelli liideses olid kooskõlas artikli järeldustega.

Probleem ilmneb lähte- ja sihtvõrgu aadressi tõlkimise (SNAT ja DNAT) etapis ning sellele järgnevas tabelisse sisenemise etapis. conntrack. Üks sisemiselt arutatud ja kogukonna soovitatud lahendustest oli DNS-i teisaldamine töötaja sõlme endasse. Sel juhul:

  • SNAT-i pole vaja, sest liiklus jääb sõlme sisse. Seda ei pea juhtima liidese kaudu eth0.
  • DNAT-d pole vaja, kuna sihtkoha IP on sõlme lokaalne, mitte reeglite kohaselt juhuslikult valitud pod iptables.

Otsustasime selle lähenemisviisi juurde jääda. CoreDNS juurutati Kubernetesis DaemonSetina ja me juurutasime kohaliku sõlme DNS-serveri solve.conf iga kaun, seades lipu --cluster-dns meeskonnad kubelet . See lahendus osutus tõhusaks DNS-i ajalõppude korral.

Siiski nägime endiselt pakettide kadu ja loenduri tõusu sisestamine_ebaõnnestunud Flanelli liideses. See jätkus ka pärast lahenduse rakendamist, kuna suutsime SNAT-i ja/või DNAT-i kõrvaldada ainult DNS-liikluse jaoks. Võistlustingimused säilitati ka muude liiklusliikide jaoks. Õnneks on enamik meie pakette TCP-d ja kui probleem ilmneb, saadetakse need lihtsalt uuesti. Püüame endiselt leida sobiva lahenduse igat tüüpi liiklusele.

Envoy kasutamine koormuse paremaks tasakaalustamiseks

Kui viisime taustateenuseid Kubernetesesse, hakkasime kannatama kaunade vahel tasakaalustamata koormuse all. Leidsime, et HTTP Keepalive põhjustas ELB-ühenduste rippumise iga juurutuse esimestel valmiskastidel. Seega läbis suurem osa liiklusest väikese osa saadaolevatest kaustadest. Esimene lahendus, mida testisime, oli MaxSurge'i seadmine 100% uute juurutuste puhul halvima stsenaariumi korral. Mõju osutus suuremate kasutuselevõtu osas tähtsusetuks ja vähetõotavaks.

Teine lahendus, mida kasutasime, oli kriitiliste teenuste ressursitaotluste kunstlik suurendamine. Sel juhul oleks läheduses asetatud kaunadel teiste raskete kaunadega võrreldes rohkem manööverdamisruumi. See ei töötaks ka pikas perspektiivis, sest see oleks ressursside raiskamine. Lisaks olid meie Node rakendused ühe keermega ja said seega kasutada ainult ühte tuuma. Ainus reaalne lahendus oli parema koormuse tasakaalustamise kasutamine.

Oleme pikka aega tahtnud täielikult hinnata saadik. Praegune olukord võimaldas meil seda väga piiratud viisil kasutusele võtta ja saada koheseid tulemusi. Envoy on suure jõudlusega avatud lähtekoodiga XNUMX. kihi puhverserver, mis on mõeldud suurte SOA rakenduste jaoks. See võib rakendada täiustatud koormuse tasakaalustamise tehnikaid, sealhulgas automaatseid korduskatseid, kaitselüliteid ja globaalset kiiruse piiramist. (Märge. tõlge: Lisateavet selle kohta saate lugeda see artikkel Istio kohta, mis põhineb saadikul.)

Jõudsime välja järgmise konfiguratsiooniga: omage iga podi ja ühe marsruudi jaoks Envoy külgkorvi ning ühendage klaster kohapeal konteineriga pordi kaudu. Võimaliku kaskaadi minimeerimiseks ja väikese tabamusraadiuse säilitamiseks kasutasime Envoy eesmise puhverserveri parki, üks iga teenuse saadavuse tsooni (AZ) kohta. Nad tuginesid lihtsale teenuseotsingu mootorile, mille oli kirjutanud üks meie inseneridest, mis lihtsalt tagastas antud teenuse igas AZ-s olevate kaustade loendi.

Seejärel kasutasid teenindusesindajad seda teenusetuvastusmehhanismi ühe ülesvoolu klastri ja marsruudiga. Seadsime piisavad ajalõpud, suurendasime kõiki kaitselüliti sätteid ja lisasime minimaalse uuesti proovimise konfiguratsiooni, et aidata üksikute tõrgete korral ja tagada sujuv juurutamine. Asetasime TCP ELB-d iga teenistusesaatja ette. Isegi kui meie peamise puhverserveri kihi Keepalive jäi mõnele Envoy kaustale kinni, said need siiski palju paremini hakkama koormusega ja olid konfigureeritud tasakaalustama taustarakenduse vähim_taotluse kaudu.

Kasutuselevõtmiseks kasutasime nii rakenduskapslitel kui ka külgkorvi hoidikutel preStop-konksu. Konks käivitas tõrke külgkorvi konteineris asuva administraatori lõpp-punkti oleku kontrollimisel ja läks mõneks ajaks magama, et võimaldada aktiivsetel ühendustel katkeda.

Üks põhjusi, miks saime nii kiiresti liikuda, on tingitud üksikasjalikest mõõdikutest, mida saime hõlpsasti integreerida tüüpilise Prometheuse installatsiooniga. See võimaldas meil täpselt näha, mis konfiguratsiooniparameetrite kohandamise ja liikluse ümberjagamise ajal toimus.

Tulemused olid kohesed ja ilmsed. Alustasime kõige tasakaalustamata teenustega ja hetkel tegutseb see klastri 12 olulisema teenuse ees. Sel aastal plaanime üleminekut täisteenusvõrgule, mis sisaldab täiustatud teenuse tuvastamist, voolukatkestusi, kõrvalekallete tuvastamist, kiiruse piiramist ja jälgimist.

Tinderi üleminek Kubernetesile
Joonis 3–1. Ühe teenuse CPU konvergents Envoyle ülemineku ajal

Tinderi üleminek Kubernetesile

Tinderi üleminek Kubernetesile

Lõpptulemus

Selle kogemuse ja täiendavate uuringute abil oleme loonud tugeva infrastruktuurimeeskonna, kellel on tugevad oskused suurte Kubernetese klastrite kavandamisel, juurutamisel ja käitamisel. Kõigil Tinderi inseneridel on nüüd teadmised ja kogemused konteinerite pakkimiseks ja rakenduste juurutamiseks Kubernetes.

Kui vanal taristul tekkis vajadus lisavõimsuse järele, pidime uute EC2 eksemplaride käivitamist ootama mitu minutit. Nüüd hakkavad konteinerid töötama ja liiklust töötlema mõne sekundi, mitte minutite jooksul. Mitme konteineri ajastamine ühele EC2 eksemplarile tagab ka parema horisontaalse kontsentratsiooni. Sellest tulenevalt prognoosime 2019. aastal EC2 kulude olulist vähenemist võrreldes eelmise aastaga.

Ränne kestis peaaegu kaks aastat, kuid lõpetasime selle 2019. aasta märtsis. Praegu töötab Tinderi platvorm eranditult Kubernetese klastris, mis koosneb 200 teenusest, 1000 sõlmest, 15 000 kaustast ja 48 000 töötavast konteinerist. Infrastruktuur ei ole enam operatiivmeeskondade ainus valdkond. Kõik meie insenerid jagavad seda vastutust ning juhivad oma rakenduste loomise ja juurutamise protsessi ainult koodi kasutades.

PS tõlkijalt

Loe ka meie ajaveebi artiklite sarja:

Allikas: www.habr.com

Lisa kommentaar