Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Aloha, mense! My naam is Oleg Anastasyev, ek werk by Odnoklassniki in die Platform-span. En buiten my werk daar baie hardeware in Odnoklassniki. Ons het vier datasentrums met ongeveer 500 rakke met meer as 8 duisend bedieners. Op 'n sekere punt het ons besef dat die bekendstelling van 'n nuwe bestuurstelsel ons in staat sal stel om toerusting meer doeltreffend te laai, toegangsbestuur te vergemaklik, die (her)verspreiding van rekenaarhulpbronne te outomatiseer, die bekendstelling van nuwe dienste te bespoedig en reaksies te bespoedig. tot grootskaalse ongelukke.

Wat het daarvan gekom?

Behalwe vir my en 'n klomp hardeware, is daar ook mense wat met hierdie hardeware werk: ingenieurs wat direk in datasentrums geleë is; netwerkers wat netwerksagteware opstel; administrateurs, of SRE's, wat infrastruktuurveerkragtigheid verskaf; en ontwikkelingspanne, elkeen van hulle is verantwoordelik vir 'n deel van die portaal se funksies. Die sagteware wat hulle skep werk iets soos volg:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Gebruikersversoeke word beide op die voorkant van die hoofportaal ontvang www.ok.ru, en op ander, byvoorbeeld op die musiek API-fronte. Om die besigheidslogika te verwerk, bel hulle die toepassingsbediener, wat, wanneer die versoek verwerk word, die nodige gespesialiseerde mikrodienste oproep - eengrafiek (grafiek van sosiale verbindings), gebruikerkas (kas van gebruikersprofiele), ens.

Elkeen van hierdie dienste word op baie masjiene ontplooi, en elkeen van hulle het verantwoordelike ontwikkelaars wat verantwoordelik is vir die funksionering van die modules, hul werking en tegnologiese ontwikkeling. Al hierdie dienste loop op hardeware bedieners, en tot onlangs het ons presies een taak per bediener geloods, dit wil sê dit was gespesialiseer vir 'n spesifieke taak.

Hoekom is dit? Hierdie benadering het verskeie voordele ingehou:

  • Verlig massabestuur. Kom ons sê 'n taak vereis 'n paar biblioteke, sommige instellings. En dan word die bediener aan presies een spesifieke groep toegewys, die cfengine-beleid vir hierdie groep word beskryf (of dit is reeds beskryf), en hierdie konfigurasie word sentraal en outomaties na alle bedieners in hierdie groep uitgerol.
  • Vereenvoudig diagnostiek. Kom ons sê jy kyk na die verhoogde las op die sentrale verwerker en besef dat hierdie las slegs gegenereer kan word deur die taak wat op hierdie hardeware verwerker loop. Die soektog na iemand om te blameer eindig baie vinnig.
  • Vereenvoudig monitering. As iets fout is met die bediener, rapporteer die monitor dit, en jy weet presies wie die skuld kry.

Aan 'n diens wat uit verskeie replikas bestaan, word verskeie bedieners toegeken - een vir elkeen. Dan word die rekenaarhulpbron vir die diens baie eenvoudig toegewys: die aantal bedieners wat die diens het, die maksimum hoeveelheid hulpbronne wat dit kan verbruik. "Maklik" hier beteken nie dat dit maklik is om te gebruik nie, maar in die sin dat hulpbrontoewysing met die hand gedoen word.

Hierdie benadering het ons ook toegelaat om te doen gespesialiseerde ysterkonfigurasies vir 'n taak wat op hierdie bediener loop. As die taak groot hoeveelhede data stoor, gebruik ons ​​'n 4U-bediener met 'n onderstel met 38 skywe. As die taak suiwer rekenaarmatig is, kan ons 'n goedkoper 1U-bediener koop. Dit is rekenkundig doeltreffend. Hierdie benadering stel ons onder meer in staat om vier keer minder masjiene te gebruik met 'n las wat vergelykbaar is met een vriendelike sosiale netwerk.

Sulke doeltreffendheid in die gebruik van rekenaarhulpbronne behoort ook ekonomiese doeltreffendheid te verseker, as ons uitgaan van die uitgangspunt dat die duurste ding bedieners is. Vir 'n lang tyd was hardeware die duurste, en ons het baie moeite gedoen om die prys van hardeware te verlaag en met fouttoleransie-algoritmes vorendag te kom om hardeware-betroubaarheidvereistes te verminder. En vandag het ons die stadium bereik waarop die prys van die bediener nie meer deurslaggewend is nie. As jy nie die nuutste eksotika oorweeg nie, maak die spesifieke konfigurasie van die bedieners in die rek nie saak nie. Nou het ons nog 'n probleem - die prys van die spasie wat deur die bediener in die datasentrum beset word, dit wil sê die spasie in die rek.

Toe ons besef dat dit die geval was, het ons besluit om te bereken hoe effektief ons die rakke gebruik.
Ons het die prys van die kragtigste bediener van die ekonomies regverdigbares geneem, bereken hoeveel sulke bedieners ons in rakke kon plaas, hoeveel take ons daarop sou hardloop gebaseer op die ou model "een bediener = een taak" en hoeveel sulkes take die toerusting kon benut. Hulle het getel en trane gestort. Dit het geblyk dat ons doeltreffendheid in die gebruik van rakke ongeveer 11% is. Die gevolgtrekking is voor die hand liggend: ons moet die doeltreffendheid van die gebruik van datasentrums verhoog. Dit wil voorkom asof die oplossing voor die hand liggend is: jy moet verskeie take gelyktydig op een bediener uitvoer. Maar dit is waar die moeilikhede begin.

Massa-konfigurasie word dramaties meer ingewikkeld - dit is nou onmoontlik om enige groep aan 'n bediener toe te wys. Na alles, nou kan verskeie take van verskillende opdragte op een bediener geloods word. Daarbenewens kan die konfigurasie botsend wees vir verskillende toepassings. Diagnose word ook meer ingewikkeld: as jy verhoogde SVE- of skyfverbruik op 'n bediener sien, weet jy nie watter taak probleme veroorsaak nie.

Maar die belangrikste ding is dat daar geen isolasie is tussen take wat op dieselfde masjien loop nie. Hier is byvoorbeeld 'n grafiek van die gemiddelde reaksietyd van 'n bedienertaak voor en nadat 'n ander rekenaartoepassing op dieselfde bediener geloods is, wat geensins verband hou met die eerste een nie - die reaksietyd van die hooftaak het aansienlik toegeneem.

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Dit is duidelik dat u take in houers of in virtuele masjiene moet uitvoer. Aangesien byna al ons take onder een bedryfstelsel (Linux) loop of daarvoor aangepas is, hoef ons nie baie verskillende bedryfstelsels te ondersteun nie. Gevolglik is virtualisering nie nodig nie; as gevolg van die bykomende bokoste, sal dit minder doeltreffend wees as houerisering.

As 'n implementering van houers om take direk op bedieners uit te voer, is Docker 'n goeie kandidaat: lêerstelselbeelde los probleme met botsende konfigurasies goed op. Die feit dat beelde uit verskeie lae saamgestel kan word, stel ons in staat om die hoeveelheid data wat benodig word om dit op die infrastruktuur te ontplooi aansienlik te verminder, deur gemeenskaplike dele in aparte basislae te skei. Dan sal die basiese (en mees lywige) lae redelik vinnig deur die hele infrastruktuur gekas word, en om baie verskillende tipes toepassings en weergawes te lewer, sal slegs klein lae oorgedra moet word.

Boonop gee 'n klaargemaakte register en beeldmerking in Docker ons klaargemaakte primitiewe vir weergawe en aflewering van kode na produksie.

Docker, soos enige ander soortgelyke tegnologie, bied ons 'n mate van houer-isolasie uit die boks. Byvoorbeeld, geheue-isolasie - elke houer kry 'n beperking op die gebruik van masjiengeheue, waarby dit nie sal verbruik nie. U kan ook houers isoleer op grond van SVE-gebruik. Vir ons was standaard isolasie egter nie genoeg nie. Maar meer daaroor hieronder.

Om houers direk op bedieners te laat loop, is slegs deel van die probleem. Die ander deel hou verband met die aanbieding van houers op bedieners. Jy moet verstaan ​​watter houer op watter bediener geplaas kan word. Dit is nie so 'n maklike taak nie, want houers moet so dig as moontlik op bedieners geplaas word sonder om hul spoed te verminder. Sulke plasing kan ook moeilik wees vanuit 'n fouttoleransie-oogpunt. Dikwels wil ons replikas van dieselfde diens in verskillende rakke of selfs in verskillende kamers van die datasentrum plaas, sodat as 'n rak of kamer misluk, ons nie dadelik al die diensreplikas verloor nie.

Om houers handmatig te versprei is nie 'n opsie as jy 8 duisend bedieners en 8-16 duisend houers het nie.

Boonop wou ons ontwikkelaars meer onafhanklikheid gee in hulpbrontoewysing sodat hulle self hul dienste in produksie kan aanbied, sonder die hulp van 'n administrateur. Terselfdertyd wou ons beheer behou sodat een of ander geringe diens nie al die hulpbronne van ons datasentrums sal verbruik nie.

Dit is duidelik dat ons 'n beheerlaag nodig het wat dit outomaties sal doen.

Ons het dus by 'n eenvoudige en verstaanbare prentjie gekom wat alle argitekte aanbid: drie vierkante.

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

een-wolk-meesters is 'n failover-kluster wat verantwoordelik is vir wolkorkestrasie. Die ontwikkelaar stuur 'n manifes aan die meester, wat al die inligting bevat wat nodig is om die diens aan te bied. Op grond daarvan gee die meester opdragte aan geselekteerde volgelinge (masjiene wat ontwerp is om houers uit te voer). Die volgelinge het ons agent, wat die opdrag ontvang, sy opdragte aan Docker uitreik, en Docker konfigureer die linux-kern om die ooreenstemmende houer te begin. Benewens die uitvoering van opdragte, rapporteer die agent voortdurend aan die meester oor veranderinge in die toestand van beide die minion-masjien en die houers wat daarop loop.

Hulpbrontoekenning

Kom ons kyk nou na die probleem van meer komplekse hulpbrontoewysing vir baie volgelinge.

'n Rekenaarhulpbron in een-wolk is:

  • Die hoeveelheid verwerkerkrag wat deur 'n spesifieke taak verbruik word.
  • Die hoeveelheid geheue beskikbaar vir die taak.
  • Netwerkverkeer. Elkeen van die volgelinge het 'n spesifieke netwerkkoppelvlak met beperkte bandwydte, so dit is onmoontlik om take te versprei sonder om die hoeveelheid data wat hulle oor die netwerk uitstuur in ag te neem.
  • Skywe. Benewens, natuurlik, aan die ruimte vir hierdie take, ken ons ook die tipe skyf toe: HDD of SSD. Skywe kan 'n eindige aantal versoeke per sekonde bedien - IOPS. Daarom, vir take wat meer IOPS genereer as wat 'n enkele skyf kan hanteer, ken ons ook "spindels" toe - dit wil sê skyftoestelle wat uitsluitlik vir die taak gereserveer moet word.

Dan kan ons vir een of ander diens, byvoorbeeld vir gebruikerskas, die verbruikte hulpbronne op hierdie manier opneem: 400 verwerkerkerne, 2,5 TB geheue, 50 Gbit/s verkeer in beide rigtings, 6 TB HDD-spasie geleë op 100 asse. Of in 'n meer bekende vorm soos hierdie:

alloc:
    cpu: 400
    mem: 2500
    lan_in: 50g
    lan_out: 50g
    hdd:100x6T

Gebruikerkasdienshulpbronne verbruik slegs 'n gedeelte van alle beskikbare hulpbronne in die produksie-infrastruktuur. Daarom wil ek seker maak dat die gebruikerkas skielik, as gevolg van 'n operateurfout of nie, nie meer hulpbronne verbruik as wat daaraan toegewys is nie. Dit wil sê, ons moet hulpbronne beperk. Maar waaraan kan ons die kwota bind?

Kom ons keer terug na ons baie vereenvoudigde diagram van die interaksie van komponente en teken dit oor met meer besonderhede - soos volg:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Wat jou oog vang:

  • Die webfrontend en musiek gebruik geïsoleerde groepe van dieselfde toepassingsbediener.
  • Ons kan die logiese lae waartoe hierdie groepe behoort, onderskei: fronte, kas, databerging en bestuurslaag.
  • Die frontend is heterogeen; dit bestaan ​​uit verskillende funksionele subsisteme.
  • Kasgeheue kan ook oor die substelsel waarvan die data hulle kas gestrooi word.

Kom ons teken die prentjie weer:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Bah! Ja, ons sien 'n hiërargie! Dit beteken dat jy hulpbronne in groter stukke kan versprei: ken 'n verantwoordelike ontwikkelaar toe aan 'n nodus van hierdie hiërargie wat ooreenstem met die funksionele substelsel (soos "musiek" in die prentjie), en heg 'n kwota aan dieselfde vlak van die hiërargie. Hierdie hiërargie stel ons ook in staat om dienste meer buigsaam te organiseer vir gemak van bestuur. Byvoorbeeld, ons verdeel die hele web, aangesien dit 'n baie groot groep bedieners is, in verskeie kleiner groepe, wat in die prentjie as groep1, groep2 getoon word.

Deur die ekstra lyne te verwyder, kan ons elke nodus van ons prentjie in 'n platter vorm skryf: groep1.web.front, api.musiek.front, gebruiker-kas.kas.

Dit is hoe ons by die konsep van “hiërargiese tou” uitkom. Dit het 'n naam soos "groep1.web.front". 'n Kwota vir hulpbronne en gebruikersregte word daaraan toegeken. Ons sal die persoon van DevOps die regte gee om 'n diens na die tou te stuur, en so 'n werknemer kan iets in die tou begin, en die persoon van OpsDev sal admin regte hê, en nou kan hy die tou bestuur, mense daar toewys, gee hierdie mense regte, ens. Dienste wat op hierdie tou loop, sal binne die tou se kwota loop. As die tou se rekenaarkwota nie genoeg is om alle dienste gelyktydig uit te voer nie, sal hulle opeenvolgend uitgevoer word, en sodoende die tou self vorm.

Kom ons kyk na die dienste van nader. 'n Diens het 'n volledig gekwalifiseerde naam, wat altyd die naam van die tou insluit. Dan sal die voorste webdiens die naam hê ok-web.groep1.web.front. En die toepassingsbedienerdiens waartoe dit toegang kry, sal genoem word ok-app.groep1.web.front. Elke diens het 'n manifes, wat al die nodige inligting spesifiseer vir plasing op spesifieke masjiene: hoeveel hulpbronne hierdie taak verbruik, watter konfigurasie daarvoor nodig is, hoeveel replikas daar moet wees, eienskappe vir die hantering van mislukkings van hierdie diens. En nadat die diens direk op die masjiene geplaas is, verskyn die gevalle daarvan. Hulle word ook ondubbelsinnig genoem - as die instansienommer en diensnaam: 1.ok-web.group1.web.front, 2.ok-web.group1.web.front, …

Dit is baie gerieflik: deur net na die naam van die lopende houer te kyk, kan ons dadelik baie uitvind.

Kom ons kyk nou van nader na wat hierdie gevalle werklik verrig: take.

Taakisolasieklasse

Alle take in OK (en waarskynlik oral) kan in groepe verdeel word:

  • Kort Latency-take - prod. Vir sulke take en dienste is die reaksievertraging (latency) baie belangrik, hoe vinnig elkeen van die versoeke deur die stelsel verwerk sal word. Voorbeelde van take: webfronte, caches, toepassingsbedieners, OLTP-berging, ens.
  • Berekeningsprobleme - bondel. Hier is die verwerkingspoed van elke spesifieke versoek nie belangrik nie. Vir hulle is dit belangrik hoeveel berekeninge hierdie taak in 'n sekere (lang) tydperk (deurset) sal doen. Dit sal enige take van MapReduce, Hadoop, masjienleer, statistiek wees.
  • Agtergrond take - ledig. Vir sulke take is nie latensie of deurset baie belangrik nie. Dit sluit verskeie toetse, migrasies, herberekeninge en omskakeling van data van een formaat na 'n ander in. Aan die een kant is hulle soortgelyk aan berekende, aan die ander kant maak dit nie regtig vir ons saak hoe vinnig hulle voltooi word nie.

Kom ons kyk hoe sulke take hulpbronne verbruik, byvoorbeeld die sentrale verwerker.

Kort vertraging take. So 'n taak sal 'n SVE-verbruikspatroon soortgelyk aan hierdie hê:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

'n Versoek van die gebruiker word vir verwerking ontvang, die taak begin om alle beskikbare SVE-kerne te gebruik, verwerk dit, gee 'n antwoord terug, wag vir die volgende versoek en stop. Die volgende versoek het gekom - ons het weer alles gekies wat daar was, dit bereken, en wag vir die volgende een.

Om die minimum latency vir so 'n taak te waarborg, moet ons die maksimum hulpbronne neem wat dit verbruik en die vereiste aantal kerns op die minion (die masjien wat die taak sal uitvoer) reserveer. Dan sal die besprekingsformule vir ons probleem soos volg wees:

alloc: cpu = 4 (max)

en as ons 'n minion-masjien met 16 kerne het, dan kan presies vier sulke take daarop geplaas word. Ons let veral daarop dat die gemiddelde verwerkerverbruik van sulke take dikwels baie laag is - wat voor die hand liggend is, aangesien 'n beduidende deel van die tyd die taak op 'n versoek wag en niks doen nie.

Berekening take. Hul patroon sal effens anders wees:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Die gemiddelde SVE-hulpbronverbruik vir sulke take is redelik hoog. Dikwels wil ons hê dat 'n berekeningstaak binne 'n sekere tyd voltooi moet word, daarom moet ons die minimum aantal verwerkers wat dit benodig reserveer sodat die hele berekening binne 'n aanvaarbare tyd voltooi word. Die besprekingsformule sal soos volg lyk:

alloc: cpu = [1,*)

"Plaas dit asseblief op 'n minion waar daar ten minste een vrye kern is, en dan sal soveel as wat daar is, dit alles verslind."

Hier is die doeltreffendheid van gebruik reeds baie beter as op take met 'n kort vertraging. Maar die wins sal baie groter wees as jy albei soorte take op een minion-masjien kombineer en sy hulpbronne onderweg versprei. Wanneer 'n taak met 'n kort vertraging 'n verwerker benodig, ontvang dit dit onmiddellik, en wanneer die hulpbronne nie meer nodig is nie, word dit na die berekeningstaak oorgedra, dit wil sê iets soos hierdie:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Maar hoe om dit te doen?

Kom ons kyk eers na prod en sy toewysing: cpu = 4. Ons moet vier kerns reserveer. In Docker run kan dit op twee maniere gedoen word:

  • Gebruik die opsie --cpuset=1-4, d.w.s. ken vier spesifieke kerne op die masjien aan die taak toe.
  • maak gebruik van --cpuquota=400_000 --cpuperiod=100_000, ken 'n kwota vir verwerkertyd toe, d.w.s. dui aan dat elke 100 ms intydse tyd die taak nie meer as 400 ms verwerkertyd verbruik nie. Dieselfde vier kerne word verkry.

Maar watter van hierdie metodes is geskik?

cpuset lyk nogal aantreklik. Die taak het vier toegewyde kerns, wat beteken dat verwerkerkas so doeltreffend moontlik sal werk. Dit het ook 'n nadeel: ons sal die taak moet aanpak om berekeninge oor die afgelaaide kerne van die masjien te versprei in plaas van die bedryfstelsel, en dit is 'n taamlik nie-triviale taak, veral as ons probeer om bondeltake op so 'n masjien. Toetse het getoon dat die opsie met 'n kwota hier beter geskik is: op hierdie manier het die bedryfstelsel meer vryheid om die kern te kies om die taak op die huidige oomblik uit te voer en verwerkertyd word meer doeltreffend versprei.

Kom ons vind uit hoe om besprekings in Docker te maak gebaseer op die minimum aantal kerns. Die kwota vir bondeltake is nie meer van toepassing nie, want dit is nie nodig om die maksimum te beperk nie, dit is genoeg om net die minimum te waarborg. En hier pas die opsie goed docker run --cpushares.

Ons het ooreengekom dat as 'n bondel 'n waarborg vir ten minste een kern vereis, dan dui ons aan --cpushares=1024, en as daar ten minste twee kerne is, dan dui ons aan --cpushares=2048. SVE-aandele meng op geen manier in met die verspreiding van verwerkertyd solank daar genoeg daarvan is nie. Dus, as prod nie tans al sy vier kerns gebruik nie, is daar niks wat bondeltake beperk nie, en hulle kan bykomende verwerkertyd gebruik. Maar in 'n situasie waar daar 'n tekort aan verwerkers is, as prod al vier sy kerns verbruik het en sy kwota bereik het, sal die oorblywende verwerkertyd proporsioneel tot cpushares verdeel word, dit wil sê in 'n situasie van drie gratis kerns, sal een wees gegee aan 'n taak met 1024 cpushares, en die oorblywende twee sal gegee word aan 'n taak met 2048 cpushares.

Maar die gebruik van kwota en aandele is nie genoeg nie. Ons moet seker maak dat 'n taak met 'n kort vertraging prioriteit bo 'n bondeltaak kry wanneer verwerkertyd toegewys word. Sonder sulke prioritisering sal die bondeltaak al die verwerkertyd in beslag neem op die oomblik wanneer dit deur die prod benodig word. Daar is geen houerprioritiseringsopsies in Docker run nie, maar Linux CPU-skeduleerderbeleide kom handig te pas. Jy kan in detail oor hulle lees hier, en binne die raamwerk van hierdie artikel gaan ons kortliks deur hulle:

  • SCHED_OTHER
    By verstek ontvang alle normale gebruikersprosesse op 'n Linux-masjien.
  • SCHED_BATCH
    Ontwerp vir hulpbron-intensiewe prosesse. Wanneer 'n taak op 'n verwerker geplaas word, word 'n sogenaamde aktiveringsboete ingestel: so 'n taak is minder geneig om verwerkerhulpbronne te ontvang as dit tans deur 'n taak met SCHED_OTHER gebruik word
  • SCHED_IDLE
    'n Agtergrondproses met 'n baie lae prioriteit, selfs laer as lekker -19. Ons gebruik ons ​​oopbron-biblioteek een-nio, om die nodige beleid te stel wanneer die houer begin word deur te bel

one.nio.os.Proc.sched_setscheduler( pid, Proc.SCHED_IDLE )

Maar selfs as jy nie in Java programmeer nie, kan dieselfde ding gedoen word met die chrt-opdrag:

chrt -i 0 $pid

Kom ons som al ons isolasievlakke in een tabel op vir duidelikheid:

Isolasie klas
Alloc voorbeeld
Docker run opsies
sched_setscheduler chrt*

Prod
cpu = 4
--cpuquota=400000 --cpuperiod=100000
SCHED_OTHER

Batch
SVE = [1, *)
--cpushares=1024
SCHED_BATCH

idle
Cpu= [2, *)
--cpushares=2048
SCHED_IDLE

*As jy chrt van binne 'n houer doen, sal jy dalk die sys_nice-vermoë nodig hê, want by verstek verwyder Docker hierdie vermoë wanneer die houer begin word.

Maar take verbruik nie net die verwerker nie, maar ook verkeer, wat die vertraging van 'n netwerktaak selfs meer beïnvloed as die verkeerde toewysing van verwerkerhulpbronne. Daarom wil ons natuurlik presies dieselfde prentjie vir verkeer kry. Dit wil sê, wanneer 'n prod-taak 'n paar pakkies na die netwerk stuur, beperk ons ​​die maksimum spoed (formule toewys: lan=[*,500mbps) ), waarmee prod dit kan doen. En vir bondel waarborg ons slegs die minimum deurset, maar beperk nie die maksimum (formule toewys: lan=[10Mbps,*) ) In hierdie geval moet prod-verkeer voorkeur bo bondeltake kry.
Hier het Docker geen primitiewe wat ons kan gebruik nie. Maar dit kom tot ons hulp Linux Verkeersbeheer. Ons kon met behulp van dissipline die gewenste resultaat behaal Hiërargiese billike dienskromme. Met die hulp daarvan onderskei ons twee klasse verkeer: hoë-prioriteit prod en lae-prioriteit bondel/ledig. As gevolg hiervan is die opstelling vir uitgaande verkeer soos volg:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

hier is 1:0 die "root qdisc" van die hsfc-dissipline; 1:1 - hsfc kinderklas met 'n totale bandwydtelimiet van 8 Gbit/s, waaronder die kinderklasse van alle houers geplaas word; 1:2 - die hsfc-kinderklas is algemeen vir alle bondel- en ledige take met 'n "dinamiese" limiet, wat hieronder bespreek word. Die oorblywende hsfc-kinderklasse is toegewyde klasse vir prodhouers wat tans gebruik word met limiete wat ooreenstem met hul manifeste - 450 en 400 Mbit/s. Aan elke hsfc-klas word 'n qdisc-tou fq of fq_codel toegeken, afhangende van die Linux-kernweergawe, om pakkieverlies tydens verkeersuitbarstings te vermy.

Tipies dien tc dissiplines om slegs uitgaande verkeer te prioritiseer. Maar ons wil ook inkomende verkeer prioritiseer - een of ander groeptaak ​​kan immers maklik die hele inkomende kanaal kies, en ontvang byvoorbeeld 'n groot bondel insetdata vir map&reduce. Hiervoor gebruik ons ​​die module ifb, wat 'n ifbX virtuele koppelvlak vir elke netwerkkoppelvlak skep en inkomende verkeer van die koppelvlak na uitgaande verkeer op ifbX herlei. Verder, vir ifbX, werk al dieselfde dissiplines om uitgaande verkeer te beheer, waarvoor die hsfc-konfigurasie baie soortgelyk sal wees:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Tydens die eksperimente het ons uitgevind dat hsfc die beste resultate toon wanneer die 1:2-klas van nie-prioriteit bondel/ledige verkeer op minion-masjiene beperk word tot nie meer as 'n sekere vrye baan nie. Andersins het nie-prioriteitverkeer te veel impak op die vertraging van prod-take. miniond bepaal die huidige hoeveelheid vrye bandwydte elke sekonde, en meet die gemiddelde verkeersverbruik van alle prod-take van 'n gegewe minion Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki en dit van die netwerkkoppelvlakbandwydte af te trek Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki met 'n klein marge, d.w.s.

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Bande word onafhanklik gedefinieer vir inkomende en uitgaande verkeer. En volgens die nuwe waardes herkonfigureer miniond die nie-prioriteit klaslimiet 1:2.

Ons het dus al drie isolasieklasse geïmplementeer: prod, bondel en ledig. Hierdie klasse beïnvloed grootliks die prestasie-eienskappe van take. Daarom het ons besluit om hierdie eienskap boaan die hiërargie te plaas, sodat wanneer ons na die naam van die hiërargiese tou kyk, dit onmiddellik duidelik sal wees waarmee ons te doen het:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Al ons vriende web и musiek die fronte word dan in die hiërargie onder prod. Byvoorbeeld, onder bondel, laat ons die diens plaas musiek katalogus, wat periodiek 'n katalogus van snitte saamstel uit 'n stel mp3-lêers wat na Odnoklassniki opgelaai is. 'n Voorbeeld van 'n diens onder ledig sal wees musiek transformator, wat die musiekvolumevlak normaliseer.

Met die ekstra reëls wat weer verwyder is, kan ons ons diensname platter skryf deur die taakisolasieklas aan die einde van die volle diensnaam by te voeg: web.front.prod, catalog.music.batch, transformator.musiek.ledig.

En nou, as ons na die naam van die diens kyk, verstaan ​​ons nie net watter funksie dit verrig nie, maar ook die isolasieklas, wat die kritiek daarvan beteken, ens.

Alles is wonderlik, maar daar is een bitter waarheid. Dit is onmoontlik om take wat op een masjien loop, heeltemal te isoleer.

Wat ons daarin geslaag het om te bereik: as bondel intensief verbruik slegs SVE hulpbronne, dan doen die ingeboude Linux SVE skeduleerder sy werk baie goed, en daar is feitlik geen impak op die prod taak nie. Maar as hierdie bondeltaak aktief met geheue begin werk, dan verskyn die wedersydse invloed reeds. Dit gebeur omdat die prod-taak “uitgewas” word uit die verwerker se geheue-kas - gevolglik neem kas-mislukkings toe, en die verwerker verwerk die prod-taak stadiger. So 'n bondeltaak kan die latensie van ons tipiese produkhouer met 10% verhoog.

Om verkeer te isoleer is selfs moeiliker as gevolg van die feit dat moderne netwerkkaarte 'n interne tou pakkies het. As die pakkie van die bondeltaak eerste daar kom, dan sal dit die eerste wees wat oor die kabel versend word, en niks kan daaraan gedoen word nie.

Daarbenewens het ons tot dusver net daarin geslaag om die probleem van die prioritisering van TCP-verkeer op te los: die hsfc-benadering werk nie vir UDP nie. En selfs in die geval van TCP-verkeer, as die bondeltaak baie verkeer genereer, gee dit ook ongeveer 'n 10% toename in die vertraging van die prod-taak.

fout verdraagsaamheid

Een van die doelwitte met die ontwikkeling van een-wolk was om die fouttoleransie van Odnoklassniki te verbeter. Daarom wil ek volgende moontlike scenario's van mislukkings en ongelukke in meer besonderhede oorweeg. Kom ons begin met 'n eenvoudige scenario - 'n houermislukking.

Die houer self kan op verskeie maniere misluk. Dit kan 'n soort eksperiment, fout of fout in die manifes wees, as gevolg waarvan die prod-taak meer hulpbronne begin verbruik as wat in die manifes aangedui word. Ons het 'n saak gehad: 'n ontwikkelaar het een komplekse algoritme geïmplementeer, dit baie keer herwerk, homself oorgedink en so deurmekaar geraak dat die probleem uiteindelik op 'n baie nie-triviale manier geloop het. En aangesien die prod-taak 'n hoër prioriteit het as alle ander op dieselfde volgelinge, het dit alle beskikbare verwerkerhulpbronne begin verbruik. In hierdie situasie het isolasie, of eerder die SVE-tydkwota, die dag gered. As 'n taak 'n kwota toegeken word, sal die taak nie meer verbruik nie. Daarom het bondel- en ander prod-take wat op dieselfde masjien uitgevoer is, niks opgemerk nie.

Die tweede moontlike probleem is die houer wat val. En hier red herbeginbeleide ons, almal ken hulle, Docker self doen goeie werk. Byna alle prod-take het 'n altyd herbegin-beleid. Soms gebruik ons ​​on_failure vir bondeltake of om produkhouers te ontfout.

Wat kan jy doen as 'n hele minion nie beskikbaar is nie?

Dit is duidelik dat, hardloop die houer op 'n ander masjien. Die interessante deel hier is wat gebeur met die IP-adres(se) wat aan die houer toegeken is.

Ons kan houers dieselfde IP-adresse toewys as die minion-masjiene waarop hierdie houers loop. Dan, wanneer die houer op 'n ander masjien geloods word, verander sy IP-adres, en alle kliënte moet verstaan ​​dat die houer geskuif het, en nou moet hulle na 'n ander adres gaan, wat 'n aparte Service Discovery-diens vereis.

Service Discovery is gerieflik. Daar is baie oplossings op die mark met verskillende grade van fouttoleransie vir die organisering van 'n diensregister. Sulke oplossings implementeer dikwels lasbalanseerder-logika, stoor bykomende konfigurasie in die vorm van KV-berging, ens.
Ons wil egter die behoefte vermy om 'n aparte register te implementeer, want dit sou beteken dat 'n kritieke stelsel bekendgestel word wat deur alle dienste in produksie gebruik word. Dit beteken dat dit 'n potensiële punt van mislukking is, en jy moet 'n baie foutverdraagsame oplossing kies of ontwikkel, wat natuurlik baie moeilik, tydrowend en duur is.

En nog 'n groot nadeel: om ons ou infrastruktuur met die nuwe een te laat werk, sal ons absoluut alle take moet herskryf om 'n soort Service Discovery-stelsel te gebruik. Daar is BAIE werk, en op sommige plekke is dit byna onmoontlik wanneer dit kom by laevlak toestelle wat op die OS-kernvlak of direk met die hardeware werk. Implementering van hierdie funksionaliteit deur gebruik te maak van gevestigde oplossingspatrone, soos sykar sou in sommige plekke 'n bykomende las beteken, in ander - 'n komplikasie van operasie en bykomende mislukkingscenario's. Ons wou nie dinge kompliseer nie, en daarom het ons besluit om die gebruik van Service Discovery opsioneel te maak.

In eenwolk volg die IP die houer, dit wil sê elke taakinstansie het sy eie IP-adres. Hierdie adres is “staties”: dit word aan elke geval toegeken wanneer die diens die eerste keer na die wolk gestuur word. As 'n diens 'n ander aantal gevalle gedurende sy lewe gehad het, sal dit op die ou end soveel IP-adresse toegeken word as wat daar maksimum gevalle was.

Gevolglik verander hierdie adresse nie: hulle word een keer toegeken en bly voortbestaan ​​deur die hele lewe van die diens in produksie. IP-adresse volg houers oor die netwerk. As die houer na 'n ander minion oorgedra word, sal die adres dit volg.

Die kartering van 'n diensnaam aan sy lys van IP-adresse verander dus baie selde. As jy weer kyk na die name van die diensgevalle wat ons aan die begin van die artikel genoem het (1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, …), sal ons sien dat hulle lyk soos die FQDN's wat in DNS gebruik word. Dit is reg, om die name van diensgevalle na hul IP-adresse te karteer, gebruik ons ​​die DNS-protokol. Boonop gee hierdie DNS alle gereserveerde IP-adresse van alle houers terug - beide loop en gestop (kom ons sê drie replikas word gebruik, en ons het vyf adresse wat daar gereserveer is - al vyf sal teruggestuur word). Kliënte, nadat hulle hierdie inligting ontvang het, sal probeer om 'n verbinding met al vyf replikas te bewerkstellig - en sodoende vas te stel watter werk. Hierdie opsie vir die bepaling van beskikbaarheid is baie meer betroubaar; dit behels nie DNS of Service Discovery nie, wat beteken dat daar geen moeilike probleme is om op te los om die relevansie van inligting en fouttoleransie van hierdie stelsels te verseker nie. Verder, in kritieke dienste waarvan die werking van die hele portaal afhang, kan ons glad nie DNS gebruik nie, maar eenvoudig IP-adresse in die konfigurasie invoer.

Die implementering van sulke IP-oordrag agter houers kan nie-triviaal wees - en ons sal kyk hoe dit werk met die volgende voorbeeld:

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Kom ons sê die een-wolk meester gee die opdrag aan minion M1 om te hardloop 1.ok-web.groep1.web.front.prod met adres 1.1.1.1. Werk op minion BIRD, wat hierdie adres aan spesiale bedieners adverteer roete weerkaatser. Laasgenoemde het 'n BGP-sessie met die netwerkhardeware, waarin die roete van adres 1.1.1.1 op M1 vertaal word. M1 stuur pakkies binne die houer met Linux. Daar is drie roetereflektorbedieners, aangesien dit 'n baie kritieke deel van die eenwolkinfrastruktuur is - daarsonder sal die netwerk in eenwolk nie werk nie. Ons plaas dit in verskillende rakke, indien moontlik geleë in verskillende kamers van die datasentrum, om die waarskynlikheid te verminder dat al drie gelyktydig misluk.

Kom ons neem nou aan dat die verbinding tussen die eenwolkmeester en die M1 volgeling verlore is. Die eenwolkmeester sal nou optree met die veronderstelling dat M1 heeltemal misluk het. Dit wil sê, dit sal die opdrag aan die M2-minion gee om te begin web.groep1.web.front.prod met dieselfde adres 1.1.1.1. Nou het ons twee botsende roetes op die netwerk vir 1.1.1.1: op M1 en op M2. Om sulke konflikte op te los, gebruik ons ​​die Multi Exit Discriminator, wat in die BGP-aankondiging gespesifiseer word. Dit is 'n nommer wat die gewig van die geadverteerde roete toon. Onder die botsende roetes sal die roete met die laer MED-waarde gekies word. Die een-wolk-meester ondersteun MED as 'n integrale deel van houer IP-adresse. Vir die eerste keer word die adres geskryf met 'n voldoende groot MED = 1 000 000. In die situasie van so 'n noodhoueroordrag verminder die meester die MED, en M2 sal reeds die opdrag ontvang om die adres 1.1.1.1 te adverteer met MED = 999 999. Die instansie wat op M1 loop, sal by bly in hierdie geval is daar geen verband nie, en sy verdere lot interesseer ons min totdat die verbinding met die meester herstel is, wanneer hy gestop sal word soos 'n ou take.

ongelukke

Alle datasentrumbestuurstelsels hanteer altyd geringe foute aanvaarbaar. Houeroorloop is byna oral die norm.

Kom ons kyk hoe ons 'n noodgeval hanteer, soos 'n kragonderbreking in een of meer kamers van 'n datasentrum.

Wat beteken 'n ongeluk vir 'n datasentrumbestuurstelsel? In die eerste plek is dit 'n massiewe eenmalige mislukking van baie masjiene, en die beheerstelsel moet baie houers op dieselfde tyd migreer. Maar as die ramp baie groot is, kan dit gebeur dat alle take nie weer aan ander volgelinge toegewys kan word nie, omdat die hulpbronkapasiteit van die datasentrum onder 100% van die las daal.

Dikwels gaan ongelukke gepaard met mislukking van die beheerlaag. Dit kan gebeur as gevolg van die mislukking van sy toerusting, maar meer dikwels as gevolg van die feit dat ongelukke nie getoets word nie, en die beheerlaag self val as gevolg van die verhoogde las.

Wat kan jy hieraan doen?

Massa-migrasies beteken dat daar 'n groot aantal aktiwiteite, migrasies en ontplooiings in die infrastruktuur plaasvind. Elkeen van die migrasies kan 'n geruime tyd neem wat nodig is om houerbeelde aan handlangers af te lewer en uit te pak, houers te begin en te inisialiseer, ens. Daarom is dit wenslik dat meer belangrike take voor minder belangrike take geloods word.

Kom ons kyk weer na die hiërargie van dienste waarmee ons vertroud is en probeer besluit watter take ons eerste wil uitvoer.

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Dit is natuurlik die prosesse wat direk betrokke is by die verwerking van gebruikersversoeke, dit wil sê prod. Ons dui dit aan met plasing prioriteit — 'n nommer wat aan die tou toegeken kan word. As 'n tou 'n hoër prioriteit het, word sy dienste eerste geplaas.

Op prod gee ons hoër prioriteite, 0; op bondel - 'n bietjie laer, 100; op ledig - selfs laer, 200. Prioriteite word hiërargies toegepas. Alle take laer in die hiërargie sal 'n ooreenstemmende prioriteit hê. As ons wil hê dat caches binne prod voor frontends bekendgestel moet word, dan ken ons prioriteite toe aan kas = 0 en aan voorste subtoue = 1. As ons byvoorbeeld wil hê dat die hoofportaal eers van die voorkant af geloods moet word, en slegs die musiekfront dan, dan kan ons 'n laer prioriteit aan laasgenoemde toeken - 10.

Die volgende probleem is 'n gebrek aan hulpbronne. Dus, 'n groot hoeveelheid toerusting, hele sale van die datasentrum, het misluk, en ons het soveel dienste herbekendgestel dat daar nou nie genoeg hulpbronne vir almal is nie. Jy moet besluit watter take om op te offer om die belangrikste kritieke dienste aan die gang te hou.

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Anders as plasingsprioriteit, kan ons nie alle bondeltake onoordeelkundig opoffer nie; sommige van hulle is belangrik vir die werking van die portaal. Daarom het ons afsonderlik uitgelig voorrangsprioriteit take. Wanneer dit geplaas word, kan 'n hoër-prioriteit-taak 'n laer-prioriteit-taak voorkom, dit wil sê stop, as daar nie meer vrye volgelinge is nie. In hierdie geval sal 'n taak met 'n lae prioriteit waarskynlik ongeplaas bly, dit wil sê daar sal nie meer 'n geskikte volgeling daarvoor wees met genoeg gratis hulpbronne nie.

In ons hiërargie is dit baie eenvoudig om 'n voorrangprioriteit te spesifiseer sodat prod- en bondeltake ledige take voorafgaan of stop, maar nie mekaar nie, deur 'n prioriteit vir ledig gelyk aan 200 te spesifiseer. Net soos in die geval van plasingsprioriteit, ons kan ons hiërargie gebruik om meer komplekse reëls te beskryf. Kom ons dui byvoorbeeld aan dat ons die musiekfunksie opoffer as ons nie genoeg hulpbronne vir die hoofwebportaal het nie, en stel die prioriteit vir die ooreenstemmende nodusse laer: 10.

Hele DC ongelukke

Waarom kan die hele datasentrum misluk? Element. Was 'n goeie post die orkaan het die werk van die datasentrum beïnvloed. Die elemente kan beskou word as hawelose mense wat een keer die optika in die spruitstuk verbrand het, en die datasentrum het heeltemal kontak met ander webwerwe verloor. Die oorsaak van mislukking kan ook 'n menslike faktor wees: die operateur sal so 'n bevel uitreik dat die hele datasentrum sal val. Dit kan gebeur as gevolg van 'n groot fout. In die algemeen is die ineenstorting van datasentrums nie ongewoon nie. Dit gebeur een keer elke paar maande met ons.

En dit is wat ons doen om te verhoed dat iemand #lewendig tweet.

Die eerste strategie is isolasie. Elke een-wolk-instansie is geïsoleer en kan masjiene in slegs een datasentrum bestuur. Dit wil sê, die verlies van 'n wolk as gevolg van foute of verkeerde operateur-opdragte is die verlies van slegs een datasentrum. Ons is gereed hiervoor: ons het 'n oortolligheidsbeleid waarin replikas van die toepassing en data in alle datasentrums geleë is. Ons gebruik foutverdraagsame databasisse en toets gereeld vir mislukkings.
Sedert ons vandag vier datasentrums het, beteken dit vier afsonderlike, heeltemal geïsoleerde gevalle van een-wolk.

Hierdie benadering beskerm nie net teen fisiese mislukking nie, maar kan ook teen operateursfoute beskerm.

Wat anders kan gedoen word met die menslike faktor? Wanneer 'n operateur die wolk 'n vreemde of potensieel gevaarlike opdrag gee, kan hy skielik gevra word om 'n klein probleem op te los om te sien hoe goed hy gedink het. Byvoorbeeld, as dit 'n soort massastop van baie replikas is of net 'n vreemde opdrag - die aantal replikas verminder of die naam van die prent verander, en nie net die weergawenommer in die nuwe manifes nie.

Een-wolk - datasentrumvlak-bedryfstelsel in Odnoklassniki

Resultate van

Kenmerkende kenmerke van een-wolk:

  • Hiërargiese en visuele naamskema vir dienste en houers, waarmee jy baie vinnig kan uitvind wat die taak is, waarmee dit verband hou en hoe dit werk en wie daarvoor verantwoordelik is.
  • Ons pas ons tegniek om produk- en batch- te kombineertake op volgelinge om die doeltreffendheid van masjiendeling te verbeter. In plaas van cpuset gebruik ons ​​CPU-kwotas, aandele, CPU-skeduleerderbeleide en Linux QoS.
  • Dit was nie moontlik om houers wat op dieselfde masjien loop heeltemal te isoleer nie, maar hul wedersydse invloed bly binne 20%.
  • Die organisering van dienste in 'n hiërargie help met outomatiese rampherstel gebruik plasing en voorkoopprioriteite.

Vrae

Hoekom het ons nie 'n klaargemaakte oplossing geneem nie?

  • Verskillende klasse van taakisolasie vereis verskillende logika wanneer dit op volgelinge geplaas word. As prod-take geplaas kan word deur bloot hulpbronne te reserveer, moet bondel- en ledige take geplaas word, wat die werklike benutting van hulpbronne op minion-masjiene dophou.
  • Die behoefte om hulpbronne wat deur take verbruik word, in ag te neem, soos:
    • netwerk bandwydte;
    • tipes en "spindels" van skywe.
  • Die behoefte om die prioriteite van dienste aan te dui tydens noodreaksie, die regte en kwotas van opdragte vir hulpbronne, wat opgelos word deur hiërargiese toue in een-wolk te gebruik.
  • Die behoefte om menslike benaming van houers te hê om reaksietyd op ongelukke en voorvalle te verminder
  • Die onmoontlikheid van 'n eenmalige wydverspreide implementering van Service Discovery; die behoefte om vir 'n lang tyd saam te bestaan ​​met take wat op hardeware-gashere aangebied word - iets wat opgelos word deur "statiese" IP-adresse wat houers volg, en as gevolg daarvan die behoefte aan unieke integrasie met 'n groot netwerkinfrastruktuur.

Al hierdie funksies sal aansienlike wysigings van bestaande oplossings vereis om by ons te pas, en nadat ons die hoeveelheid werk beoordeel het, het ons besef dat ons ons eie oplossing met ongeveer dieselfde arbeidskoste kan ontwikkel. Maar jou oplossing sal baie makliker wees om te bedryf en te ontwikkel - dit bevat nie onnodige abstraksies wat funksionaliteit ondersteun wat ons nie nodig het nie.

Aan die wat die laaste reëls lees, dankie vir julle geduld en aandag!

Bron: will.com

Voeg 'n opmerking