One-cloud - datacenternivo OS yn Odnoklassniki

One-cloud - datacenternivo OS yn Odnoklassniki

Aloha, minsken! Myn namme is Oleg Anastasyev, ik wurkje by Odnoklassniki yn it platfoarmteam. En neist my wurket d'r in protte hardware yn Odnoklassniki. Wy hawwe fjouwer datasintra mei sawat 500 racks mei mear as 8 tûzen servers. Op in bepaald punt realisearren wy dat de ynfiering fan in nij behearsysteem ús soe tastean om apparatuer effisjinter te laden, tagongsbehear te fasilitearjen, de (wer)ferdieling fan kompjûterboarnen te automatisearjen, de lansearring fan nije tsjinsten te fersnellen en antwurden te fersnellen. ta grutskalige ûngelokken.

Wat kaam der fan?

Njonken my en in bulte hardware binne der ek minsken dy't mei dizze hardware wurkje: yngenieurs dy't direkt yn datasintra sitte; netwurkers dy't netwurksoftware ynstelle; behearders, of SRE's, dy't ynfrastruktuerfêstens leverje; en ûntwikkeling teams, elk fan harren is ferantwurdlik foar in part fan it portaal syn funksjes. De software dy't se meitsje wurket sa'n ding:

One-cloud - datacenternivo OS yn Odnoklassniki

Oanfragen fan brûkers wurde ûntfongen sawol op 'e fronten fan it haadportaal www.ok.ru, en op oaren, bygelyks op 'e muzyk API fronten. Om de saaklike logika te ferwurkjen, neame se de applikaasje-tsjinner, dy't by it ferwurkjen fan it fersyk de nedige spesjalisearre mikrotsjinsten neamt - ien-grafyk (grafyk fan sosjale ferbiningen), brûker-cache (cache fan brûkersprofilen), ensfh.

Elk fan dizze tsjinsten wurdt ynset op in protte masines, en elk fan harren hat ferantwurdlik ûntwikkelders ferantwurdlik foar it funksjonearjen fan de modules, harren wurking en technologyske ûntwikkeling. Al dizze tsjinsten rinne op hardware-tsjinners, en oant koartlyn lansearren wy krekt ien taak per tsjinner, d.w.s. it wie spesjalisearre foar in spesifike taak.

Wêrom is dat? Dizze oanpak hie ferskate foardielen:

  • Ferljochte massa behear. Litte wy sizze dat in taak wat biblioteken fereasket, guon ynstellings. En dan de tsjinner wurdt tawiisd oan krekt ien spesifike groep, it cfengine belied foar dizze groep wurdt beskreaun (of it is al beskreaun), en dizze konfiguraasje wurdt sintraal en automatysk rôle út nei alle tsjinners yn dizze groep.
  • ferienfâldige diagnostyk. Litte we sizze dat jo sjogge nei de ferhege lading op 'e sintrale prosessor en realisearje dat dizze lading koe allinnich wurde oanmakke troch de taak dy't rint op dizze hardware prosessor. It sykjen nei immen te skuld einiget hiel fluch.
  • ferienfâldige tafersjoch. As der wat mis is mei de tsjinner, rapportearret de monitor it, en jo witte krekt wa't de skuld hat.

In tsjinst besteande út ferskate replika's wurdt tawiisd ferskate tsjinners - ien foar elk. Dan wurdt de komputerboarne foar de tsjinst heul ienfâldich tawiisd: it oantal servers dat de tsjinst hat, it maksimale bedrach fan boarnen dy't it kin konsumearje. "Easy" betsjut hjir net dat it maklik te brûken is, mar yn 'e sin dat de allocaasje fan boarnen mei de hân wurdt dien.

Dizze oanpak liet ús ek dwaan spesjalisearre izeren konfiguraasjes foar in taak dy't rint op dizze tsjinner. As de taak grutte hoemannichten gegevens bewarret, dan brûke wy in 4U-tsjinner mei in chassis mei 38 skiven. As de taak suver komputerend is, dan kinne wy ​​in goedkeapere 1U-tsjinner keapje. Dit is berekkene effisjint. Dizze oanpak lit ús ûnder oare fjouwer kear minder masines brûke mei in lading dy't fergelykber is mei ien freonlik sosjale netwurk.

Sokke effisjinsje yn it brûken fan komputerboarnen soe ek ekonomyske effisjinsje moatte soargje, as wy útgean fan it útgongspunt dat it djoerste ding servers is. Foar in lange tiid wie hardware de djoerste, en wy sette in soad ynspannings foar it ferminderjen fan de priis fan hardware, komme mei fouttolerânsje algoritmen foar it ferminderjen fan hardware betrouberens easken. En hjoed hawwe wy it poadium berikt wêryn't de priis fan 'e tsjinner net mear beslissend is. As jo ​​​​de lêste eksoatyske net beskôgje, dan makket de spesifike konfiguraasje fan 'e servers yn' e rack net út. No hawwe wy in oar probleem - de priis fan 'e romte beset troch de tsjinner yn it datasintrum, dat is de romte yn it rek.

Wy realisearje dat dit it gefal wie, besleaten wy te berekkenjen hoe effektyf wy de rekken brûkten.
Wy namen de priis fan 'e machtichste tsjinner fan' e ekonomysk rjochtfeardige, berekkene hoefolle sokke tsjinners wy yn racks kinne pleatse, hoefolle taken wy op har soene útfiere basearre op it âlde model "ien tsjinner = ien taak" en hoefolle sokke taken koene de apparatuer brûke. Se telden en triennen. It die bliken dat ús effisjinsje by it brûken fan rekken sa'n 11% is. De konklúzje is fanselssprekkend: wy moatte de effisjinsje fan it brûken fan datasintra ferheegje. It liket derop dat de oplossing fanselssprekkend is: jo moatte ferskate taken tagelyk op ien server útfiere. Mar dit is wêr't de swierrichheden begjinne.

Massakonfiguraasje wurdt dramatysk yngewikkelder - it is no ûnmooglik om ien groep oan in server ta te jaan. Ommers, no kinne ferskate taken fan ferskate kommando's wurde lansearre op ien server. Derneist kin de konfiguraasje konflikt wêze foar ferskate applikaasjes. Diagnoaze wurdt ek yngewikkelder: as jo sjogge ferhege CPU of skiif konsumpsje op in tsjinner, jo witte net hokker taak soarget foar problemen.

Mar it wichtichste is dat d'r gjin isolaasje is tusken taken dy't op deselde masine rinne. Hjir is bygelyks in grafyk fan 'e gemiddelde reaksjetiid fan in tsjinnertaak foar en nei't in oare komputerapplikaasje op deselde tsjinner lansearre is, op gjin inkelde manier relatearre oan de earste - de antwurdtiid fan 'e haadtaak is signifikant tanommen.

One-cloud - datacenternivo OS yn Odnoklassniki

Fansels moatte jo taken útfiere yn konteners as yn firtuele masines. Om't hast al ús taken ûnder ien OS (Linux) rinne of dêrfoar oanpast binne, hoege wy net in protte ferskillende bestjoeringssystemen te stypjen. Dêrtroch is virtualisaasje net nedich; Troch de ekstra overhead sil it minder effisjint wêze dan kontenerisaasje.

As ymplemintaasje fan konteners foar it útfieren fan taken direkt op servers, is Docker in goede kandidaat: triemsysteemôfbyldings losse problemen mei konfliktende konfiguraasjes goed op. It feit dat ôfbyldings kinne wurde gearstald út ferskate lagen lit ús de hoemannichte gegevens signifikant ferminderje dy't nedich binne om se op 'e ynfrastruktuer yn te setten, troch mienskiplike dielen te skieden yn aparte basislagen. Dan wurde de basis (en meast volumineuze) lagen frij fluch yn 'e heule ynfrastruktuer yn' e cache bewarre, en om in protte ferskillende soarten applikaasjes en ferzjes te leverjen, sille allinich lytse lagen moatte wurde oerdroegen.

Plus, in klearmakke register en ôfbyldingstagging yn Docker jouwe ús klearmakke primitives foar ferzjen en leverjen fan koade oan produksje.

Docker, lykas elke oare ferlykbere technology, leveret ús wat nivo fan kontenerisolaasje út 'e doaze. Bygelyks, ûnthâld isolaasje - eltse container wurdt jûn in limyt op it brûken fan masine ûnthâld, dêrbûten sil net konsumearje. Jo kinne ek konteners isolearje op basis fan CPU-gebrûk. Foar ús wie lykwols standert isolaasje net genôch. Mar mear oer dat hjirûnder.

Direkt rinnende konteners op servers is mar in diel fan it probleem. It oare diel is relatearre oan it hostjen fan konteners op servers. Jo moatte begripe hokker kontener kin wurde pleatst op hokker server. Dit is net sa'n maklike taak, om't konteners sa ticht mooglik op servers pleatst wurde moatte sûnder har snelheid te ferminderjen. Sokke pleatsing kin ek lestich wêze út in flatertolerânsje. Faak wolle wy replika's fan deselde tsjinst yn ferskate racks of sels yn ferskate keamers fan it datasintrum pleatse, sadat as in rack of keamer mislearret, wy net fuortendaliks alle tsjinstreplika's ferlieze.

Containers mei de hân distribúsje is gjin opsje as jo 8 tûzen tsjinners en 8-16 tûzen konteners hawwe.

Derneist woenen wy ûntwikkelders mear ûnôfhinklikens jaan yn 'e allocaasje fan boarnen, sadat se har tsjinsten sels yn produksje kinne hostje, sûnder de help fan in behearder. Tagelyk woenen wy kontrôle behâlde, sadat guon lytse tsjinst net alle boarnen fan ús datasintra soe konsumearje.

Fansels hawwe wy in kontrôlelaach nedich dy't dit automatysk soe dwaan.

Sa kamen wy ta in ienfâldich en begryplik byld dat alle arsjitekten oanbidde: trije fjouwerkanten.

One-cloud - datacenternivo OS yn Odnoklassniki

one-cloud masters is in failover kluster ferantwurdlik foar wolk orkestraasje. De ûntwikkelder stjoert in manifest nei de master, dy't alle ynformaasje befettet dy't nedich is om de tsjinst te hostjen. Op grûn dêrfan jout de master kommando's oan selekteare minions (masines ûntworpen om konteners út te fieren). De minions hawwe ús agint, dy't it kommando ûntfangt, har kommando's útjout oan Docker, en Docker konfigurearret de linux-kernel om de oerienkommende kontener te starten. Neist it útfieren fan kommando's rapportearret de agint kontinu oan 'e master oer feroaringen yn' e steat fan sawol de minion-masine as de konteners dy't derop rinne.

Resource allocation

Litte wy no sjen nei it probleem fan kompleksere allocaasje fan boarnen foar in protte minions.

In komputerboarne yn ien wolk is:

  • De hoemannichte prosessorkrêft konsumearre troch in spesifike taak.
  • It bedrach fan ûnthâld beskikber foar de taak.
  • Netwurk ferkear. Elk fan 'e minions hat in spesifike netwurkynterface mei beheinde bânbreedte, dus it is ûnmooglik om taken te fersprieden sûnder rekken te hâlden mei de hoemannichte gegevens dy't se oer it netwurk stjoere.
  • Disks. Dêrneist, fansels, ta de romte foar dizze taken, wy ek tawize it type skiif: HDD of SSD. Skiven kinne tsjinje in einich oantal oanfragen per sekonde - IOPS. Dêrom, foar taken dy't generearje mear IOPS as in inkele skiif kin omgean, wy ek tawize "spindles" - dat is, skiif apparaten dy't moatte wurde eksklusyf reservearre foar de taak.

Dan foar guon tsjinst, bygelyks foar brûker-cache, kinne wy ​​​​de konsumeare boarnen op dizze manier opnimme: 400 prosessorkearnen, 2,5 TB ûnthâld, 50 Gbit / s ferkear yn beide rjochtingen, 6 TB HDD-romte leit op 100 spindles. Of yn in mear fertroude foarm as dizze:

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

Brûkerscache-tsjinstboarnen konsumearje mar in diel fan alle beskikbere boarnen yn 'e produksjeynfrastruktuer. Dêrom wol ik der wis fan wêze dat ynienen, troch in operatorflater of net, de brûker-cache net mear boarnen ferbrûkt dan dêroan tawiisd binne. Dat is, wy moatte middels beheine. Mar wêr kinne wy ​​it kwotum oan bine?

Litte wy weromgean nei ús sterk ferienfâldige diagram fan 'e ynteraksje fan komponinten en it opnij tekenje mei mear details - lykas dit:

One-cloud - datacenternivo OS yn Odnoklassniki

Wat falt jo each:

  • De webfrontend en muzyk brûke isolearre klusters fan deselde applikaasjeserver.
  • Wy kinne ûnderskiede de logyske lagen dêr't dizze klusters hearre: fronten, caches, gegevens opslach en behear laach.
  • It frontend is heterogeen; it bestiet út ferskate funksjonele subsystemen.
  • Caches kinne ek ferspraat wurde oer it subsysteem wêrfan de gegevens se yn it cache bewarje.

Litte wy de foto nochris tekenje:

One-cloud - datacenternivo OS yn Odnoklassniki

Bah! Ja, wy sjogge in hiërargy! Dit betsjut dat jo boarnen kinne fersprieden yn gruttere brokken: in ferantwurdlike ûntwikkelder tawize oan in knooppunt fan dizze hiërargy dy't oerienkomt mei it funksjonele subsysteem (lykas "muzyk" yn 'e ôfbylding), en hechtsje in kwota oan itselde nivo fan' e hiërargy. Dizze hiërargy lit ús ek tsjinsten fleksibeler organisearje foar gemak fan behear. Bygelyks, wy ferdiele it hiele web, om't dit in heul grutte groep servers is, yn ferskate lytsere groepen, werjûn yn 'e ôfbylding as groep1, groep2.

Troch de ekstra rigels te ferwiderjen, kinne wy ​​elke knooppunt fan ús foto yn in plattere foarm skriuwe: group1.web.front, api.music.front, user-cache.cache.

Dit is hoe't wy komme ta it konsept fan "hierarchyske wachtrige". It hat in namme lykas "group1.web.front". Der wurdt in kwota foar middels en brûkersrjochten oan tawiisd. Wy sille de persoan fan DevOps de rjochten jaan om in tsjinst nei de wachtrige te stjoeren, en sa'n meiwurker kin wat yn 'e wachtrige starte, en de persoan fan OpsDev sil adminrjochten hawwe, en no kin hy de wachtrige beheare, minsken dêr tawize, jou dizze minsken rjochten, ensfh. Tsjinsten dy't rinne op dizze wachtrige sille rinne binnen it kwota fan 'e wachtrige. As it komputerkwota fan 'e wachtrige net genôch is om alle tsjinsten tagelyk út te fieren, dan wurde se sequentieel útfierd, sadat de wachtrige sels foarmje.

Litte wy de tsjinsten fan tichterby besjen. In tsjinst hat in folslein kwalifisearre namme, dy't altyd de namme fan 'e wachtrige omfettet. Dan sil de foarste webtsjinst de namme hawwe ok-web.group1.web.front. En de tsjinst fan de applikaasje-tsjinner dêr't it tagong ta sil wurde neamd ok-app.group1.web.front. Elke tsjinst hat in manifest, dy't alle nedige ynformaasje spesifisearret foar pleatsing op spesifike masines: hoefolle boarnen dizze taak ferbrûkt, hokker konfiguraasje dêrfoar nedich is, hoefolle replika's moatte wêze, eigenskippen foar it behanneljen fan mislearrings fan dizze tsjinst. En nei't de tsjinst direkt op 'e masines is pleatst, ferskine har eksimplaren. Se wurde ek unambigu neamd - as it eksimplaarnûmer en tsjinstnamme: 1.ok-web.group1.web.front, 2.ok-web.group1.web.front, …

Dit is heul handich: allinich nei de namme fan 'e rinnende kontener sjogge, kinne wy ​​​​daliks in protte útfine.

Litte wy no in tichterby besjen wat dizze eksimplaren eins útfiere: taken.

Taakisolaasjeklassen

Alle taken yn OK (en, wierskynlik, oeral) kinne wurde ferdield yn groepen:

  • Koarte latency taken - prod. Foar sokke taken en tsjinsten is de antwurdfertraging (latency) heul wichtich, hoe fluch elk fan 'e oanfragen troch it systeem wurdt ferwurke. Foarbylden fan taken: webfronten, caches, applikaasjeservers, OLTP-opslach, ensfh.
  • Berekkeningsproblemen - batch. Hjir is de ferwurkingssnelheid fan elke spesifike oanfraach net wichtich. Foar harren is it wichtich hoefolle berekkeningen dizze taak sil dwaan yn in bepaalde (lange) perioade fan tiid (trochput). Dit sille alle taken wêze fan MapReduce, Hadoop, masine learen, statistiken.
  • Eftergrûntaken - idle. Foar sokke taken binne noch latency noch trochslach heul wichtich. Dit omfettet ferskate testen, migraasjes, opnij berekkeningen, en konverzje fan gegevens fan it iene formaat nei it oare. Oan 'e iene kant binne se gelyk oan berekkene, oan' e oare kant makket it ús net echt út hoe fluch se foltôge binne.

Litte wy sjen hoe't sokke taken boarnen brûke, bygelyks de sintrale prosessor.

Taken mei koarte fertraging. Sa'n taak sil in CPU-konsumpsjepatroan hawwe lykas dit:

One-cloud - datacenternivo OS yn Odnoklassniki

In fersyk fan de brûker wurdt ûntfongen foar ferwurking, de taak begjint alle beskikbere CPU-kearnen te brûken, ferwurket it, jout in antwurd werom, wachtet op it folgjende fersyk en stopet. It folgjende fersyk kaam - wer hawwe wy alles keazen dat der wie, berekkene it, en wachtsje op de folgjende.

Om de minimale latency foar sa'n taak te garandearjen, moatte wy de maksimale boarnen nimme dy't it verbruikt en it fereaske oantal kearnen reservearje op 'e minion (de masine dy't de taak sil útfiere). Dan sil de reservearringsformule foar ús probleem as folgjend wêze:

alloc: cpu = 4 (max)

en as wy in minion-masine hawwe mei 16 kearnen, dan kinne der krekt fjouwer sokke taken op pleatst wurde. Wy merken benammen op dat it gemiddelde prosessorkonsumpsje fan sokke taken faaks heul leech is - wat fanselssprekkend is, om't in signifikant diel fan 'e tiid de taak wachtet op in fersyk en neat docht.

Berekkening taken. Har patroan sil wat oars wêze:

One-cloud - datacenternivo OS yn Odnoklassniki

It gemiddelde CPU-boarneferbrûk foar sokke taken is frij heech. Faak wolle wy dat in berekkeningstaak yn in bepaalde tiid foltôge is, dus moatte wy it minimale oantal processors reservearje dat it nedich is, sadat de folsleine berekkening yn in akseptabele tiid foltôge wurdt. De reservearringsformule sil der sa útsjen:

alloc: cpu = [1,*)

"Plaze it asjebleaft op in minion wêr't op syn minst ien frije kearn is, en dan safolle as d'r binne, sil it alles opsnuorje."

Hjir is de effisjinsje fan gebrûk al folle better as op taken mei in koarte fertraging. Mar de winst sil folle grutter as jo kombinearje beide soarten taken op ien minion masine en fersprieden syn middels ûnderweis. As in taak mei in koarte fertraging in prosessor fereasket, ûntfangt it fuortendaliks, en as de middels net mear nedich binne, wurde se oerbrocht nei de berekkeningstaak, dus soksawat:

One-cloud - datacenternivo OS yn Odnoklassniki

Mar hoe dat te dwaan?

Lit ús earst sjen nei prod en syn alloc: cpu = 4. Wy moatte reservearje fjouwer kearnen. Yn Docker run kin dit op twa manieren dien wurde:

  • Mei help fan de opsje --cpuset=1-4, dat wol sizze fjouwer spesifike kearnen op 'e masine tawize oan de taak.
  • Brûke --cpuquota=400_000 --cpuperiod=100_000, tawize in kwota foar prosessor tiid, d.w.s. oanjaan dat elke 100 ms fan echte tiid de taak net mear as 400 ms fan prosessor tiid ferbrûkt. Deselde fjouwer kearnen wurde krigen.

Mar hokker fan dizze metoaden is geskikt?

cpuset sjocht der frij oantreklik út. De taak hat fjouwer tawijd kearnen, wat betsjut dat prosessor-caches sa effisjint mooglik wurkje. Dit hat ek in neidiel: wy soene de taak moatte nimme om berekkeningen te fersprieden oer de ûntladen kearnen fan 'e masine ynstee fan it OS, en dit is in nochal net-triviale taak, foaral as wy besykje batchtaken te pleatsen op sa'n in masine. Tests hawwe útwiisd dat de opsje mei in kwota hjir better geskikt is: sa hat it bestjoeringssysteem mear frijheid yn it kiezen fan de kearn om de taak op it hjoeddeiske momint út te fieren en wurdt de prosessortiid effisjinter ferdield.

Litte wy útfine hoe't jo reservearje kinne meitsje yn Docker basearre op it minimale oantal kearnen. It kwota foar batchtaken is net mear fan tapassing, om't it maksimum net hoecht te beheinen, it is genôch om gewoan it minimum te garandearjen. En hjir past de opsje goed docker run --cpushares.

Wy hawwe ôfpraat dat as in batch in garânsje fereasket foar op syn minst ien kearn, dan jouwe wy oan --cpushares=1024, en as der op syn minst twa kearnen binne, dan jouwe wy oan --cpushares=2048. Cpu oandielen net bemuoie mei de ferdieling fan prosessor tiid sa lang as der genôch fan it. Dus, as prod op it stuit net al syn fjouwer kearnen brûkt, is d'r neat dat batchtaken beheint, en se kinne ekstra prosessortiid brûke. Mar yn in situaasje wêryn d'r in tekoart is oan processors, as prod alle fjouwer fan har kearnen konsumearre hat en syn kwota hat berikt, sil de oerbleaune prosessortiid proporsjoneel ferdield wurde oan cpushares, dus yn in situaasje fan trije frije kearnen, sil ien wêze jûn oan in taak mei 1024 cpushares, en de oerbleaune twa wurde jûn oan in taak mei 2048 cpushares.

Mar it brûken fan kwota en oandielen is net genôch. Wy moatte derfoar soargje dat in taak mei in koarte fertraging prioriteit krijt boppe in batchtaak by it tawizen fan prosessortiid. Sûnder sa'n prioritearring sil de batchtaak alle prosessortiid nimme op it momint dat it nedich is troch de prod. D'r binne gjin opsjes foar kontenerprioritearing yn Docker run, mar Linux CPU-plannerbelied komt goed fan pas. Jo kinne lêze oer harren yn detail hjir, en yn it ramt fan dit artikel sille wy se koart trochgean:

  • SCHED_OTHER
    Standert ûntfange alle normale brûkersprosessen op in Linux-masine.
  • SCHED_BATCH
    Ûntwurpen foar boarne-yntinsive prosessen. By it pleatsen fan in taak op in prosessor wurdt in saneamde aktivearringsboete ynfierd: sa'n taak krijt minder kâns om prosessorboarnen te ûntfangen as it op it stuit brûkt wurdt troch in taak mei SCHED_OTHER
  • SCHED_IDLE
    In eftergrûnproses mei in heul lege prioriteit, sels leger as moai -19. Wy brûke ús iepen boarne bibleteek ien njo, om it nedige belied yn te stellen by it starten fan de kontener troch te skiljen

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

Mar sels as jo net yn Java programmearje, kin itselde ding dien wurde mei it kommando chrt:

chrt -i 0 $pid

Litte wy al ús isolaasjenivo's gearfetsje yn ien tabel foar dúdlikens:

Isolaasje klasse
Foarbyld fan Alloc
Docker run opsjes
sched_setscheduler chrt*

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

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

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

*As jo ​​chrt fan binnen in kontener dogge, kinne jo de sys_nice-mooglikheid nedich wêze, om't standert Docker dizze mooglikheid ferwideret by it starten fan de kontener.

Mar taken konsumearje net allinich de prosessor, mar ek ferkear, wat de latency fan in netwurktaak noch mear beynfloedet as de ferkearde allocaasje fan prosessorboarnen. Dêrom wolle wy fansels krekt itselde byld krije foar it ferkear. Dat is, as in prod-taak guon pakketten nei it netwurk stjoert, beheine wy ​​de maksimale snelheid (formule alloc: lan=[*,500mbps) ), wêrmei prod dit kin dwaan. En foar batch garandearje wy allinich de minimale trochset, mar beheine it maksimum (formule alloc: lan=[10Mbps,*) ) Yn dit gefal moat prodferkear prioriteit krije boppe batchtaken.
Hjir hat Docker gjin primitives dy't wy kinne brûke. Mar it komt ús ta help Linux Ferkearskontrôle. Mei help fan dissipline koenen wy it winske resultaat berikke Hierarchical Fair Service Curve. Mei har help ûnderskiede wy twa klassen fan ferkear: prod mei hege prioriteit en batch / idle mei lege prioriteit. As resultaat is de konfiguraasje foar útgeand ferkear sa:

One-cloud - datacenternivo OS yn Odnoklassniki

hjir is 1:0 de "root qdisc" fan 'e hsfc-dissipline; 1: 1 - hsfc bern klasse mei in totale bânbreedte limyt fan 8 Gbit / s, dêr't de bern klassen fan alle konteners wurde pleatst; 1:2 - de hsfc-berneklasse is mienskiplik foar alle batch- en idle taken mei in "dynamyske" limyt, dy't hjirûnder besprutsen wurdt. De oerbleaune hsfc-berneklassen binne tawijde klassen foar op it stuit rinnende prodkonteners mei grinzen dy't oerienkomme mei har manifesten - 450 en 400 Mbit / s. Elke hsfc-klasse wurdt tawiisd in qdisc-wachtrige fq of fq_codel, ôfhinklik fan de Linux-kernelferzje, om pakketferlies te foarkommen tidens ferkearsbursts.

Typysk tsjinje tc-dissiplines om allinich útgeand ferkear te prioritearjen. Mar wy wolle ek foarrang jaan oan ynkommende ferkear - ommers, guon batch-taak kin maklik it hiele ynkommende kanaal selektearje, en ûntfange, bygelyks, in grutte partij ynfiergegevens foar map&reduce. Dêrfoar brûke wy de module ifb, dy't in firtuele ifbX-ynterface foar elke netwurkynterface makket en ynkommende ferkear fan 'e ynterface omliedt nei útgeande ferkear op ifbX. Fierder, foar ifbX, wurkje alle deselde dissiplines om útgeand ferkear te kontrolearjen, wêrfoar de hsfc-konfiguraasje heul gelyk sil wêze:

One-cloud - datacenternivo OS yn Odnoklassniki

Tidens de eksperiminten, wy fûn út dat hsfc toant de bêste resultaten as de 1: 2 klasse fan net-prioriteit batch / idle ferkear wurdt beheind op minion masines ta net mear as in bepaalde frije baan. Oars hat net-prioriteit ferkear tefolle ynfloed op 'e latency fan prodtaken. miniond bepaalt de hjoeddeistige hoemannichte frije bânbreedte elke sekonde, mjit it gemiddelde ferkearskonsumpsje fan alle prod-taken fan in opjûne minion One-cloud - datacenternivo OS yn Odnoklassniki en subtracting it fan de netwurk ynterface bânbreedte One-cloud - datacenternivo OS yn Odnoklassniki mei in lytse marzje, d.w.s.

One-cloud - datacenternivo OS yn Odnoklassniki

Bands wurde ûnôfhinklik definiearre foar ynkommende en útgeande ferkear. En neffens de nije wearden konfigurearret miniond de net-prioriteit klasse limyt 1:2.

Sa hawwe wy alle trije isolaasjeklassen ymplementearre: prod, batch en idle. Dizze klassen beynfloedzje de prestaasjeskenmerken fan taken sterk. Dêrom hawwe wy besletten dit attribút oan 'e boppekant fan' e hiërargy te pleatsen, sadat by it besjen fan 'e namme fan' e hiërargyske wachtrige it daliks dúdlik wêze soe wêr't wy mei te krijen hawwe:

One-cloud - datacenternivo OS yn Odnoklassniki

Al ús freonen reach и music de fronten wurde dan pleatst yn de hiërargy ûnder prod. Bygelyks, ûnder batch, litte wy de tsjinst pleatse muzyk katalogus, dy't periodyk in katalogus fan spoaren kompilearret út in set fan mp3-bestannen uploaded nei Odnoklassniki. In foarbyld fan in tsjinst ûnder idle soe wêze muzyk transformator, dy't it muzykvolumintnivo normalisearret.

Mei de ekstra rigels wer fuorthelle, kinne wy ​​ús tsjinstnammen platter skriuwe troch de taakisolaasjeklasse ta te foegjen oan it ein fan 'e folsleine tsjinstnamme: web.front.prod, catalog.music.batch, transformer.music.idle.

En no, as wy nei de namme fan 'e tsjinst sjogge, begripe wy net allinich hokker funksje it docht, mar ek har isolaasjeklasse, wat syn krityk betsjut, ensfh.

Alles is geweldich, mar der is ien bittere wierheid. It is ûnmooglik om taken folslein te isolearjen dy't rinne op ien masine.

Wat wy slagge te berikken: as batch yntinsyf konsumearret allinnich CPU-boarnen, dan docht de ynboude Linux CPU-planner har wurk heul goed, en d'r is praktysk gjin ynfloed op 'e prodtaak. Mar as dizze batch-taak begjint aktyf te wurkjen mei ûnthâld, dan ferskynt de ûnderlinge ynfloed al. Dit bart om't de prod-taak "útwosken" is fan 'e ûnthâldcaches fan' e prosessor - as gefolch, cache mist tanimme, en de prosessor ferwurket de prod-taak stadiger. Sa'n batchtaak kin de latency fan ús typyske prodkontener mei 10% ferheegje.

It isolearjen fan ferkear is noch dreger fanwege it feit dat moderne netwurkkaarten in ynterne wachtrige fan pakketten hawwe. As it pakket fan 'e batchtaak dêr earst komt, dan sil it de earste wêze dy't oer de kabel ferstjoerd wurdt, en der kin neat oan dien wurde.

Dêrnjonken hawwe wy oant no ta allinich it probleem op te lossen fan it prioritearjen fan TCP-ferkear: de hsfc-oanpak wurket net foar UDP. En sels yn it gefal fan TCP-ferkear, as de batchtaak in soad ferkear genereart, jout dit ek sa'n 10% tanimming yn 'e fertraging fan' e prodtaak.

marzje foar flaters

Ien fan 'e doelen by it ûntwikkeljen fan ien-wolk wie om de fouttolerânsje fan Odnoklassniki te ferbetterjen. Dêrom soe ik folgjende yn mear detail mooglike senario's fan mislearrings en ûngemakken beskôgje. Litte wy begjinne mei in ienfâldich senario - in kontenerfal.

De kontener sels kin op ferskate manieren mislearje. Dit kin in soarte fan eksperimint, brek of flater yn it manifest wêze, wêrtroch't de prodtaak mear boarnen begjint te konsumearjen dan oanjûn yn it manifest. Wy hienen in saak: in ûntwikkelder ymplementearre ien kompleks algoritme, bewurke it in protte kearen, betocht himsels en waard sa yn 'e war dat it probleem úteinlik yn in heul net-triviale loop gie. En om't de prodtaak in hegere prioriteit hat as alle oaren op deselde minions, begon it alle beskikbere prosessorboarnen te konsumearjen. Yn dizze situaasje hat isolaasje, of leaver it CPU-tiidskwota, de dei bewarre. As in taak in kwota wurdt tawiisd, sil de taak net mear konsumearje. Dêrom, batch en oare prod taken dy't rûnen op deselde masine net merken neat.

It twadde mooglike probleem is dat de kontener falle. En hjir rêdt ús opnij belied, elkenien wit se, Docker sels docht in geweldige baan. Hast alle prodtaken hawwe in altyd opnij belied. Soms brûke wy on_failure foar batchtaken of foar it debuggen fan prodcontainers.

Wat kinne jo dwaan as in hiele minion net beskikber is?

Fansels, rinne de kontener op in oare masine. It nijsgjirrige diel hjir is wat der bart mei de IP-adres(sen) dy't oan 'e kontener binne tawiisd.

Wy kinne konteners deselde IP-adressen tawize as de minionmasines wêrop dizze konteners rinne. Dan, as de kontener wurdt lansearre op in oare masine, feroaret it IP-adres, en alle kliïnten moatte begripe dat de kontener is ferpleatst, en no moatte se nei in oar adres gean, wat in aparte Service Discovery-tsjinst fereasket.

Service Discovery is handich. D'r binne in protte oplossingen op 'e merk fan ferskate graden fan skuldtolerânsje foar it organisearjen fan in tsjinstregister. Faak implementearje sokke oplossingen load balancer logika, bewarje ekstra konfiguraasje yn 'e foarm fan KV-opslach, ensfh.
Wy wolle lykwols de needsaak foarkomme om in apart register te ymplementearjen, om't dit betsjutte dat in kritysk systeem ynfierd wurdt dat wurdt brûkt troch alle tsjinsten yn produksje. Dit betsjut dat dit in potinsjele punt fan mislearring, en jo moatte kieze of ûntwikkeljen in hiel skuld-tolerante oplossing, dat is fansels hiel dreech, tiidslinend en djoer.

En noch ien grut nadeel: om ús âlde ynfrastruktuer te wurkjen mei de nije, soene wy ​​absolút alle taken moatte oerskriuwe om in soarte fan Service Discovery-systeem te brûken. D'r is in protte wurk, en op guon plakken is it hast ûnmooglik as it giet om apparaten op leech nivo dy't wurkje op it OS-kernelnivo of direkt mei de hardware. Utfiering fan dizze funksjonaliteit mei help fan fêststelde oplossingspatroanen, lykas side-auto soe betsjutte op guon plakken in ekstra lading, yn oaren - in komplikaasje fan operaasje en ekstra faluta senario. Wy woenen de dingen net komplisearje, dus besleaten wy it gebrûk fan Service Discovery opsjoneel te meitsjen.

Yn ien-wolk folget de IP de kontener, d.w.s. elke taakeksimplaar hat in eigen IP-adres. Dit adres is "statysk": it wurdt tawiisd oan elke eksimplaar as de tsjinst foar it earst nei de wolk stjoerd wurdt. As in tsjinst yn syn libben in oar oantal eksimplaren hie, dan sil it op it lêst safolle IP-adressen wurde tawiisd as d'r maksimale eksimplaren wiene.

Dêrnei feroarje dizze adressen net: se wurde ien kear tawiisd en bestean troch it hiele libben fan 'e tsjinst yn produksje. IP-adressen folgje konteners oer it netwurk. As de kontener wurdt oerbrocht nei in oare minion, dan sil it adres folgje.

Sa feroaret de mapping fan in tsjinstnamme oan syn list mei IP-adressen heul selden. As jo ​​​​op 'e nij sjogge nei de nammen fan' e tsjinstynstânsjes dy't wy oan it begjin fan it artikel neamden (1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, …), sille wy merke dat se lykje op de FQDN's dy't brûkt wurde yn DNS. Dat is krekt, om de nammen fan tsjinstynstânsjes yn kaart te bringen op har IP-adressen, brûke wy it DNS-protokol. Boppedat jout dizze DNS alle reservearre IP-adressen fan alle konteners werom - sawol rinnende as stoppe (litte wy sizze dat trije replika's wurde brûkt, en wy hawwe dêr fiif adressen reservearre - alle fiif wurde weromjûn). Klanten dy't dizze ynformaasje krigen hawwe, sille besykje in ferbining te meitsjen mei alle fiif replika's - en sadwaande bepale wa't wurkje. Dizze opsje foar it bepalen fan beskikberens is folle betrouberer; it omfettet gjin DNS of Service Discovery, wat betsjut dat d'r gjin drege problemen binne om op te lossen by it garandearjen fan de relevânsje fan ynformaasje en fouttolerânsje fan dizze systemen. Boppedat, yn krityske tsjinsten wêrfan de wurking fan it hiele portal hinget, kinne wy ​​​​gjin DNS brûke, mar gewoan IP-adressen yn 'e konfiguraasje ynfiere.

It ymplementearjen fan sa'n IP-oerdracht efter konteners kin net-triviaal wêze - en wy sille sjen hoe't it wurket mei it folgjende foarbyld:

One-cloud - datacenternivo OS yn Odnoklassniki

Litte wy sizze dat de ien-wolkmaster it kommando jout oan minion M1 om te rinnen 1.ok-web.group1.web.front.prod mei adres 1.1.1.1. Wurket op in minion FÛGEL, dy't dit adres advertearret oan spesjale tsjinners rûte reflector. De lêste hawwe in BGP-sesje mei de netwurkhardware, wêryn de rûte fan adres 1.1.1.1 op M1 oerset wurdt. M1 rûtes pakketten binnen de kontener mei Linux. D'r binne trije rûtereflektorservers, om't dit in heul kritysk diel is fan 'e ien-wolk-ynfrastruktuer - sûnder harren sil it netwurk yn ien-wolk net wurkje. Wy pleatse se yn ferskate rekken, as it mooglik is yn ferskate keamers fan it datasintrum, om de kâns te ferminderjen dat alle trije tagelyk mislearje.

Litte wy no oannimme dat de ferbining tusken de ien-wolkmaster en de M1-minion ferlern is. De ien-wolkmaster sil no hannelje op de oanname dat M1 folslein mislearre is. Dat is, it sil it kommando jaan oan 'e M2-minion om te starten web.group1.web.front.prod mei itselde adres 1.1.1.1. No hawwe wy twa tsjinstridige rûtes op it netwurk foar 1.1.1.1: op M1 en op M2. Om sokke konflikten op te lossen, brûke wy de Multi Exit Discriminator, dy't spesifisearre is yn 'e BGP-oankundiging. Dit is in nûmer dat it gewicht fan 'e oankundige rûte toant. Under de tsjinstridige rûtes sil de rûte mei de legere MED-wearde selektearre wurde. De ien-wolkmaster stipet MED as in yntegraal diel fan container IP-adressen. Foar it earst wurdt it adres skreaun mei in genôch grutte MED = 1 000 000. Yn 'e situaasje fan sa'n needkontenerferfier fermindert de master de MED, en M2 sil al it kommando krije om it adres 1.1.1.1 te advertearjen mei MED = 999 999. De eksimplaar dy't rint op M1 sil bliuwe op yn dit gefal is der gjin ferbining, en syn fierdere lot ynteresseart ús bytsje oant de ferbining mei de master wurdt werombrocht, doe't hy sil wurde stoppe as in âlde take.

ûngemakken

Alle datacenterbehearsystemen behannelje altyd lytse flaters akseptabel. Container oerstreaming is hast oeral de noarm.

Litte wy sjen nei hoe't wy omgean mei in need, lykas in stroomûnderbrekking yn ien of mear keamers fan in datasintrum.

Wat betsjuttet in ûngelok foar in datacenterbehearsysteem? Alderearst is dit in massale ienmalige mislearring fan in protte masines, en it kontrôlesysteem moat tagelyk in protte konteners migrearje. Mar as de ramp tige grut is, dan kin it barre dat alle taken net opnij oan oare minions kinne wurde tawiisd, om't de boarnekapasiteit fan it datasintrum ûnder 100% fan 'e lading falt.

Faak wurde ûngemakken begelaat troch falen fan 'e kontrôlelaach. Dit kin barre fanwege it mislearjen fan syn apparatuer, mar faker fanwege it feit dat ûngemakken wurde net hifke, en de kontrôle laach sels falt fanwege de ferhege lading.

Wat kinne jo dwaan oan dit alles?

Massemigraasjes betsjutte dat d'r in grut oantal aktiviteiten, migraasjes en ynset binne yn 'e ynfrastruktuer. Elk fan 'e migraasjes kin wat tiid nedich wêze om kontenerôfbyldings te leverjen en út te pakken oan minions, konteners te starten en te initialisearjen, ensfh Dêrom is it winsklik dat wichtiger taken wurde lansearre foardat minder wichtige.

Litte wy nochris sjen nei de hiërargy fan tsjinsten dy't wy bekend binne en besykje te besluten hokker taken wy earst wolle útfiere.

One-cloud - datacenternivo OS yn Odnoklassniki

Fansels binne dit de prosessen dy't direkt belutsen binne by it ferwurkjen fan brûkersoanfragen, dus prod. Wy jouwe dit oan mei pleatsing prioriteit - in nûmer dat kin wurde tawiisd oan de wachtrige. As in wachtrige in hegere prioriteit hat, wurde har tsjinsten earst pleatst.

Op prod wy jouwe hegere prioriteiten, 0; op batch - in bytsje leger, 100; op idle - noch leger, 200. Prioriteiten wurde hiërargysk tapast. Alle taken leger yn 'e hiërargy sille in oerienkommende prioriteit hawwe. As wy wolle dat caches binnen prod wurde lansearre foar frontends, dan jouwe wy prioriteiten ta oan cache = 0 en oan front subqueues = 1. As wy bygelyks wolle dat it haadportaal earst fan 'e fronten lansearre wurdt, en allinich de muzykfront dan kinne wy ​​de lêste in legere prioriteit tawize - 10.

It folgjende probleem is gebrek oan middels. Dat, in grutte hoemannichte apparatuer, hiele sealen fan it datasintrum, mislearre, en wy hawwe safolle tsjinsten opnij lansearre dat no net genôch boarnen binne foar elkenien. Jo moatte beslute hokker taken jo moatte opofferje om de wichtichste krityske tsjinsten rinnen te hâlden.

One-cloud - datacenternivo OS yn Odnoklassniki

Oars as pleatsingsprioriteit kinne wy ​​​​alle batchtaken net sûnder ûnderskied opofferje; guon fan harren binne wichtich foar de wurking fan it portaal. Dêrom hawwe wy apart markearre preemption prioriteit taken. As pleatst, kin in taak mei hegere prioriteit preempje, dus stopje, in taak mei legere prioriteit as d'r gjin frije minions mear binne. Yn dit gefal sil in taak mei in lege prioriteit wierskynlik net pleatst bliuwe, d.w.s. d'r sil gjin geskikte minion mear foar wêze mei genôch frije middels.

Yn ús hiërargy is it hiel ienfâldich om in preemption-prioriteit te spesifisearjen sadat prod- en batchtaken idle taken preemje of stopje, mar net inoar, troch in prioriteit op te jaan foar idle gelyk oan 200. Krekt as yn it gefal fan pleatsingsprioriteit, wy kinne ús hiërargy brûke om mear komplekse regels te beskriuwen. Litte wy bygelyks oanjaan dat wy de muzykfunksje opofferje as wy net genôch boarnen hawwe foar it haadwebportaal, de prioriteit foar de korrespondearjende knopen leger ynstelle: 10.

Hiele DC ûngemakken

Wêrom kin it heule datasintrum mislearje? Elemint. Wie in goede post de orkaan beynfloede it wurk fan it datasintrum. De eleminten kinne beskôge wurde as dakleazen dy't ienris de optyk yn 'e mannichfâld ferbaarne, en it datasintrum folslein ferlear kontakt mei oare siden. De oarsaak fan mislearring kin ek in minsklike faktor wêze: de operator sil sa'n kommando útjaan dat it hiele datasintrum falle sil. Dit kin barre troch in grutte bug. Yn 't algemien is it ynstoarten fan datasintra net ûngewoan. Dit bart ús ien kear yn de pear moannen.

En dit is wat wy dogge om foar te kommen dat elkenien #alive tweet.

De earste strategy is isolaasje. Elke eksimplaar fan ien wolk is isolearre en kin masines beheare yn mar ien datasintrum. Dat is, it ferlies fan in wolk troch bugs of ferkearde operatorkommando's is it ferlies fan mar ien datasintrum. Wy binne der klear foar: wy hawwe in ûntslachbelied wêryn replika's fan 'e applikaasje en gegevens yn alle datasintra lizze. Wy brûke fouttolerante databases en testen periodyk op mislearrings.
Sûnt hjoed hawwe wy fjouwer datasintra, dat betsjut fjouwer aparte, folslein isolearre eksimplaren fan ien-wolk.

Dizze oanpak beskermet net allinnich tsjin fysike falen, mar kin ek beskermje tsjin operator flater.

Wat oars kin dien wurde mei de minsklike faktor? As in operator de wolk in nuver of potinsjeel gefaarlik kommando jout, kin hy ynienen frege wurde om in lyts probleem op te lossen om te sjen hoe goed hy tocht. Bygelyks, as dit in soarte fan massa stop is fan in protte replika's of gewoan in frjemd kommando - it ferminderjen fan it oantal replika's of it feroarjen fan de namme fan 'e ôfbylding, en net allinich it ferzjenûmer yn it nije manifest.

One-cloud - datacenternivo OS yn Odnoklassniki

Resultaten

Underskate skaaimerken fan ien-wolk:

  • Hierarchysk en fisueel nammejouwingskema foar tsjinsten en konteners, wêrmei jo hiel fluch útfine wat de taak is, wat it oanbelanget en hoe't it wurket en wa't der ferantwurdlik foar is.
  • Wy tapasse ús technyk fan it kombinearjen fan prod- en batch-taken op minions om de effisjinsje fan dielen fan masines te ferbetterjen. Ynstee fan cpuset brûke wy CPU-kwota's, oandielen, CPU-plannerbelied en Linux QoS.
  • It wie net mooglik om folslein isolearje konteners dy't rinne op deselde masine, mar harren ûnderlinge ynfloed bliuwt binnen 20%.
  • It organisearjen fan tsjinsten yn in hiërargy helpt by it brûken fan automatyske rampherstel pleatsing en preemption prioriteiten.

FAQ

Wêrom hawwe wy gjin klearebare oplossing nommen?

  • Ferskillende klassen fan taakisolaasje fereaskje ferskillende logika as se pleatst op minions. As prodtaken kinne wurde pleatst troch gewoan boarnen te reservearjen, dan moatte batch- en idle-taken wurde pleatst, en folgje it eigentlike gebrûk fan boarnen op minion-masines.
  • De needsaak om rekken te hâlden mei boarnen konsumearre troch taken, lykas:
    • netwurk bânbreedte;
    • soarten en "spindels" fan skiven.
  • De needsaak om de prioriteiten fan tsjinsten oan te jaan tidens needreaksje, de rjochten en kwota's fan kommando's foar boarnen, dy't wurdt oplost mei hiërargyske wachtrijen yn ien wolk.
  • De needsaak om minsklike nammen fan konteners te hawwen om de reaksjetiid op ûngemakken en ynsidinten te ferminderjen
  • De ûnmooglikheid fan in ien kear wiidferspraat ymplemintaasje fan Service Discovery; de needsaak om te bestean foar in lange tiid mei taken hosted op hardware hosts - iets dat wurdt oplost troch "statyske" IP-adressen folgjende konteners, en, as gefolch, de needsaak foar unike yntegraasje mei in grutte netwurk ynfrastruktuer.

Al dizze funksjes soene wichtige oanpassingen fan besteande oplossingen fereaskje om ús te passen, en, nei it beoardieljen fan it bedrach fan wurk, realisearre wy dat wy ús eigen oplossing koene ûntwikkelje mei sawat deselde arbeidskosten. Mar jo oplossing sil folle makliker wêze om te operearjen en te ûntwikkeljen - it befettet gjin ûnnedige abstraksjes dy't funksjonaliteit stypje dy't wy net nedich binne.

Oan dyjingen dy't de lêste rigels lêze, tank foar jo geduld en oandacht!

Boarne: www.habr.com

Add a comment