Tinder oergong nei Kubernetes

Noat. transl.: Meiwurkers fan 'e wrâldferneamde Tinder-tsjinst dielde koartlyn wat technyske details oer it migrearjen fan har ynfrastruktuer nei Kubernetes. It proses duorre hast twa jier en resultearre yn de lansearring fan in hiel grutskalige platfoarm op K8s, besteande út 200 tsjinsten hosted op 48 tûzen konteners. Hokker nijsgjirrige swierrichheden kamen de Tinder-yngenieurs tsjin en hokker resultaten kamen se ta? Lês dizze oersetting.

Tinder oergong nei Kubernetes

Wêrom?

Hast twa jier lyn besleat Tinder har platfoarm te ferpleatsen nei Kubernetes. Kubernetes soe tastean it Tinder team te containerize en ferhúzje nei produksje mei minimale ynspanning troch ûnferoarlike ynset (ûnferoarlike ynset). Yn dit gefal soe de gearstalling fan applikaasjes, har ynset, en de ynfrastruktuer sels unyk wurde definieare troch koade.

Wy sochten ek nei in oplossing foar it probleem fan skalberens en stabiliteit. Doe't skaalfergrutting kritysk waard, moasten wy faaks ferskate minuten wachtsje foar nije EC2-eksimplaren om te draaien. It idee om konteners te lansearjen en ferkear te begjinnen yn sekonden ynstee fan minuten waard foar ús heul oantreklik.

It proses blykte dreech te wêzen. Tidens ús migraasje yn it begjin fan 2019 berikte it Kubernetes-kluster krityske massa en begon wy ferskate problemen tsjin te kommen fanwege ferkearsvolume, klustergrutte en DNS. Underweis hawwe wy in protte nijsgjirrige problemen oplost yn ferbân mei it migrearjen fan 200 tsjinsten en it behâld fan in Kubernetes-kluster besteande út 1000 knopen, 15000 pods en 48000 rinnende konteners.

Hoe?

Sûnt jannewaris 2018 hawwe wy ferskate stadia fan migraasje trochmakke. Wy begûnen mei it kontenerisearjen fan al ús tsjinsten en ynsette se nei Kubernetes testwolkomjouwings. Begjin oktober begûnen wy metodysk te migrearjen fan alle besteande tsjinsten nei Kubernetes. Tsjin maart fan it folgjende jier hawwe wy de migraasje foltôge en no rint it Tinder-platfoarm eksklusyf op Kubernetes.

Bouwe ôfbyldings foar Kubernetes

Wy hawwe mear dan 30 boarnekoade-repositories foar mikrotsjinsten dy't rinne op in Kubernetes-kluster. De koade yn dizze repositories is skreaun yn ferskate talen (bygelyks Node.js, Java, Scala, Go) mei meardere runtime-omjouwings foar deselde taal.

It bousysteem is ûntworpen om in folslein oanpasbere "bouwkontekst" te leverjen foar elke mikrotsjinst. It bestiet normaal út in Dockerfile en in list mei shell-kommando's. Har ynhâld is folslein oanpasber, en tagelyk binne al dizze bouwkonteksten skreaun neffens in standerdisearre formaat. Standerdisearring fan bouwkonteksten lit ien inkeld bouwsysteem alle mikrotsjinsten behannelje.

Tinder oergong nei Kubernetes
figuer 1-1. Standertisearre bouproses fia Builder-container

Om maksimale gearhing tusken runtimes te berikken (runtime-omjouwings) itselde bouproses wurdt brûkt by ûntwikkeling en testen. Wy stiene foar in heul ynteressante útdaging: wy moasten in manier ûntwikkelje om konsistinsje fan 'e bouwomjouwing oer it heule platfoarm te garandearjen. Om dit te berikken, wurde alle assemblageprosessen útfierd yn in spesjale kontener. Bouwer.

Syn kontener-ymplemintaasje easke avansearre Docker-techniken. Bouwer erft de lokale brûkers-ID en geheimen (lykas SSH-kaai, AWS-bewizen, ensfh.) nedich om tagong te krijen ta privee Tinder-repositories. It monteart lokale mappen mei boarnen om natuerlik bouwen fan artefakten op te slaan. Dizze oanpak ferbettert prestaasjes, om't it de needsaak elimineert om build-artefakten te kopiearjen tusken de Builder-kontener en de host. Opsleine build-artefakten kinne opnij brûkt wurde sûnder ekstra konfiguraasje.

Foar guon tsjinsten moasten wy in oare kontener oanmeitsje om de kompilaasjeomjouwing yn kaart te bringen nei de runtime-omjouwing (bygelyks genereart de bcrypt-biblioteek fan Node.js platfoarm-spesifike binêre artefakten by ynstallaasje). Tidens it kompilaasjeproses kinne easken ferskille tusken tsjinsten, en de definitive Dockerfile wurdt op 'e flecht kompilearre.

Kubernetes kluster arsjitektuer en migraasje

Cluster grutte behear

Wy besletten om te brûken kube-aws foar automatisearre kluster-ynset op Amazon EC2-eksimplaren. Oan it begjin wurke alles yn ien mienskiplike pool fan knopen. Wy realisearre fluch de needsaak om wurklasten te skieden troch grutte en eksimplaartype om effisjinter gebrûk fan boarnen te meitsjen. De logika wie dat it útfieren fan ferskate laden multi-threaded pods bliken te wêzen mear foarsisber yn termen fan prestaasjes as harren co-existinsje mei in grut oantal single-threaded pods.

Uteinlik hawwe wy fêstlein op:

  • m5.4x grut - foar tafersjoch (Prometheus);
  • c5.4x grut - foar Node.js workload (single-threaded workload);
  • c5.2x grut - foar Java en Go (multithreaded workload);
  • c5.4x grut - foar it kontrôlepaniel (3 knopen).

Migraasje

Ien fan 'e tariedende stappen foar it migrearjen fan' e âlde ynfrastruktuer nei Kubernetes wie om de besteande direkte kommunikaasje tusken tsjinsten troch te lieden nei de nije loadbalancers (Elastic Load Balancers (ELB). Se waarden makke op in spesifyk subnet fan in firtuele privee wolk (VPC). Dit subnet wie ferbûn mei in Kubernetes VPC. Dit liet ús modules stadichoan migrearje, sûnder de spesifike folchoarder fan tsjinstôfhinklikens te beskôgjen.

Dizze einpunten waarden makke mei gewichtige sets fan DNS-records dy't CNAME's hiene dy't nei elke nije ELB wiisden. Om oer te skeakeljen, hawwe wy in nije yngong tafoege dy't wiist nei de nije ELB fan 'e Kubernetes-tsjinst mei in gewicht fan 0. Wy sette dan de Time To Live (TTL) fan 'e yngong ynsteld op 0. Hjirnei waarden de âlde en nije gewichten stadichoan oanpast, en úteinlik waard 100% fan de lading stjoerd nei in nije tsjinner. Nei it wikseljen wie foltôge, kaam de TTL-wearde werom nei in mear adekwaat nivo.

De Java-modules dy't wy hiene koenen omgean mei lege TTL DNS, mar de Node-applikaasjes koenen net. Ien fan 'e yngenieurs skreau in diel fan' e ferbiningspoolkoade opnij en ferpakt it yn in manager dy't de swimbaden elke 60 sekonden bywurke. De keazen oanpak wurke heul goed en sûnder merkbere prestaasjesdegradaasje.

Lessen

De grinzen fan it netwurk stof

Yn 'e iere moarn fan 8 jannewaris 2019 crashte it Tinder-platfoarm ûnferwachts. Yn reaksje op in net-relatearre ferheging fan platfoarmlatinsje earder dy moarns, naam it oantal pods en knopen yn it kluster ta. Dit feroarsake de ARP-cache op al ús knooppunten útput.

D'r binne trije Linux-opsjes yn ferbân mei de ARP-cache:

Tinder oergong nei Kubernetes
(boarne)

gc_thresh3 - dit is in hurde limyt. It uterlik fan "buortafel oerstreaming" yngongen yn it log betsjutte dat sels nei syngroane garbage collection (GC), der wie net genôch romte yn de ARP cache te bewarjen de oanbuorjende yngong. Yn dit gefal hat de kernel it pakket gewoanwei folslein fuortslein.

Wy brûke Flannel as netwurkstof yn Kubernetes. Pakketten wurde oerdroegen oer VXLAN. VXLAN is in L2 tunnel ferhege boppe op in L3 netwurk. De technology brûkt MAC-in-UDP (MAC Address-in-User Datagram Protocol) ynkapseling en jout útwreiding fan Laach 2 netwurk segminten. It ferfierprotokol op it fysike datasintrumnetwurk is IP plus UDP.

Tinder oergong nei Kubernetes
Ofbylding 2-1. Flanel diagram (boarne)

Tinder oergong nei Kubernetes
figuer 2-2. VXLAN pakket (boarne)

Elke Kubernetes-wurkerknooppunt jout in firtuele adresromte ta mei in /24-masker fan in grutter /9-blok. Foar elke node is dit betsjut ien yngong yn 'e routing tabel, ien yngong yn' e ARP tabel (op de flannel.1 ynterface), en ien yngong yn 'e switching tabel (FDB). Se wurde tafoege de earste kear dat in arbeider knooppunt wurdt begûn of eltse kear in nij knooppunt wurdt ûntdutsen.

Derneist giet node-pod (of pod-pod) kommunikaasje úteinlik troch de ynterface Eth0 (lykas werjûn yn it Flannel-diagram hjirboppe). Dit resultearret yn in ekstra yngong yn 'e ARP-tabel foar elke oerienkommende boarne en bestimminghost.

Yn ús omjouwing is dit soarte fan kommunikaasje hiel gewoan. Foar tsjinstobjekten yn Kubernetes wurdt in ELB makke en Kubernetes registrearret elke node mei de ELB. De ELB wit neat oer pods en de selektearre knooppunt is miskien net de definitive bestimming fan it pakket. It punt is dat as in knooppunt in pakket fan 'e ELB ûntfangt, it beskôget dat it rekken hâldt mei de regels iptables foar in spesifike tsjinst en willekeurich selektearje in pod op in oare knooppunt.

Op it stuit fan it mislearjen wiene d'r 605 knopen yn it kluster. Om de hjirboppe neamde redenen wie dit genôch om de betsjutting te oerwinnen gc_thresh3, dat is de standert. As dit bart, begjinne net allinich pakketten te fallen, mar de heule Flannel firtuele adresromte mei in /24-masker ferdwynt út 'e ARP-tabel. Node-pod-kommunikaasje en DNS-fragen wurde ûnderbrutsen (DNS wurdt host yn in kluster; lês letter yn dit artikel foar details).

Om dit probleem op te lossen, moatte jo de wearden ferheegje gc_thresh1, gc_thresh2 и gc_thresh3 en Flannel opnij starte om de ûntbrekkende netwurken opnij te registrearjen.

Unferwachte DNS-skaalfergrutting

Tidens it migraasjeproses hawwe wy DNS aktyf brûkt om ferkear te behearjen en tsjinsten stadichoan oer te setten fan 'e âlde ynfrastruktuer nei Kubernetes. Wy sette relatyf lege TTL-wearden yn foar assosjearre RecordSets yn Route53. Doe't de âlde ynfrastruktuer op EC2-eksimplaren rûn, wiisde ús resolverkonfiguraasje op Amazon DNS. Wy namen dit as fanselssprekkend en de ynfloed fan 'e lege TTL op ús tsjinsten en Amazon-tsjinsten (lykas DynamoDB) gie foar in grut part ûngemurken.

Doe't wy tsjinsten migrearren nei Kubernetes, fûnen wy dat DNS 250 tûzen oanfragen per sekonde ferwurke. As resultaat begon applikaasjes konstante en serieuze timeouts te belibjen foar DNS-fragen. Dit barde nettsjinsteande ongelooflijke ynspanningen om de DNS-provider te optimalisearjen en te wikseljen nei CoreDNS (dy't by peakload 1000 pods berikte dy't rinne op 120 kearnen).

Wylst wy ûndersiikje nei oare mooglike oarsaken en oplossingen, ûntdutsen wy in artikel, beskriuwing fan racebetingsten dy't ynfloed hawwe op it pakketfilteringskader net filter yn Linux. De timeouts dy't wy observearre, keppele oan in tanimmende teller ynfoegje_mislearre yn de Flannel ynterface wiene oerienstimming mei de befinings fan it artikel.

It probleem komt foar op it poadium fan Boarne- en Destination Network Address Translation (SNAT en DNAT) en folgjende yngong yn 'e tabel ferbine. Ien fan 'e oplossingen dy't yntern besprutsen en foarsteld troch de mienskip wie om de DNS te ferpleatsen nei it wurkknooppunt sels. Yn dit gefal:

  • SNAT is net nedich omdat it ferkear binnen it knooppunt bliuwt. It hoecht net troch de ynterface te wurde stjoerd Eth0.
  • DNAT is net nedich, om't de bestimmings-IP lokaal is foar de knoop, en net in willekeurich selektearre pod neffens de regels iptables.

Wy besletten om te hâlden mei dizze oanpak. CoreDNS waard ynset as in DaemonSet yn Kubernetes en wy ymplementearre in lokale knooppunt DNS-tsjinner yn resolve.conf elke pod troch it ynstellen fan in flagge --cluster-dns kommando's cubelet . Dizze oplossing die bliken effektyf te wêzen foar DNS-timeouts.

Wy seagen lykwols noch pakketferlies en in ferheging fan 'e teller ynfoegje_mislearre yn de Flannel ynterface. Dit gie troch neidat de oplossing waard ymplementearre, om't wy SNAT en / of DNAT allinich foar DNS-ferkear kinne eliminearje. Race betingsten waarden bewarre bleaun foar oare soarten fan ferkear. Gelokkich binne de measte fan ús pakketten TCP, en as der in probleem optreedt, wurde se gewoan opnij ferstjoerd. Wy besykje noch in passende oplossing te finen foar alle soarten ferkear.

Gebrûk fan Envoy foar Better Load Balancing

Doe't wy backend-tsjinsten migrearren nei Kubernetes, begûnen wy te lijen fan unbalansearre lading tusken pods. Wy fûnen dat HTTP Keepalive feroarsake dat ELB-ferbiningen hingje oan 'e earste kleare pods fan elke ynset útrôle. Sa gie it grutste part fan it ferkear troch in lyts persintaazje beskikbere podden. De earste oplossing dy't wy testen wie it ynstellen fan MaxSurge op 100% op nije ynset foar minste gefal senario's. It effekt blykte ûnbelangryk en net belofte te wêzen yn termen fan gruttere ynset.

In oare oplossing dy't wy brûkten wie om boarneoanfragen foar krityske tsjinsten keunstmjittich te ferheegjen. Yn dit gefal soene pods yn 'e buert pleatst mear romte hawwe om te manoeuvreren yn ferliking mei oare swiere pods. It soe op 'e lange termyn ek net wurkje, om't it in fergriemerij fan middels wêze soe. Derneist wiene ús Node-applikaasjes single-threaded en koenen sadwaande mar ien kearn brûke. De ienige echte oplossing wie it brûken fan bettere load balancing.

Wy hawwe lang woe folslein wurdearje envoy. De hjoeddeistige situaasje liet ús it op in heul beheinde manier ynsette en direkte resultaten krije. Envoy is in hege prestaasjes, iepen boarne, layer-XNUMX proxy ûntworpen foar grutte SOA-applikaasjes. It kin avansearre load balancing techniken ymplemintearje, ynklusyf automatyske werhellings, circuit breakers, en globale taryf beheining. (Noat. transl.: Jo kinne mear oer dit lêze yn dit artikel oer Istio, dat is basearre op Envoy.)

Wy kamen mei de folgjende konfiguraasje: hawwe in Envoy sidecar foar eltse pod en in inkele rûte, en ferbine it kluster oan de kontener lokaal fia haven. Om potinsjele cascadearing te minimalisearjen en in lytse hitradius te behâlden, brûkten wy in float fan Envoy front-proxy pods, ien per Availability Zone (AZ) foar elke tsjinst. Se fertrouden op in ienfâldige tsjinst ûntdekkingsmotor skreaun troch ien fan ús yngenieurs dy't gewoan in list mei pods yn elke AZ foar in opjûne tsjinst weromjûn.

Tsjinstfront-Envoys brûkten dan dit tsjinstûntdekkingmeganisme mei ien streamop kluster en rûte. Wy sette adekwate time-outs, ferhege alle circuit breaker ynstellings, en tafoege minimale opnij konfiguraasje te helpen mei inkele mislearrings en soargje soepele ynset. Wy pleatst in TCP ELB foar elk fan dizze tsjinst front-Envoys. Sels as de keepalive fan ús haadproxy-laach fêst siet op guon Envoy-pods, wiene se noch yn steat om de lading folle better te behanneljen en waarden konfigureare om te balansearjen fia least_request yn 'e efterkant.

Foar ynset brûkten wy de preStop-haak op sawol applikaasje-pods as sidecar-pods. De heak feroarsake in flater by it kontrolearjen fan de status fan it admin-einpunt dat op 'e sidecar-kontener leit en gie in skoft yn 'e sliep om aktive ferbiningen te beëinigjen.

Ien fan 'e redenen dat wy sa fluch koenen ferpleatse is troch de detaillearre metriken dy't wy maklik yntegrearje kinne yn in typyske Prometheus-ynstallaasje. Dit liet ús sjen wat der barde, wylst wy konfiguraasjeparameters oanpasse en ferkear ferdielden.

De resultaten wiene direkt en dúdlik. Wy begûnen mei de meast unbalansearre tsjinsten, en op it stuit wurket it foar de 12 wichtichste tsjinsten yn it kluster. Dit jier plannen wy in oergong nei in folsleine tsjinstmesh mei mear avansearre tsjinstûntdekking, circuit breaking, outlier-deteksje, taryfbeheining en tracing.

Tinder oergong nei Kubernetes
figuer 3-1. CPU-konverginsje fan ien tsjinst by de oergong nei Envoy

Tinder oergong nei Kubernetes

Tinder oergong nei Kubernetes

Einresultaat

Troch dizze ûnderfining en oanfoljend ûndersyk hawwe wy in sterk ynfrastruktuerteam boud mei sterke feardigens yn it ûntwerpen, ynsetten en operearje fan grutte Kubernetes-klusters. Alle Tinder-yngenieurs hawwe no de kennis en ûnderfining om konteners te ferpakken en applikaasjes yn te setten nei Kubernetes.

Doe't de needsaak foar ekstra kapasiteit ûntstie op 'e âlde ynfrastruktuer, moasten wy ferskate minuten wachtsje foar nije EC2-eksimplaren om te lansearjen. No begjinne konteners te rinnen en begjinne ferkear binnen sekonden te ferwurkjen ynstee fan minuten. It plannen fan meardere konteners op ien EC2-eksimplaar leveret ek ferbettere horizontale konsintraasje. As resultaat foarsizze wy in signifikante reduksje yn EC2019-kosten yn 2 yn ferliking mei ferline jier.

De migraasje duorre hast twa jier, mar wy hawwe it yn maart 2019 foltôge. Op it stuit rint it Tinder-platfoarm eksklusyf op in Kubernetes-kluster besteande út 200 tsjinsten, 1000 knopen, 15 pods en 000 rinnende konteners. Ynfrastruktuer is net langer it ienige domein fan operaasjeteams. Al ús yngenieurs diele dizze ferantwurdlikens en kontrolearje it proses fan it bouwen en ynsetten fan har applikaasjes allinich mei koade.

PS fan oersetter

Lês ek in searje artikels op ús blog:

Boarne: www.habr.com

Add a comment