Vieno debesies – duomenų centro lygio OS Odnoklassniki

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Aloha, žmonės! Mano vardas Olegas Anastasjevas, dirbu „Odnoklassniki“ platformos komandoje. Be manęs, Odnoklassniki dirba daug techninės įrangos. Turime keturis duomenų centrus su apie 500 stelažų ir daugiau nei 8 tūkstančius serverių. Tam tikru momentu supratome, kad naujos valdymo sistemos įdiegimas leis efektyviau apkrauti įrangą, palengvinti prieigos valdymą, automatizuoti skaičiavimo resursų (per)skirstymą, paspartinti naujų paslaugų paleidimą ir greitesnį atsakymą. į didelio masto avarijas.

Kas iš to išėjo?

Be manęs ir daugybės techninės įrangos, taip pat yra žmonių, kurie dirba su šia aparatūra: inžinieriai, kurie yra tiesiogiai duomenų centruose; tinklo darbuotojai, kurie nustato tinklo programinę įrangą; administratoriai arba SRE, užtikrinantys infrastruktūros atsparumą; ir kūrimo komandos, kiekviena iš jų yra atsakinga už dalį portalo funkcijų. Jų sukurta programinė įranga veikia maždaug taip:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Vartotojų užklausos gaunamos abiejuose pagrindinio portalo frontuose www.ok.ru, ir kitose, pavyzdžiui, muzikos API frontuose. Norėdami apdoroti verslo logiką, jie iškviečia programų serverį, kuris, apdorodamas užklausą, iškviečia reikiamas specializuotas mikropaslaugas - vieno grafiko (socialinių ryšių grafikas), vartotojo talpyklą (vartotojo profilių talpyklą) ir kt.

Kiekviena iš šių paslaugų yra įdiegta daugelyje mašinų ir kiekvienoje iš jų yra atsakingi kūrėjai, atsakingi už modulių funkcionavimą, jų veikimą ir technologinę plėtrą. Visos šios paslaugos veikia aparatinės įrangos serveriuose, o iki šiol kiekvienam serveriui paleidome tiksliai vieną užduotį, t. y. ji buvo skirta konkrečiai užduočiai atlikti.

Kodėl taip? Šis metodas turėjo keletą privalumų:

  • Palengvėjo masinis valdymas. Tarkime, kad užduočiai atlikti reikia tam tikrų bibliotekų, tam tikrų nustatymų. Tada serveris priskiriamas tiksliai vienai konkrečiai grupei, aprašoma šios grupės cfengine politika (arba ji jau buvo aprašyta), ir ši konfigūracija centralizuotai ir automatiškai iškeliama į visus šios grupės serverius.
  • Supaprastinta diagnostika. Tarkime, pažvelgsite į padidėjusį centrinio procesoriaus apkrovą ir suprasite, kad šią apkrovą gali generuoti tik užduotis, kuri vykdoma šiame aparatūros procesoriuje. Kaltintojo paieškos baigiasi labai greitai.
  • Supaprastinta stebėjimas. Jei kas nors negerai su serveriu, monitorius apie tai praneša ir jūs tiksliai žinote, kas kaltas.

Paslaugai, susidedančiai iš kelių kopijų, priskiriami keli serveriai – po vieną kiekvienam. Tada paslaugos skaičiavimo resursas paskirstomas labai paprastai: kiek serverių turi paslauga, kiek resursų ji gali sunaudoti. „Lengva“ čia nereiškia, kad juo lengva naudotis, o ta prasme, kad išteklių paskirstymas atliekamas rankiniu būdu.

Šis požiūris taip pat leido mums tai padaryti specializuotos geležies konfigūracijos užduočiai, vykdomai šiame serveryje. Jei užduotyje saugomi dideli duomenų kiekiai, tada naudojame 4U serverį su važiuokle su 38 diskais. Jei užduotis yra grynai skaičiavimo, galime nusipirkti pigesnį 1U serverį. Tai skaičiavimo požiūriu efektyvu. Be kita ko, šis metodas leidžia mums naudoti keturis kartus mažiau mašinų, kurių apkrova prilygsta vienam draugiškam socialiniam tinklui.

Toks skaičiavimo resursų panaudojimo efektyvumas turėtų užtikrinti ir ekonominį efektyvumą, jei vadovausimės prielaida, kad brangiausia yra serveriai. Ilgą laiką aparatinė įranga buvo pati brangiausia, todėl labai stengėmės sumažinti techninės įrangos kainą, sugalvojome atsparumo gedimams algoritmus, kad sumažintume techninės įrangos patikimumo reikalavimus. Ir šiandien pasiekėme tą etapą, kai serverio kaina nustojo būti lemiama. Jei neatsižvelgiate į naujausią egzotiką, konkreti stovo serverių konfigūracija neturi reikšmės. Dabar turime dar vieną problemą – serverio užimamos vietos duomenų centre kaina, tai yra vietos stove.

Suprasdami, kad taip yra, nusprendėme paskaičiuoti, kaip efektyviai naudojame stelažus.
Galingiausio serverio kainą paėmėme iš ekonomiškai pagrįstų, skaičiavome, kiek tokių serverių galėtume sudėti į stelažus, kiek užduočių juose vykdysime pagal seną modelį „vienas serveris = viena užduotis“ ir kiek tokių. užduotys galėtų panaudoti įrangą. Jie skaičiavo ir liejo ašaras. Paaiškėjo, kad mūsų efektyvumas naudojant stelažus siekia apie 11%. Išvada akivaizdi: turime padidinti duomenų centrų naudojimo efektyvumą. Atrodytų, sprendimas akivaizdus: viename serveryje vienu metu reikia vykdyti kelias užduotis. Tačiau čia ir prasideda sunkumai.

Masinė konfigūracija tampa žymiai sudėtingesnė – dabar serveriui neįmanoma priskirti vienos grupės. Juk dabar viename serveryje galima paleisti kelias skirtingų komandų užduotis. Be to, skirtingų programų konfigūracija gali prieštarauti. Diagnozė taip pat tampa sudėtingesnė: jei serveryje matote padidėjusį procesoriaus ar disko suvartojimą, nežinote, kuri užduotis sukelia problemų.

Tačiau svarbiausia, kad toje pačioje mašinoje vykdomos užduotys nebūtų atskirtos. Pavyzdžiui, čia yra vidutinio serverio užduoties atsako laiko grafikas prieš ir po to, kai tame pačiame serveryje buvo paleista kita skaičiavimo programa, niekaip nesusijusi su pirmąja – pagrindinės užduoties atsako laikas gerokai pailgėjo.

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Akivaizdu, kad užduotis reikia vykdyti konteineriuose arba virtualiose mašinose. Kadangi beveik visos mūsų užduotys vykdomos vienoje OS („Linux“) arba yra jai pritaikytos, mums nereikia palaikyti daug skirtingų operacinių sistemų. Atitinkamai, virtualizacija nereikalinga, dėl papildomų pridėtinių išlaidų ji bus mažiau efektyvi nei konteinerizavimas.

Kaip konteinerius, skirtus užduotims vykdyti tiesiogiai serveriuose, „Docker“ yra geras kandidatas: failų sistemos vaizdai gerai išsprendžia prieštaringų konfigūracijų problemas. Tai, kad vaizdai gali būti sudaryti iš kelių sluoksnių, leidžia žymiai sumažinti duomenų, reikalingų jiems įdiegti infrastruktūroje, kiekį, atskiriant bendras dalis į atskirus pagrindinius sluoksnius. Tada pagrindiniai (ir didžiausi) sluoksniai bus gana greitai talpinami visoje infrastruktūroje, o norint pateikti daugybę skirtingų programų ir versijų tipų, reikės perkelti tik mažus sluoksnius.

Be to, paruoštas registras ir vaizdų žymėjimas programoje „Docker“ suteikia mums paruoštų versijų kūrimo ir kodo pateikimo į gamybą primityvų.

„Docker“, kaip ir bet kuri kita panaši technologija, suteikia mums tam tikrą konteinerio izoliacijos lygį. Pavyzdžiui, atminties izoliavimas – kiekvienam konteineriui suteikiamas įrenginio atminties naudojimo limitas, kurį viršijus jis nevartos. Taip pat galite atskirti konteinerius pagal procesoriaus naudojimą. Tačiau mums nepakako standartinės izoliacijos. Bet daugiau apie tai žemiau.

Tiesioginis konteinerių paleidimas serveriuose yra tik dalis problemos. Kita dalis yra susijusi su konteinerių talpinimu serveriuose. Turite suprasti, kuris konteineris gali būti dedamas į kurį serverį. Tai nėra tokia lengva užduotis, nes konteinerius reikia dėti į serverius kuo tankiau, nesumažinant jų greičio. Toks išdėstymas taip pat gali būti sudėtingas atsparumo gedimams požiūriu. Dažnai tos pačios paslaugos kopijas norime patalpinti skirtinguose stelažuose ar net skirtingose ​​duomenų centro patalpose, kad sugedus stovui ar patalpai iš karto neprarastume visų paslaugų kopijų.

Neautomatinis konteinerių platinimas nėra išeitis, kai turite 8 tūkst. serverių ir 8-16 tūkst. konteinerių.

Be to, norėjome suteikti kūrėjams daugiau nepriklausomybės paskirstydami išteklius, kad jie patys, be administratoriaus pagalbos, galėtų priglobti savo paslaugas gamyboje. Tuo pačiu norėjome išlaikyti kontrolę, kad kuri nors nedidelė paslauga nesunaudotų visų mūsų duomenų centrų resursų.

Akivaizdu, kad mums reikia valdymo sluoksnio, kuris tai padarytų automatiškai.

Taigi priėjome prie paprasto ir suprantamo paveikslo, kurį dievina visi architektai: trys kvadratai.

Vieno debesies – duomenų centro lygio OS Odnoklassniki

one-cloud masters yra failų perkėlimo klasteris, atsakingas už debesų orkestravimą. Kūrėjas pagrindiniam kompiuteriui siunčia manifestą, kuriame yra visa informacija, reikalinga paslaugai priglobti. Remdamasis juo, kapitonas duoda komandas pasirinktiems minionams (mašinoms, skirtoms konteineriams paleisti). Minionai turi mūsų agentą, kuris gauna komandą, išduoda savo komandas Docker, o Docker sukonfigūruoja Linux branduolį, kad paleistų atitinkamą konteinerį. Be komandų vykdymo, agentas nuolat praneša pagrindiniam darbuotojui apie miniono mašinos ir joje veikiančių konteinerių būsenos pokyčius.

Išteklių paskirstymas

Dabar pažvelkime į sudėtingesnio išteklių paskirstymo daugeliui pakalikų problemą.

Skaičiavimo išteklius viename debesyje yra:

  • Procesoriaus energijos kiekis, sunaudotas atliekant konkrečią užduotį.
  • Užduočiai turimos atminties kiekis.
  • Tinklo srautas. Kiekvienas iš minionų turi tam tikrą tinklo sąsają su ribotu pralaidumu, todėl neįmanoma paskirstyti užduočių neatsižvelgiant į duomenų, kuriuos jie perduoda tinkle, kiekį.
  • Diskai. Be to, akivaizdu, kad šių užduočių vietai mes taip pat skiriame disko tipą: HDD arba SSD. Diskai gali aptarnauti ribotą užklausų skaičių per sekundę – IOPS. Todėl užduotims, kurios generuoja daugiau IOPS, nei gali apdoroti vienas diskas, taip pat skiriame „verpstus“ - tai yra, disko įrenginius, kurie turi būti išskirtinai rezervuoti užduočiai.

Tada kuriai nors paslaugai, pavyzdžiui, vartotojo talpyklai, sunaudotus resursus galime įrašyti tokiu būdu: 400 procesoriaus branduolių, 2,5 TB atminties, 50 Gbit/s srautas į abi puses, 6 TB HDD vietos, esančios ant 100 velenų. Arba labiau pažįstama forma, kaip ši:

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

Vartotojo talpyklos paslaugų ištekliai sunaudoja tik dalį visų turimų išteklių gamybos infrastruktūroje. Todėl noriu įsitikinti, kad staiga, dėl operatoriaus klaidos ar ne, vartotojo talpykla nesunaudoja daugiau resursų, nei jai skirta. Tai reiškia, kad turime riboti išteklius. Bet su kuo galėtume susieti kvotą?

Grįžkime prie mūsų labai supaprastintos komponentų sąveikos diagramos ir perbraižykime ją su daugiau detalių – pavyzdžiui:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Kas patraukia jūsų dėmesį:

  • Žiniatinklio sąsaja ir muzika naudoja atskiras to paties taikomųjų programų serverio grupes.
  • Galime atskirti loginius sluoksnius, kuriems priklauso šios klasteriai: frontai, talpyklos, duomenų saugojimo ir valdymo sluoksnis.
  • Priekinė dalis yra nevienalytė, ji susideda iš skirtingų funkcinių posistemių.
  • Talpyklos taip pat gali būti išsklaidytos posistemėje, kurios duomenis jos talpina.

Dar kartą perpieškime paveikslėlį:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Bah! Taip, mes matome hierarchiją! Tai reiškia, kad galite paskirstyti išteklius didesniais gabalais: priskirti atsakingą kūrėją šios hierarchijos mazgui, atitinkančiam funkcinį posistemį (kaip paveikslėlyje „muzika“), ir pridėti kvotą tam pačiam hierarchijos lygiui. Ši hierarchija taip pat leidžia lanksčiau organizuoti paslaugas, kad būtų lengviau valdyti. Pavyzdžiui, mes suskirstome visą žiniatinklį, nes tai yra labai didelė serverių grupė, į kelias mažesnes grupes, paveikslėlyje parodytas kaip group1, group2.

Pašalinus papildomas eilutes, kiekvieną paveikslėlio mazgą galime parašyti plokštesne forma: group1.web.front, api.muzika.priekis, user-cache.cache.

Taip pasiekiame „hierarchinės eilės“ sąvoką. Jis turi tokį pavadinimą kaip „group1.web.front“. Jai priskiriama išteklių ir vartotojo teisių kvota. Žmogui iš DevOps suteiksime teises siųsti paslaugą į eilę, ir toks darbuotojas gali ką nors paleisti eilėje, o žmogus iš OpsDev turės administratoriaus teises, o dabar jis galės tvarkyti eilę, priskirti ten žmones, suteikti šiems žmonėms teises ir pan. Šioje eilėje veikiančios paslaugos veiks pagal eilės kvotą. Jei eilės skaičiavimo kvotos neužtenka visoms paslaugoms atlikti vienu metu, tada jos bus vykdomos nuosekliai, taip suformuojant pačią eilę.

Pažvelkime į paslaugas atidžiau. Paslauga turi visiškai apibrėžtą pavadinimą, kuris visada apima eilės pavadinimą. Tada priekinė žiniatinklio paslauga turės pavadinimą ok-web.group1.web.front. Ir bus iškviesta programų serverio paslauga, kurią ji pasiekia ok-app.group1.web.front. Kiekviena paslauga turi manifestą, kuriame nurodoma visa reikalinga informacija talpinimui konkrečiuose įrenginiuose: kiek resursų sunaudoja ši užduotis, kokios konfigūracijos jai reikia, kiek turi būti kopijų, šios paslaugos gedimų tvarkymo savybės. Ir po to, kai paslauga yra patalpinta tiesiai į mašinas, atsiranda jos egzemplioriai. Jie taip pat įvardijami vienareikšmiškai – kaip egzemplioriaus numeris ir paslaugos pavadinimas: 1.ok-web.group1.web.front, 2.ok-web.group1.web.front, …

Tai labai patogu: pažvelgę ​​tik į bėgančio konteinerio pavadinimą, iš karto galime daug sužinoti.

Dabar atidžiau pažvelkime į tai, ką šie atvejai iš tikrųjų atlieka: užduotis.

Užduočių izoliavimo klasės

Visos užduotys OK (ir tikriausiai visur) gali būti suskirstytos į grupes:

  • Trumpos delsos užduotys – prod. Tokioms užduotims ir paslaugoms labai svarbus atsakymo delsimas (delsavimas), kaip greitai kiekviena iš užklausų bus apdorojama sistemoje. Užduočių pavyzdžiai: žiniatinklio fasadai, talpyklos, programų serveriai, OLTP saugykla ir kt.
  • Skaičiavimo uždaviniai – partija. Čia kiekvienos konkrečios užklausos apdorojimo greitis nėra svarbus. Jiems svarbu, kiek skaičiavimų ši užduotis atliks per tam tikrą (ilgą) laikotarpį (pralaidumą). Tai bus bet kokios „MapReduce“, „Hadoop“, mašininio mokymosi, statistikos užduotys.
  • Fono užduotys – neaktyvios. Tokioms užduotims nei delsa, nei pralaidumas nėra labai svarbūs. Tai apima įvairius bandymus, perkėlimus, perskaičiavimus ir duomenų konvertavimą iš vieno formato į kitą. Viena vertus, jie yra panašūs į apskaičiuotus, kita vertus, mums visiškai nesvarbu, kaip greitai jie baigiami.

Pažiūrėkime, kaip tokios užduotys sunaudoja išteklius, pavyzdžiui, centrinį procesorių.

Trumpos uždelsimo užduotys. Tokios užduoties procesoriaus vartojimo modelis bus panašus į šį:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Gaunamas vartotojo prašymas apdoroti, užduotis pradeda naudoti visus turimus procesoriaus branduolius, ją apdoroja, grąžina atsakymą, laukia kitos užklausos ir sustoja. Atėjo kitas prašymas - vėl išsirinkome viską, kas buvo, paskaičiavome ir laukiame kito.

Norėdami garantuoti minimalų tokios užduoties delsą, turime paimti maksimalius jos sunaudojamus išteklius ir rezervuoti reikiamą branduolių skaičių minione (mašinoje, kuri atliks užduotį). Tada mūsų problemos rezervavimo formulė bus tokia:

alloc: cpu = 4 (max)

o jei turime minionų mašiną su 16 branduolių, tai ant jos galima įdėti lygiai keturias tokias užduotis. Ypač atkreipiame dėmesį, kad vidutinis tokių užduočių procesoriaus suvartojimas dažnai yra labai mažas – tai akivaizdu, nes didelę laiko dalį užduotis laukia užklausos ir nieko nedaro.

Skaičiavimo užduotys. Jų modelis bus šiek tiek kitoks:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Vidutinis procesoriaus resursų suvartojimas tokioms užduotims yra gana didelis. Dažnai norime, kad skaičiavimo užduotis būtų atlikta per tam tikrą laiką, todėl turime rezervuoti minimalų jai reikalingą procesorių skaičių, kad visas skaičiavimas būtų atliktas per priimtiną laiką. Jo rezervavimo formulė atrodys taip:

alloc: cpu = [1,*)

„Padėkite jį ant miniono, kur yra bent vienas laisvas branduolys, ir kiek jų bus, jis viską prarys.

Čia naudojimo efektyvumas jau yra daug geresnis nei atliekant užduotis su trumpu vėlavimu. Tačiau pelnas bus daug didesnis, jei sujungsite abiejų tipų užduotis viename minioniniame įrenginyje ir paskirstysite jo išteklius kelyje. Kai užduočiai su nedideliu uždelsimu reikia procesoriaus, jis jį iškart gauna, o kai resursai nebereikalingi, jie perkeliami į skaičiavimo užduotį, t.y. maždaug taip:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Bet kaip tai padaryti?

Pirmiausia pažiūrėkime į prod ir jo aloc: cpu = 4. Turime rezervuoti keturis branduolius. „Docker“ paleidime tai galima padaryti dviem būdais:

  • Naudojant parinktį --cpuset=1-4, t. y. užduočiai paskirkite keturias konkrečias mašinos šerdis.
  • Naudokite --cpuquota=400_000 --cpuperiod=100_000, priskirkite procesoriaus laiko kvotą, t.y. nurodykite, kad kas 100 ms realaus laiko užduotis sunaudoja ne daugiau kaip 400 ms procesoriaus laiko. Gaunamos tos pačios keturios šerdys.

Bet kuris iš šių būdų yra tinkamas?

cpuset atrodo gana patraukliai. Užduotyje yra keturi tam skirti branduoliai, o tai reiškia, kad procesoriaus talpyklos veiks kuo efektyviau. Tai taip pat turi neigiamą pusę: mes turėtume imtis užduoties paskirstyti skaičiavimus per neapkrautus mašinos branduolius, o ne OS, ir tai yra gana nebanali užduotis, ypač jei bandome sudėtines užduotis tokioje sistemoje. mašina. Testai parodė, kad čia labiau tinka variantas su kvota: tokiu būdu operacinė sistema turi daugiau laisvės pasirenkant branduolį, kad atliktų užduotį esamu momentu, o procesoriaus laikas paskirstomas efektyviau.

Išsiaiškinkime, kaip rezervuoti „Docker“ pagal minimalų branduolių skaičių. Paketinių užduočių kvota nebetaikoma, nes nereikia riboti maksimumo, užtenka tik garantuoti minimumą. Ir čia variantas puikiai tinka docker run --cpushares.

Sutarėme, kad jei partijai reikalinga garantija bent vienam branduoliui, tada nurodome --cpushares=1024, o jei yra bent du branduoliai, tada nurodome --cpushares=2048. CPU akcijos jokiu būdu netrukdo paskirstyti procesoriaus laiką, kol jo yra pakankamai. Taigi, jei prod šiuo metu nenaudoja visų keturių branduolių, paketinių užduočių niekas neriboja ir jie gali naudoti papildomą procesoriaus laiką. Tačiau tais atvejais, kai trūksta procesorių, jei prod sunaudojo visus keturis branduolius ir pasiekė savo kvotą, likęs procesoriaus laikas bus padalintas proporcingai cpushares, t. y. esant trims laisviems branduoliams, vienas bus duota užduočiai su 1024 cpushares, o likusios dvi bus pateiktos užduočiai su 2048 cpushares.

Tačiau kvotos ir akcijų naudojimo neužtenka. Turime užtikrinti, kad paskirstant procesoriaus laiką užduočiai su trumpu vėlavimu būtų teikiama pirmenybė prieš paketinę užduotį. Be tokio prioriteto nustatymo, paketinė užduotis užims visą procesoriaus laiką tuo metu, kai to prireiks gamintojui. Vykdant „Docker“ nėra konteinerių prioritetų nustatymo parinkčių, tačiau „Linux“ procesoriaus planavimo priemonės yra naudingos. Galite perskaityti apie juos išsamiai čia, o šiame straipsnyje trumpai juos apžvelgsime:

  • SCHED_OTHER
    Pagal numatytuosius nustatymus gaunami visi įprasti vartotojo procesai Linux kompiuteryje.
  • SCHED_BATCH
    Sukurta daug išteklių reikalaujantiems procesams. Pateikiant užduotį procesoriui, įvedama vadinamoji aktyvinimo nuobauda: tokia užduotis mažiau tikėtina, kad gaus procesoriaus išteklius, jei šiuo metu ją naudoja užduotis su SCHED_OTHER
  • SCHED_IDLE
    Fono procesas, kurio prioritetas labai žemas, net žemesnis nei gražus –19. Mes naudojame atvirojo kodo biblioteką vienas-nio, norėdami nustatyti reikiamą politiką paleidžiant konteinerį skambinant

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

Bet net jei neprogramuojate Java, tą patį galima padaryti naudojant komandą chrt:

chrt -i 0 $pid

Aiškumo dėlei apibendrinkime visus mūsų izoliacijos lygius į vieną lentelę:

Izoliacijos klasė
Alloc pavyzdys
„Docker“ paleidimo parinktys
sched_setscheduler chrt*

Bakstelėjimas
CPU = 4
--cpuquota=400000 --cpuperiod=100000
SCHED_OTHER

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

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

*Jei atliekate chrt iš sudėtinio rodinio, jums gali prireikti sys_nice galimybės, nes pagal numatytuosius nustatymus „Docker“ pašalina šią funkciją paleidus konteinerį.

Tačiau užduotys sunaudoja ne tik procesorių, bet ir srautą, o tai dar labiau įtakoja tinklo užduoties delsą nei neteisingas procesoriaus išteklių paskirstymas. Todėl, žinoma, norime gauti lygiai tokį patį eismo vaizdą. Tai yra, kai prod užduotis siunčia kai kuriuos paketus į tinklą, mes ribojame maksimalų greitį (formulė paskirstymas: lan=[*,500mbps) ), su kuria prod gali tai padaryti. Ir partijai garantuojame tik minimalų pralaidumą, bet neribojame maksimalaus (formulė paskirstymas: lan=[10Mbps,*) ) Šiuo atveju produkcijos srautui turėtų būti teikiama pirmenybė prieš paketines užduotis.
Čia Docker neturi jokių primityvų, kuriuos galėtume naudoti. Bet tai ateina mums į pagalbą Linux eismo kontrolė. Drausmės pagalba pavyko pasiekti norimą rezultatą Hierarchinė sąžiningos paslaugos kreivė. Su jo pagalba išskiriame dvi srauto klases: aukšto prioriteto prod ir žemo prioriteto paketą / tuščiąja eiga. Dėl to išeinančio srauto konfigūracija yra tokia:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

čia 1:0 yra hsfc disciplinos "root qdisc"; 1:1 - hsfc antrinė klasė, kurios bendras pralaidumo limitas yra 8 Gbit/s, žemiau kurios yra visų konteinerių antrinės klasės; 1:2 – antrinė hsfc klasė yra bendra visoms paketinėms ir tuščiosios eigos užduotims su „dinamine“ riba, kuri aptariama toliau. Likusios hsfc antrinės klasės yra skirtos šiuo metu veikiantiems prod konteineriams, kurių ribos atitinka jų aprašus – 450 ir 400 Mbit/s. Kiekvienai hsfc klasei priskiriama qdisc eilė fq arba fq_code, priklausomai nuo Linux branduolio versijos, kad būtų išvengta paketų praradimo srauto eigoje.

Paprastai tc disciplinos teikia pirmenybę tik išeinančiam srautui. Tačiau norime teikti pirmenybę įeinančiam srautui – juk tam tikra paketinė užduotis gali lengvai pasirinkti visą įeinantį kanalą, gaudama, pavyzdžiui, didelę įvesties duomenų paketą map&reduce. Tam naudojame modulį jei, kuri sukuria virtualią ifbX sąsają kiekvienai tinklo sąsajai ir nukreipia gaunamą srautą iš sąsajos į išeinantį srautą per ifbX. Be to, ifbX atveju visos tos pačios disciplinos veikia kontroliuojant išeinantį srautą, kurio hsfc konfigūracija bus labai panaši:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Eksperimentų metu išsiaiškinome, kad hsfc rodo geriausius rezultatus, kai 1:2 neprioritetinio paketinio / tuščiosios eigos eismas minion mašinose apribojamas iki tam tikros laisvos juostos. Priešingu atveju neprioritetinis srautas turi per daug įtakos gaminių užduočių delsai. miniond nustato dabartinį laisvo pralaidumo kiekį kas sekundę, matuodamas vidutinį srauto suvartojimą atliekant visas tam tikro miniono gaminio užduotis Vieno debesies – duomenų centro lygio OS Odnoklassniki ir atimant jį iš tinklo sąsajos pralaidumo Vieno debesies – duomenų centro lygio OS Odnoklassniki su nedidele marža, t.y.

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Įeinančio ir išeinančio srauto juostos apibrėžiamos atskirai. O pagal naujas reikšmes miniond perkonfigūruoja neprioritetinės klasės ribą 1:2.

Taigi įgyvendinome visas tris izoliavimo klases: prod, batch ir idle. Šios klasės labai įtakoja užduočių atlikimo charakteristikas. Todėl nusprendėme šį atributą pastatyti hierarchijos viršuje, kad pažiūrėjus į hierarchinės eilės pavadinimą būtų iš karto aišku, su kuo mes susiduriame:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Visi mūsų draugai tinklas и muzika tada frontai pateikiami hierarchijoje pagal prod. Pavyzdžiui, į partiją patalpinkime paslaugą muzikos katalogas, kuri periodiškai sudaro takelių katalogą iš mp3 failų rinkinio, įkelto į Odnoklassniki. Neaktyvios paslaugos pavyzdys būtų muzikos transformatorius, kuris normalizuoja muzikos garsumo lygį.

Vėl pašalinus papildomas eilutes, paslaugų pavadinimus galime parašyti glausčiau, viso paslaugos pavadinimo pabaigoje pridėdami užduočių atskyrimo klasę: web.front.prod, katalogas.muzika.partija, transformatorius.muzika.tuščioji eiga.

O dabar pažiūrėję į paslaugos pavadinimą suprantame ne tik kokią funkciją ji atlieka, bet ir jos izoliacijos klasę, o tai reiškia jos kritiškumą ir t.t.

Viskas puiku, bet yra viena karti tiesa. Neįmanoma visiškai atskirti užduočių, vykdomų vienoje mašinoje.

Ką mums pavyko pasiekti: jei partija intensyviai vartoja tik CPU resursai, tada įmontuotas Linux procesoriaus planuoklis savo darbą atlieka labai gerai, o prod užduočiai įtakos praktiškai nėra. Bet jei ši paketinė užduotis pradeda aktyviai dirbti su atmintimi, tada jau atsiranda abipusė įtaka. Taip nutinka todėl, kad gamybos užduotis „išplaunama“ iš procesoriaus atminties talpyklų – dėl to padidėja talpyklos praleidimų skaičius, o procesorius lėčiau apdoroja gaminimo užduotį. Tokia paketinė užduotis gali 10 % padidinti mūsų tipinio gaminio talpyklos delsą.

Atskirti srautą dar sunkiau dėl to, kad šiuolaikinėse tinklo plokštėse yra vidinė paketų eilė. Jei paketas iš paketinės užduoties ten patenka pirmas, tada jis bus pirmasis, kuris bus perduotas kabeliu, ir nieko negalima padaryti.

Be to, iki šiol mums pavyko išspręsti tik TCP srauto prioritetų nustatymo problemą: hsfc metodas neveikia UDP. Ir net TCP srauto atveju, jei paketinė užduotis generuoja daug srauto, tai taip pat padidina gamybos užduoties delsą apie 10 %.

atsparumas gedimams

Vienas iš tikslų kuriant vieną debesį buvo pagerinti Odnoklassniki atsparumą gedimams. Todėl toliau norėčiau išsamiau apsvarstyti galimus gedimų ir avarijų scenarijus. Pradėkime nuo paprasto scenarijaus – konteinerio gedimo.

Pats konteineris gali sugesti keliais būdais. Tai gali būti koks nors eksperimentas, klaida ar manifesto klaida, dėl kurios gamybos užduotis pradeda vartoti daugiau išteklių, nei nurodyta manifeste. Turėjome atvejį: kūrėjas įdiegė vieną sudėtingą algoritmą, daug kartų jį perdirbo, persigalvojo ir taip susipainiojo, kad galiausiai problema kilo labai nebanaliu būdu. Ir kadangi prod užduotis turi didesnį prioritetą nei visos kitos tuose pačiuose minionuose, ji pradėjo eikvoti visus turimus procesoriaus išteklius. Šioje situacijoje situaciją išgelbėjo izoliacija, tiksliau – procesoriaus laiko kvota. Jei užduočiai skirta kvota, užduotis nesunaudos daugiau. Todėl paketinės ir kitos gaminių užduotys, kurios buvo vykdomos toje pačioje mašinoje, nieko nepastebėjo.

Antra galima problema – krentantis konteineris. Ir čia mus gelbsti restart politika, jas visi žino, pats „Docker“ puikiai atlieka savo darbą. Beveik visos gamybos užduotys turi nuolatinio paleidimo iš naujo politiką. Kartais „on_failure“ naudojame paketinėms užduotims arba gaminių sudėtinių rodinių derinimui.

Ką daryti, jei visas minionas nepasiekiamas?

Aišku, paleiskite konteinerį kitoje mašinoje. Įdomiausia dalis yra tai, kas atsitinka su konteineriui priskirtu IP adresu (-iais).

Konteineriams galime priskirti tuos pačius IP adresus kaip ir minionams, kuriuose veikia šie konteineriai. Tada, kai konteineris paleidžiamas kitame kompiuteryje, jo IP adresas pasikeičia ir visi klientai turi suprasti, kad konteineris persikėlė, o dabar reikia eiti kitu adresu, kuriam reikalinga atskira Service Discovery paslauga.

Paslaugų atradimas yra patogus. Rinkoje yra daugybė skirtingų gedimų tolerancijos laipsnio sprendimų, kaip organizuoti paslaugų registrą. Dažnai tokie sprendimai įgyvendina apkrovos balansavimo logiką, saugo papildomą konfigūraciją KV saugyklos pavidalu ir pan.
Tačiau norėtume išvengti atskiro registro diegimo, nes tai reikštų kritinės sistemos, kurią gamyboje naudoja visos paslaugos, įdiegimą. Tai reiškia, kad tai yra potencialus gedimo taškas, todėl jums reikia pasirinkti arba sukurti labai gedimams atsparų sprendimą, kuris akivaizdžiai yra labai sudėtingas, daug laiko reikalaujantis ir brangus.

Ir dar vienas didelis trūkumas: tam, kad mūsų senoji infrastruktūra veiktų su nauja, turėtume perrašyti absoliučiai visas užduotis, kad naudotume kažkokią Service Discovery sistemą. Darbo yra DAUG, o kai kuriose vietose tai beveik neįmanoma, kai kalbama apie žemo lygio įrenginius, kurie veikia OS branduolio lygiu arba tiesiogiai su aparatine įranga. Šios funkcijos įgyvendinimas naudojant nusistovėjusius sprendimų modelius, pvz šoninis automobilis vietomis reikštų papildomą apkrovą, kitur – eksploatacijos komplikaciją ir papildomus gedimų scenarijus. Nenorėjome visko komplikuoti, todėl nusprendėme, kad paslaugų aptikimo naudojimas yra neprivalomas.

Viename debesyje IP seka konteinerį, ty kiekvienas užduoties egzempliorius turi savo IP adresą. Šis adresas yra „statinis“: jis priskiriamas kiekvienam atvejui, kai paslauga pirmą kartą siunčiama į debesį. Jei paslauga per savo gyvavimo laikotarpį turėjo skirtingą egzempliorių skaičių, galiausiai jai bus priskirta tiek IP adresų, kiek buvo maksimalus egzempliorių skaičius.

Vėliau šie adresai nesikeičia: jie priskiriami vieną kartą ir išlieka visą gamybinės paslaugos laikotarpį. IP adresai seka konteinerius visame tinkle. Jei konteineris perkeliamas kitam minionui, tada adresas bus po jo.

Taigi paslaugos pavadinimo susiejimas su jos IP adresų sąrašu keičiasi labai retai. Jei dar kartą pažvelgsite į paslaugų egzempliorių pavadinimus, kuriuos paminėjome straipsnio pradžioje (1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, …), pastebėsime, kad jie panašūs į DNS naudojamus FQDN. Teisingai, norėdami susieti paslaugų egzempliorių pavadinimus su jų IP adresais, naudojame DNS protokolą. Be to, šis DNS grąžina visus rezervuotus visų konteinerių IP adresus – tiek veikiančių, tiek sustabdytų (tarkime, naudojamos trys kopijos ir ten rezervavome penkis adresus – bus grąžinti visi penki). Klientai, gavę šią informaciją, bandys užmegzti ryšį su visomis penkiomis kopijomis – ir taip nustatyti veikiančias. Ši prieinamumo nustatymo parinktis yra daug patikimesnė, ji neapima nei DNS, nei paslaugų aptikimo, o tai reiškia, kad nėra sudėtingų problemų, kurias reikia išspręsti užtikrinant informacijos tinkamumą ir šių sistemų atsparumą gedimams. Be to, svarbiose paslaugose, nuo kurių priklauso viso portalo veikimas, negalime naudoti DNS, o tiesiog įvesti IP adresus į konfigūraciją.

Tokio IP perdavimo už konteinerių įgyvendinimas gali būti nereikšmingas – ir pažiūrėsime, kaip tai veikia pagal šį pavyzdį:

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Tarkime, vieno debesies meistras duoda komandą minionui M1 paleisti 1.ok-web.group1.web.front.prod su adresu 1.1.1.1. Dirba ant miniono PAUKŠTIS, kuri reklamuoja šį adresą specialiuose serveriuose maršruto atšvaitas. Pastarieji turi BGP seansą su tinklo aparatine įranga, į kurią verčiamas M1.1.1.1 adreso 1 maršrutas. M1 nukreipia paketus konteinerio viduje naudojant Linux. Yra trys maršruto atspindžio serveriai, nes tai labai svarbi vieno debesies infrastruktūros dalis – be jų tinklas viename debesyje neveiks. Mes dedame juos į skirtingus stovus, jei įmanoma, skirtingose ​​duomenų centro patalpose, kad sumažintume tikimybę, kad visi trys suges vienu metu.

Tarkime, kad ryšys tarp vieno debesies meistro ir M1 miniono nutrūko. Vieno debesies meistras dabar veiks remdamasis prielaida, kad M1 visiškai sugedo. Tai yra, jis duos komandą M2 minionui paleisti web.group1.web.front.prod tuo pačiu adresu 1.1.1.1. Dabar tinkle yra du prieštaraujantys 1.1.1.1 maršrutai: M1 ir M2. Norėdami išspręsti tokius konfliktus, naudojame Multi Exit Discriminator, kuris nurodytas BGP pranešime. Tai skaičius, rodantis reklamuojamo maršruto svorį. Tarp nesuderinamų maršrutų bus pasirinktas maršrutas, kurio MED reikšmė mažesnė. Vieno debesies pagrindinis kompiuteris palaiko MED kaip sudėtinę konteinerio IP adresų dalį. Pirmą kartą adresas rašomas pakankamai dideliu MED = 1 000 000. Tokio avarinio konteinerio perkėlimo situacijoje meistras sumažina MED, o M2 jau gaus komandą reklamuoti adresą 1.1.1.1 su MED = 999 999. M1 einantis egzempliorius liks šiuo atveju ryšio nėra, o tolimesnis jo likimas mus mažai domina, kol nebus atkurtas ryšys su meistru, kai jis bus sustabdytas kaip senas paėmimas.

nelaimingų atsitikimų

Visos duomenų centrų valdymo sistemos visada priimtinai tvarko nedidelius gedimus. Konteinerio perpildymas yra norma beveik visur.

Pažiūrėkime, kaip elgiamės avarijos atveju, pvz., dingus maitinimui viename ar daugiau duomenų centro patalpų.

Ką duomenų centro valdymo sistemai reiškia avarija? Visų pirma, tai didžiulis vienkartinis daugelio mašinų gedimas, o valdymo sistema vienu metu turi migruoti daug konteinerių. Bet jei nelaimė yra labai didelės apimties, gali atsitikti taip, kad visų užduočių nepavyks perskirstyti kitiems pakalikai, nes duomenų centro resursų talpa nukrenta žemiau 100% apkrovos.

Dažnai avarijas lydi valdymo sluoksnio gedimas. Taip gali nutikti dėl jos įrangos gedimo, bet dažniau dėl to, kad avarijos nėra testuojamos, o dėl padidėjusios apkrovos krenta pats kontrolinis sluoksnis.

Ką tu gali padaryti dėl viso to?

Masinis perkėlimas reiškia, kad infrastruktūroje vyksta daug veiklos, perkėlimų ir diegimų. Kiekvienas perkėlimas gali užtrukti šiek tiek laiko, reikalingo konteinerių vaizdams pristatyti ir išpakuoti minionams, paleisti ir inicijuoti konteinerius ir pan. Todėl pageidautina, kad svarbesnės užduotys būtų pradėtos prieš mažiau svarbias.

Dar kartą pažvelkime į mums pažįstamų paslaugų hierarchiją ir pabandykime nuspręsti, kurias užduotis norime vykdyti pirmiausia.

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Žinoma, tai procesai, kurie tiesiogiai susiję su vartotojų užklausų apdorojimu, t.y. prod. Mes tai nurodome su vietos prioritetas — numeris, kurį galima priskirti eilei. Jei eilė turi aukštesnį prioritetą, jos paslaugos pateikiamos pirmiausia.

Prod priskiriame aukštesnius prioritetus, 0; partijoje - šiek tiek mažesnis, 100; tuščiąja eiga – dar žemesnė, 200. Prioritetai taikomi hierarchiškai. Visos užduotys, esančios žemiau hierarchijos, turės atitinkamą prioritetą. Jei norime, kad prod talpyklos būtų paleistos prieš sąsajas, priskyrime prioritetus talpyklai = 0 ir priekinėms antrinėms eilėms = 1. Jei, pavyzdžiui, norime, kad pagrindinis portalas būtų paleistas pirmiausia iš priekio, o tik muzikos frontas. tada pastarajam galime priskirti žemesnį prioritetą – 10.

Kita problema – išteklių trūkumas. Taigi sugedo didelis kiekis technikos, ištisos duomenų centro salės ir mes iš naujo paleidome tiek paslaugų, kad dabar resursų visiems neužtenka. Turite nuspręsti, kurias užduotis paaukoti, kad pagrindinės svarbios paslaugos veiktų.

Vieno debesies – duomenų centro lygio OS Odnoklassniki

Skirtingai nuo išdėstymo prioriteto, negalime beatodairiškai paaukoti visų paketinių užduočių, kai kurios iš jų yra svarbios portalo veikimui. Todėl mes pabrėžėme atskirai pirmumo pirmenybė užduotys. Įdėjus aukštesnio prioriteto užduotį, ji gali užbėgti už akių, t. y. sustabdyti žemesnio prioriteto užduotį, jei nebėra laisvų pakalikų. Tokiu atveju žemo prioriteto užduotis greičiausiai liks nepadėta, t.y. nebeliks jai tinkamo miniono, turinčio pakankamai laisvų resursų.

Mūsų hierarchijoje labai paprasta nurodyti išankstinio pasirinkimo prioritetą, kad gamybos ir paketų užduotys užkirstų kelią arba sustabdytų neaktyvias užduotis, bet ne viena kitą, nurodant tuščiosios eigos prioritetą, lygų 200. Kaip ir paskirties vietos prioriteto atveju, mes gali naudoti mūsų hierarchiją, kad apibūdintų sudėtingesnes taisykles. Pavyzdžiui, nurodykime, kad aukojame muzikos funkciją, jei neturime pakankamai resursų pagrindiniam interneto portalui, atitinkamų mazgų prioritetą nustatydami žemesnį: 10.

Ištisos nuolatinės srovės avarijos

Kodėl gali sugesti visas duomenų centras? Elementas. Geras postas buvo uraganas paveikė duomenų centro darbą. Elementais galima laikyti benamius, kurie kadaise degino optiką kolektoriuje, o duomenų centras visiškai prarado ryšį su kitomis svetainėmis. Gedimo priežastis gali būti ir žmogiškasis faktorius: operatorius duos tokią komandą, kad visas duomenų centras sugrius. Taip gali nutikti dėl didelės klaidos. Apskritai duomenų centrų griūtis nėra neįprasta. Pas mus taip nutinka kartą per kelis mėnesius.

Ir tai mes darome, kad niekas negalėtų tviteryje skelbti #alive.

Pirmoji strategija yra izoliacija. Kiekvienas vieno debesies egzempliorius yra izoliuotas ir gali valdyti įrenginius tik viename duomenų centre. Tai reiškia, kad debesies praradimas dėl klaidų ar neteisingų operatoriaus komandų yra tik vieno duomenų centro praradimas. Esame tam pasiruošę: turime atleidimo politiką, pagal kurią programos ir duomenų kopijos yra visuose duomenų centruose. Naudojame gedimams atsparias duomenų bazes ir periodiškai tikriname, ar nėra gedimų.
Nuo šiandien turime keturis duomenų centrus, tai reiškia keturis atskirus, visiškai izoliuotus vieno debesies atvejus.

Šis metodas ne tik apsaugo nuo fizinių gedimų, bet ir gali apsaugoti nuo operatoriaus klaidų.

Ką dar galima padaryti su žmogiškuoju faktoriumi? Kai operatorius debesiui duoda kokią nors keistą ar potencialiai pavojingą komandą, jo staiga gali būti paprašyta išspręsti nedidelę problemą, kad pamatytų, kaip gerai jis galvojo. Pavyzdžiui, jei tai yra kažkoks masinis daugelio kopijų sustabdymas arba tiesiog keista komanda - sumažinti kopijų skaičių arba pakeisti vaizdo pavadinimą, o ne tik versijos numerį naujame manifeste.

Vieno debesies – duomenų centro lygio OS Odnoklassniki

rezultatai

Išskirtiniai vieno debesies bruožai:

  • Hierarchinė ir vizualinė paslaugų ir konteinerių pavadinimų schema, kuri leidžia labai greitai išsiaiškinti, kokia yra užduotis, su kuo ji susijusi ir kaip ji veikia bei kas už ją atsakinga.
  • Mes taikome savo gaminių ir partijų derinimo technikapakalikų užduotis, siekiant pagerinti dalijimosi mašinomis efektyvumą. Vietoj cpuset naudojame procesoriaus kvotas, bendrinimus, procesoriaus planavimo politiką ir Linux QoS.
  • Visiškai izoliuoti ta pačia mašina veikiančių konteinerių nepavyko, tačiau jų tarpusavio įtaka išlieka 20 % ribose.
  • Paslaugų suskirstymas į hierarchiją padeda automatiškai atkurti nelaimės atveju įdėjimo ir pirmumo prioritetai.

DUK

Kodėl nepriėmėme paruošto sprendimo?

  • Skirtingoms užduočių izoliavimo klasėms reikalinga skirtinga logika, kai jie yra pakalikai. Jei gamybos užduotis galima įdėti paprasčiausiai rezervuojant išteklius, reikia įdėti paketines ir tuščiosios eigos užduotis, stebint faktinį išteklių panaudojimą minioninėse mašinose.
  • Poreikis atsižvelgti į išteklius, sunaudojamus atliekant užduotis, pavyzdžiui:
    • tinklo pralaidumas;
    • diskų tipai ir „verpstės“.
  • Poreikis nurodyti paslaugų prioritetus reaguojant į ekstremalias situacijas, resursų komandų teises ir kvotas, kuris sprendžiamas naudojant hierarchines eiles viename debesyje.
  • Būtinybė, kad konteineriai būtų pavadinti žmogaus vardu, kad sutrumpėtų reagavimo į avarijas ir incidentus laikas
  • Neįmanoma vienkartinio plačiai įdiegti Service Discovery; poreikis ilgą laiką egzistuoti kartu su užduotimis, esančiomis aparatūros pagrindiniuose kompiuteriuose - tai išsprendžiama „statiniais“ IP adresais, einančiomis po konteinerius, ir dėl to unikalios integracijos su didele tinklo infrastruktūra poreikis.

Visos šios funkcijos pareikalautų reikšmingų esamų sprendimų modifikacijų, kad mums tiktų, o įvertinę darbų kiekį supratome, kad galime sukurti savo sprendimą su maždaug tokiomis pačiomis darbo sąnaudomis. Tačiau jūsų sprendimą bus daug lengviau valdyti ir plėtoti – jame nėra nereikalingų abstrakcijų, palaikančių mums nereikalingą funkcionalumą.

Tiems, kurie skaito paskutines eilutes, ačiū už kantrybę ir dėmesį!

Šaltinis: www.habr.com

Добавить комментарий