Tinder-transiro al Kubernetes

Notu. transl.: Dungitoj de la mondfama servo Tinder lastatempe konigis kelkajn teknikajn detalojn pri migrado de sia infrastrukturo al Kubernetes. La procezo daŭris preskaŭ du jarojn kaj rezultigis la lanĉon de tre grandskala platformo sur K8s, konsistanta el 200 servoj gastigitaj sur 48 mil ujoj. Kiajn interesajn malfacilaĵojn renkontis la inĝenieroj de Tinder kaj al kiaj rezultoj ili venis?Legu ĉi tiun tradukon.

Tinder-transiro al Kubernetes

Kial?

Antaŭ preskaŭ du jaroj, Tinder decidis movi sian platformon al Kubernetes. Kubernetes permesus al la teamo Tinder konteneri kaj moviĝi al produktado kun minimuma peno per neŝanĝebla deplojo (neŝanĝebla deplojo). En ĉi tiu kazo, la kunigo de aplikoj, ilia deplojo kaj la infrastrukturo mem estus unike difinitaj per kodo.

Ni ankaŭ serĉis solvon al la problemo de skaleblo kaj stabileco. Kiam grimpigo fariĝis kritika, ni ofte devis atendi plurajn minutojn por ke novaj EC2-instancoj ŝpruciĝos. La ideo lanĉi ujojn kaj komenci servi trafikon en sekundoj anstataŭ minutoj fariĝis tre alloga por ni.

La procezo montriĝis malfacila. Dum nia migrado komence de 2019, la Kubernetes-grupo atingis kritikan mason kaj ni komencis renkonti diversajn problemojn pro trafika volumo, areto kaj DNS. Survoje, ni solvis multajn interesajn problemojn rilate al migrado de 200 servoj kaj konservado de Kubernetes-grupo konsistanta el 1000 nodoj, 15000 podoj kaj 48000 kurantaj ujoj.

Kiel?

Ekde januaro 2018, ni trapasis diversajn stadiojn de migrado. Ni komencis kontenerigante ĉiujn niajn servojn kaj deplojante ilin al provaj nubaj medioj de Kubernetes. Ekde oktobro, ni komencis metode migri ĉiujn ekzistantajn servojn al Kubernetes. Ĝis marto de la sekva jaro, ni kompletigis la migradon kaj nun la platformo Tinder funkcias ekskluzive sur Kubernetes.

Konstruado de bildoj por Kubernetes

Ni havas pli ol 30 fontkodajn deponejojn por mikroservoj kurantaj sur Kubernetes-areto. La kodo en ĉi tiuj deponejoj estas skribita en malsamaj lingvoj (ekzemple, Node.js, Java, Scala, Go) kun pluraj rultempaj medioj por la sama lingvo.

La konstrusistemo estas dizajnita por disponigi plene agordeblan "konstruan kuntekston" por ĉiu mikroservo. Ĝi kutime konsistas el Dockerfile kaj listo de ŝelkomandoj. Ilia enhavo estas tute agordebla, kaj samtempe ĉiuj ĉi konstruaj kuntekstoj estas skribitaj laŭ normigita formato. Normigi konstrukuntekstojn permesas al unu sola konstrusistemo pritrakti ĉiujn mikroservojn.

Tinder-transiro al Kubernetes
Figuro 1-1. Normigita konstruprocezo per Builder-ujo

Por atingi maksimuman konsistencon inter rultempoj (rultempaj medioj) la sama konstruprocezo estas uzata dum evoluo kaj testado. Ni alfrontis tre interesan defion: ni devis evoluigi manieron certigi konsistencon de la konstrumedio tra la tuta platformo. Por atingi tion, ĉiuj kunigprocezoj estas efektivigitaj ene de speciala ujo. konstruisto.

Lia efektivigo de kontenero postulis altnivelajn Docker-teknikojn. Konstruisto heredas la lokan uzantidentigilon kaj sekretojn (kiel SSH-ŝlosilon, AWS-akreditaĵojn, ktp.) necesajn por aliri privatajn deponejojn de Tinder. Ĝi muntas lokajn adresarojn enhavantajn fontojn por nature stoki konstruajn artefaktojn. Ĉi tiu aliro plibonigas efikecon ĉar ĝi forigas la bezonon kopii konstruajn artefaktojn inter la Builder-ujo kaj la gastiganto. Stokitaj konstruaj artefaktoj povas esti reuzitaj sen plia agordo.

Por iuj servoj, ni devis krei alian ujon por mapi la kompilan medion al la rultempa medio (ekzemple, la Node.js bcrypt-biblioteko generas platform-specifajn binarajn artefaktojn dum instalado). Dum la kompilprocezo, postuloj povas varii inter servoj, kaj la fina Dockerfile estas kompilita sur la flugo.

Kubernetes-grupo-arkitekturo kaj migrado

Administrado de grandeco de areto

Ni decidis uzi kube-aws por aŭtomatigita clusterdeplojo sur Amazon EC2-instancoj. Ĉe la komenco, ĉio funkciis en unu komuna aro de nodoj. Ni rapide rimarkis la bezonon apartigi laborŝarĝojn laŭ grandeco kaj instanco-tipo por fari pli efikan uzon de rimedoj. La logiko estis, ke ruli plurajn ŝarĝitajn multfadenajn podojn montriĝis pli antaŭvidebla laŭ rendimento ol ilia kunekzistado kun granda nombro da unufadenaj podoj.

Fine ni decidis:

  • m5.4xgranda — por monitorado (Prometeo);
  • c5.4xgranda - por Node.js laborŝarĝo (unu-fadena laborŝarĝo);
  • c5.2xgranda - por Java kaj Go (multfadena laborŝarĝo);
  • c5.4xgranda — por la kontrolpanelo (3 nodoj).

Migrado

Unu el la preparaj paŝoj por migrado de la malnova infrastrukturo al Kubernetes estis redirekti la ekzistantan rektan komunikadon inter servoj al la novaj ŝarĝbalanciloj (Elastic Load Balancers (ELB). Ili estis kreitaj sur specifa subreto de virtuala privata nubo (VPC). Ĉi tiu subreto estis konektita al Kubernetes VPC. Ĉi tio permesis al ni migri modulojn laŭgrade, sen konsideri la specifan ordon de servodependecoj.

Tiuj finpunktoj estis kreitaj uzante pezbalancitajn arojn de DNS-rekordoj kiuj havis CNAMEojn montrantajn al ĉiu nova ELB. Por ŝanĝi, ni aldonis novan eniron montrantan al la nova ELB de la servo Kubernetes kun pezo de 0. Ni tiam starigis la Tempon por Vivi (TTL) de la eniro fiksita al 0. Post ĉi tio, la malnovaj kaj novaj pezoj estis malrapide alĝustigita, kaj finfine 100% de la ŝarĝo estis sendita al nova servilo. Post kiam la ŝanĝado estis kompletigita, la TTL-valoro revenis al pli adekvata nivelo.

La Java-moduloj, kiujn ni havis, povis elteni malaltan TTL-DNS, sed la Node-aplikoj ne povis. Unu el la inĝenieroj reverkis parton de la koneksa naĝejo kaj envolvis ĝin en administranto kiu ĝisdatigis la naĝejojn ĉiujn 60 sekundojn. La elektita aliro funkciis tre bone kaj sen ia rimarkinda rendimentodegenero.

Lecionoj

La Limoj de la Reta Ŝtofo

Frumatene de la 8-a de januaro 2019, la platformo Tinder neatendite kraŝis. En respondo al senrilata pliiĝo en platforma latenteco pli frue tiun matenon, la nombro da balgoj kaj nodoj en la areto pliiĝis. Ĉi tio kaŭzis, ke la ARP-kaŝmemoro elĉerpiĝis sur ĉiuj niaj nodoj.

Estas tri Linukso-opcioj rilataj al la ARP-kaŝmemoro:

Tinder-transiro al Kubernetes
(fonto)

gc_thresh3 - ĉi tio estas malfacila limo. La apero de "najbara tablo superfluo" enskriboj en la protokolo signifis ke eĉ post sinkrona rubkolekto (GC), estis ne sufiĉe da spaco en la ARP-kaŝmemoro por stoki la najbaran eniron. En ĉi tiu kazo, la kerno simple forĵetis la pakaĵeton tute.

Ni uzas Fandalo kiel retŝtofo en Kubernetes. Pakoj estas elsenditaj tra VXLAN. VXLAN estas L2 tunelo levita aldone al L3-reto. La teknologio uzas MAC-en-UDP (MAC Address-in-User Datagram Protocol) enkapsuligon kaj permesas vastiĝon de Layer 2 retsegmentoj. La transportprotokolo en la fizika datumcentra reto estas IP plus UDP.

Tinder-transiro al Kubernetes
Figuro 2–1. Flanela diagramo (fonto)

Tinder-transiro al Kubernetes
Figuro 2-2. VXLAN-pakaĵo (fonto)

Ĉiu labornodo de Kubernetes asignas virtualan adresspacon kun /24-masko de pli granda /9-bloko. Por ĉiu nodo ĉi tio estas signifas unu eniro en la vojtabelo, unu eniro en la ARP-tabelo (sur la flannel.1-interfaco), kaj unu eniro en la ŝanĝtabelo (FDB). Ili estas aldonitaj la unuan fojon kiam laborista nodo estas komencita aŭ ĉiufoje kiam nova nodo estas malkovrita.

Aldone, nodo-pod (aŭ pod-pod) komunikado finfine iras tra la interfaco et0 (kiel montrite en la Flanela diagramo supre). Ĉi tio rezultigas plian eniron en la ARP-tabelo por ĉiu responda fonto kaj celgastiganto.

En nia medio, ĉi tiu tipo de komunikado estas tre ofta. Por servobjektoj en Kubernetes, ELB estas kreita kaj Kubernetes registras ĉiun nodon kun la ELB. La ELB scias nenion pri balgoj kaj la elektita nodo eble ne estas la fina celo de la pako. La punkto estas, ke kiam nodo ricevas pakaĵeton de la ELB, ĝi konsideras ĝin konsiderante la regulojn iptables por specifa servo kaj hazarde elektas pod sur alia nodo.

En la momento de la fiasko, estis 605 nodoj en la areto. Pro la supraj kialoj, tio sufiĉis por venki la signifon gc_thresh3, kiu estas la defaŭlta. Kiam tio okazas, ne nur pakaĵetoj komencas esti faligitaj, sed la tuta Flannel virtuala adresspaco kun /24-masko malaperas de la ARP-tabelo. Nodo-pod-komunikado kaj DNS-demandoj estas interrompitaj (DNS estas gastigita en areto; legu poste en ĉi tiu artikolo por detaloj).

Por solvi ĉi tiun problemon, vi devas pliigi la valorojn gc_thresh1, gc_thresh2 и gc_thresh3 kaj rekomencu Flannel por reregistri la mankantajn retojn.

Neatendita DNS-skalado

Dum la migrada procezo, ni aktive uzis DNS por administri trafikon kaj iom post iom transdoni servojn de la malnova infrastrukturo al Kubernetes. Ni fiksas relative malaltajn TTL-valorojn por rilataj RecordSets en Route53. Kiam la malnova infrastrukturo funkciis per EC2-instancoj, nia solvila agordo montris Amazon DNS. Ni prenis ĉi tion por donita kaj la efiko de la malalta TTL sur niaj servoj kaj Amazon-servoj (kiel ekzemple DynamoDB) estis plejparte nerimarkita.

Dum ni migris servojn al Kubernetes, ni trovis, ke DNS prilaboras 250 mil petojn sekundo. Kiel rezulto, aplikoj komencis sperti konstantajn kaj seriozajn tempodaŭrojn por DNS-demandoj. Ĉi tio okazis malgraŭ nekredeblaj klopodoj por optimumigi kaj ŝanĝi la DNS-provizanton al CoreDNS (kiu ĉe pinta ŝarĝo atingis 1000 podojn kurantajn sur 120 kernoj).

Esplorante aliajn eblajn kaŭzojn kaj solvojn, ni malkovris artikolo, priskribante raskondiĉojn influantajn la pakaĵetan filtran kadron netfiltrilo en Linukso. La tempodaŭroj ni observis, kunligitaj kun kreskanta nombrilo insert_failed en la Flannel-interfaco estis kongruaj kun la trovoj de la artikolo.

La problemo okazas ĉe la stadio de Fonto kaj Destina Reto-Adrestraduko (SNAT kaj DNAT) kaj posta eniro en la tabelon ligo. Unu el la solvoj diskutitaj interne kaj sugestitaj de la komunumo estis movi la DNS al la laborista nodo mem. Tiuokaze:

  • SNAT ne estas bezonata ĉar la trafiko restas ene de la nodo. Ĝi ne bezonas esti direktita tra la interfaco et0.
  • DNAT ne estas bezonata ĉar la celo IP estas loka al la nodo, kaj ne hazarde elektita pod laŭ la reguloj iptables.

Ni decidis resti kun ĉi tiu aliro. CoreDNS estis deplojita kiel DaemonSet en Kubernetes kaj ni efektivigis lokan nodan DNS-servilon en solv.conf ĉiu balgo metante flagon --cluster-dns ordonas kubeto . Ĉi tiu solvo montriĝis efika por DNS-tempotempoj.

Tamen, ni ankoraŭ vidis pakaĵperdon kaj pliiĝon en la nombrilo insert_failed en la Flanela interfaco. Ĉi tio daŭris post kiam la solvo estis efektivigita ĉar ni povis forigi SNAT kaj/aŭ DNAT nur por DNS-trafiko. Vetkurkondiĉoj estis konservitaj por aliaj specoj de trafiko. Feliĉe, la plej multaj el niaj pakaĵoj estas TCP, kaj se okazas problemo ili estas simple retranssenditaj. Ni ankoraŭ provas trovi taŭgan solvon por ĉiuj specoj de trafiko.

Uzante Envoy por Pli bona Ŝarĝbalancado

Dum ni migris backend-servojn al Kubernetes, ni komencis suferi de malekvilibra ŝarĝo inter podoj. Ni trovis, ke HTTP Keepalive kaŭzis, ke ELB-konektoj pendis sur la unuaj pretaj podoj de ĉiu disfaldiĝo. Tiel, la plejparto de la trafiko trapasis malgrandan procenton de disponeblaj guŝoj. La unua solvo, kiun ni testis, estis agordi MaxSurge al 100% pri novaj deplojoj por plej malbonaj okazoj. La efiko montriĝis por sensignifa kaj nepromesplena laŭ pli grandaj deplojoj.

Alia solvo, kiun ni uzis, estis artefarite pliigi rimedpetojn por kritikaj servoj. En ĉi tiu kazo, balgoj metitaj proksime havus pli da loko por manovri kompare kun aliaj pezaj balgoj. Ĝi ankaŭ ne funkcius longtempe ĉar ĝi estus malŝparo de rimedoj. Krome, niaj Node-aplikoj estis unufadenaj kaj, sekve, povis uzi nur unu kernon. La nura vera solvo estis uzi pli bonan ŝarĝbalancadon.

Ni delonge volis plene aprezi sendita. La nuna situacio permesis al ni deploji ĝin en tre limigita maniero kaj akiri tujajn rezultojn. Envoy estas alt-efikeca, malfermfonta, tavolo-XNUMX prokurilo dizajnita por grandaj SOA-aplikoj. Ĝi povas efektivigi altnivelajn ŝarĝajn ekvilibrajn teknikojn, inkluzive de aŭtomataj reprovoj, ŝaltiloj kaj tutmonda tariflimigo. (Notu. transl.: Vi povas legi pli pri tio en ĉi tiu artikolo pri Istio, kiu baziĝas sur Envoy.)

Ni elpensis la sekvan agordon: havu Envoy-kromĉaron por ĉiu pod kaj ununura itinero, kaj ligu la areton al la ujo loke per haveno. Por minimumigi eblan kaskadon kaj konservi malgrandan trafan radiuson, ni uzis aron de Envoy-antaŭprokuraj podoj, unu per Disponebla Zono (AZ) por ĉiu servo. Ili dependis de simpla servo-malkovra motoro skribita de unu el niaj inĝenieroj, kiu simple resendis liston de balgoj en ĉiu AZ por difinita servo.

Servaj antaŭaj senditoj tiam uzis ĉi tiun servo-malkovran mekanismon kun unu kontraŭflua areto kaj itinero. Ni agordis taŭgajn paŭzojn, pliigis ĉiujn agordojn de interrompilo kaj aldonis minimuman reprovan agordon por helpi pri unuopaj misfunkciadoj kaj certigi glatajn deplojojn. Ni metis TCP ELB antaŭ ĉiu el ĉi tiuj servaj frontaj senditoj. Eĉ se la konservado de nia ĉefa prokura tavolo estis blokita sur iuj Envoy-podoj, ili ankoraŭ povis multe pli bone trakti la ŝarĝon kaj estis agorditaj por ekvilibrigi per minimum_request en la backend.

Por deplojo, ni uzis la preStop-hokon sur ambaŭ aplikaĵkapsoj kaj kromĉaroj. La hoko deĉenigis eraron en kontrolado de la stato de la administra finpunkto situanta sur la sidecar-ujo kaj endormiĝis dum iom da tempo por permesi ke aktivaj ligoj ĉesigu.

Unu el la kialoj, ke ni povis moviĝi tiel rapide, estas pro la detalaj metrikoj, kiujn ni povis facile integri en tipa Prometheus-instalaĵo. Ĉi tio permesis al ni vidi ĝuste kio okazis dum ni ĝustigis agordajn parametrojn kaj redistribuis trafikon.

La rezultoj estis tujaj kaj evidentaj. Ni komencis per la plej malekvilibraj servoj, kaj nuntempe ĝi funkcias antaŭ la 12 plej gravaj servoj en la areto. Ĉi-jare ni planas transiron al plena servo-maŝo kun pli altnivela servo-malkovro, cirkvito-rompado, eksterordinara detekto, tariflimigo kaj spurado.

Tinder-transiro al Kubernetes
Figuro 3–1. CPU-konverĝo de unu servo dum la transiro al Envoy

Tinder-transiro al Kubernetes

Tinder-transiro al Kubernetes

Fina rezulto

Per ĉi tiu sperto kaj plia esplorado, ni konstruis fortan infrastrukturan teamon kun fortaj kapabloj en projektado, deplojado kaj funkciigado de grandaj Kubernetes-grupoj. Ĉiuj inĝenieroj de Tinder nun havas la scion kaj sperton por paki ujojn kaj disfaldi aplikaĵojn al Kubernetes.

Kiam la bezono de plia kapablo ekestis sur la malnova infrastrukturo, ni devis atendi kelkajn minutojn por lanĉi novajn EC2-instancojn. Nun ujoj ekfunkcias kaj komencas prilabori trafikon ene de sekundoj anstataŭ minutoj. Planado de multoblaj ujoj sur ununura EC2-instanco ankaŭ disponigas plibonigitan horizontalan koncentriĝon. Kiel rezulto, ni antaŭvidas gravan redukton de EC2019-kostoj en 2 kompare kun la pasinta jaro.

La migrado daŭris preskaŭ du jarojn, sed ni kompletigis ĝin en marto 2019. Nuntempe, la platformo Tinder funkcias ekskluzive sur Kubernetes-areo konsistanta el 200 servoj, 1000 nodoj, 15 podoj kaj 000 kurantaj ujoj. Infrastrukturo ne plu estas la sola domajno de operaciaj teamoj. Ĉiuj niaj inĝenieroj dividas ĉi tiun respondecon kaj kontrolas la procezon konstrui kaj disfaldi siajn aplikaĵojn uzante nur kodon.

PS de tradukisto

Legu ankaŭ serion da artikoloj en nia blogo:

fonto: www.habr.com

Aldoni komenton