One-cloud - OS na razini podatkovnog centra u Odnoklassniki

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Aloha ljudi! Moje ime je Oleg Anastasyev, radim u Odnoklassniki u timu Platforme. A osim mene, u Odnoklassniki radi puno hardvera. Imamo četiri podatkovna centra s oko 500 rakova s ​​više od 8 tisuća servera. U određenom smo trenutku shvatili da će nam uvođenje novog sustava upravljanja omogućiti učinkovitije učitavanje opreme, olakšati upravljanje pristupom, automatizirati (pre)distribuciju računalnih resursa, ubrzati pokretanje novih usluga i ubrzati odgovore do nesreća velikih razmjera.

Što je iz toga proizašlo?

Osim mene i hrpe hardvera, tu su i ljudi koji rade s tim hardverom: inženjeri koji su smješteni izravno u podatkovnim centrima; mrežni stručnjaci koji postavljaju mrežni softver; administratori ili SRE koji pružaju otpornost infrastrukture; i razvojnih timova, svaki od njih odgovoran je za dio funkcija portala. Softver koji su izradili radi otprilike ovako:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Zahtjevi korisnika primaju se na obje strane glavnog portala www.ok.ru, i na drugima, na primjer na pročeljima glazbenog API-ja. Za obradu poslovne logike pozivaju aplikacijski poslužitelj koji prilikom obrade zahtjeva poziva potrebne specijalizirane mikroservise - one-graph (graf društvenih veza), user-cache (cache korisničkih profila) itd.

Svaki od ovih servisa raspoređen je na više strojeva, a svaki od njih ima odgovorne programere odgovorne za funkcioniranje modula, njihov rad i tehnološki razvoj. Svi ti servisi rade na hardverskim poslužiteljima, a donedavno smo pokretali točno jedan task po poslužitelju, odnosno bio je specijaliziran za određeni zadatak.

Zašto je to? Ovaj pristup je imao nekoliko prednosti:

  • Laknulo masovno upravljanje. Recimo da zadatak zahtijeva neke biblioteke, neke postavke. Zatim se poslužitelj dodjeljuje točno jednoj specifičnoj grupi, cfengine politika za ovu grupu je opisana (ili je već opisana), a ova konfiguracija se centralno i automatski uvodi na sve poslužitelje u ovoj grupi.
  • Pojednostavljeno dijagnostika. Recimo da pogledate povećano opterećenje središnjeg procesora i shvatite da to opterećenje može proizvesti samo zadatak koji se izvodi na tom hardverskom procesoru. Potraga za nekim koga će se okriviti završava vrlo brzo.
  • Pojednostavljeno nadgledanje. Ako nešto nije u redu s serverom, monitor to javlja i točno se zna tko je kriv.

Usluzi koja se sastoji od nekoliko replika dodijeljeno je nekoliko poslužitelja - po jedan za svaki. Zatim se računalni resurs za uslugu dodjeljuje vrlo jednostavno: broj poslužitelja koje usluga ima, maksimalna količina resursa koju može potrošiti. “Lako” ovdje ne znači da je jednostavno za korištenje, već u smislu da se dodjela resursa vrši ručno.

Ovaj nam je pristup također omogućio specijalizirane konfiguracije željeza za zadatak koji se izvodi na ovom poslužitelju. Ako zadatak pohranjuje velike količine podataka, tada koristimo 4U poslužitelj s kućištem s 38 diskova. Ako je zadatak isključivo računalni, tada možemo kupiti jeftiniji 1U poslužitelj. Ovo je računalno učinkovito. Između ostalog, ovaj nam pristup omogućuje korištenje četiri puta manje strojeva s opterećenjem usporedivim s jednom prijateljskom društvenom mrežom.

Takva učinkovitost u korištenju računalnih resursa trebala bi osigurati i ekonomsku učinkovitost, ako pođemo od toga da su najskuplja stvar poslužitelji. Dugo vremena hardver je bio najskuplji, a mi smo uložili puno truda u smanjenje cijene hardvera, osmislivši algoritme tolerancije grešaka kako bismo smanjili zahtjeve za pouzdanošću hardvera. A danas smo došli do faze u kojoj je cijena servera prestala biti odlučujuća. Ako ne uzmete u obzir najnoviju egzotiku, tada specifična konfiguracija poslužitelja u stalku nije bitna. Sada imamo još jedan problem - cijenu prostora koji server zauzima u podatkovnom centru, odnosno prostora u rack-u.

Shvativši da je to slučaj, odlučili smo izračunati koliko učinkovito koristimo police.
Uzeli smo cijenu najsnažnijeg poslužitelja od onih ekonomski opravdanih, izračunali koliko takvih poslužitelja možemo smjestiti u regale, koliko bismo zadataka na njima izvodili po starom modelu “jedan poslužitelj = jedan zadatak” i koliko takvih zadaci mogu koristiti opremu. Brojali su i suze lili. Ispostavilo se da je naša učinkovitost u korištenju regala oko 11%. Zaključak je očit: moramo povećati učinkovitost korištenja podatkovnih centara. Čini se da je rješenje očito: trebate pokrenuti nekoliko zadataka na jednom poslužitelju odjednom. Ali tu počinju poteškoće.

Masovna konfiguracija postaje dramatično kompliciranija - sada je nemoguće dodijeliti bilo koju grupu poslužitelju. Uostalom, sada se na jednom poslužitelju može pokrenuti nekoliko zadataka različitih naredbi. Osim toga, konfiguracija može biti u sukobu za različite aplikacije. Dijagnostika također postaje kompliciranija: ako vidite povećanu potrošnju procesora ili diska na poslužitelju, ne znate koji zadatak uzrokuje probleme.

Ali glavna stvar je da nema izolacije između zadataka koji se izvode na istom stroju. Evo, na primjer, grafikona prosječnog vremena odgovora zadatka poslužitelja prije i nakon što je druga računalna aplikacija pokrenuta na istom poslužitelju, ni na koji način povezana s prvom - vrijeme odgovora glavnog zadatka se značajno povećalo.

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Očito je da morate pokretati zadatke ili u spremnicima ili u virtualnim strojevima. Budući da se gotovo svi naši zadaci izvode pod jednim OS-om (Linux) ili su za njega prilagođeni, ne moramo podržavati mnogo različitih operativnih sustava. Sukladno tome, virtualizacija nije potrebna; zbog dodatnih troškova bit će manje učinkovita od kontejnerizacije.

Kao implementacija spremnika za izvršavanje zadataka izravno na poslužiteljima, Docker je dobar kandidat: slike datotečnog sustava dobro rješavaju probleme s proturječnim konfiguracijama. Činjenica da slike mogu biti sastavljene od nekoliko slojeva omogućuje nam značajno smanjenje količine podataka potrebnih za njihovu implementaciju na infrastrukturu, odvajajući zajedničke dijelove u zasebne osnovne slojeve. Zatim će osnovni (i najobimniji) slojevi biti predmemorirani prilično brzo kroz cijelu infrastrukturu, a za isporuku mnogo različitih tipova aplikacija i verzija, trebat će se prenijeti samo mali slojevi.

Osim toga, gotov registar i označavanje slika u Dockeru daju nam gotove primitive za izradu verzija i isporuku koda u proizvodnju.

Docker, kao i bilo koja druga slična tehnologija, pruža nam određenu razinu izolacije spremnika odmah po otvaranju. Na primjer, izolacija memorije - svaki spremnik ima ograničenje upotrebe strojne memorije, izvan kojeg neće trošiti. Također možete izolirati spremnike na temelju upotrebe CPU-a. Nama, međutim, standardna izolacija nije bila dovoljna. Ali o tome više u nastavku.

Izravno pokretanje spremnika na poslužiteljima samo je dio problema. Drugi dio se odnosi na smještaj kontejnera na poslužiteljima. Morate razumjeti koji se spremnik može postaviti na koji poslužitelj. To i nije tako lak zadatak, jer kontejnere treba postaviti na servere što gušće, a da im se ne smanji brzina. Takvo postavljanje također može biti teško s gledišta tolerancije na greške. Često želimo smjestiti replike iste usluge u različite police ili čak u različite prostorije podatkovnog centra, tako da ako stalak ili soba zakaže, ne bismo odmah izgubili sve replike usluge.

Ručna distribucija spremnika nije opcija kada imate 8 tisuća poslužitelja i 8-16 tisuća spremnika.

Osim toga, htjeli smo programerima dati više neovisnosti u dodjeli resursa kako bi mogli sami ugostiti svoje usluge u proizvodnji, bez pomoći administratora. Istovremeno smo željeli zadržati kontrolu kako neka manja usluga ne bi pojela sve resurse naših podatkovnih centara.

Očito, potreban nam je kontrolni sloj koji bi to radio automatski.

Tako smo došli do jednostavne i razumljive slike koju obožavaju svi arhitekti: tri kvadrata.

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

one-cloud masters je failover klaster odgovoran za orkestraciju oblaka. Razvojni programer šalje manifest masteru koji sadrži sve podatke potrebne za hostiranje usluge. Na temelju njega, majstor daje naredbe odabranim minionima (strojevi dizajnirani za pokretanje kontejnera). Minioni imaju našeg agenta, koji prima naredbu, izdaje svoje naredbe Dockeru, a Docker konfigurira Linux kernel za pokretanje odgovarajućeg spremnika. Osim izvršavanja naredbi, agent kontinuirano izvješćuje mastera o promjenama u stanju i minion stroja i spremnika koji rade na njemu.

Raspredelenie resursov

Sada pogledajmo problem složenije raspodjele resursa za mnoge miljenike.

Računalni resurs u jednom oblaku je:

  • Količina snage procesora koju troši određeni zadatak.
  • Količina memorije dostupna za zadatak.
  • Mrežni promet. Svaki od miniona ima specifično mrežno sučelje s ograničenom propusnošću, tako da je nemoguće distribuirati zadatke bez uzimanja u obzir količine podataka koje prenose preko mreže.
  • Diskovi. Osim, očito, prostoru za ove zadatke također dodjeljujemo i vrstu diska: HDD ili SSD. Diskovi mogu poslužiti konačan broj zahtjeva u sekundi - IOPS. Stoga, za zadatke koji generiraju više IOPS-a nego što jedan disk može podnijeti, također dodjeljujemo "vretena" - to jest diskovne uređaje koji moraju biti isključivo rezervirani za zadatak.

Zatim za neku uslugu, na primjer za user-cache, možemo evidentirati potrošene resurse na ovaj način: 400 procesorskih jezgri, 2,5 TB memorije, 50 Gbit/s prometa u oba smjera, 6 TB prostora na HDD-u smještenom na 100 vretena. Ili u poznatijem obliku poput ovog:

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

Resursi usluge korisničke predmemorije troše samo dio svih dostupnih resursa u proizvodnoj infrastrukturi. Stoga, želim biti siguran da iznenada, zbog pogreške operatera ili ne, korisnička predmemorija ne troši više resursa nego što su joj dodijeljeni. Odnosno, moramo ograničiti resurse. Ali za što bismo mogli vezati kvotu?

Vratimo se našem uvelike pojednostavljenom dijagramu interakcije komponenti i ponovno ga nacrtajmo s više detalja - ovako:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Ono što upada u oči:

  • Web sučelje i glazba koriste izolirane klastere istog poslužitelja aplikacija.
  • Možemo razlikovati logičke slojeve kojima ovi klasteri pripadaju: frontovi, predmemorije, pohrana podataka i sloj upravljanja.
  • Sučelje je heterogeno, sastoji se od različitih funkcionalnih podsustava.
  • Predmemorije također mogu biti raštrkane po podsustavu čije podatke spremaju u predmemoriju.

Ponovno nacrtajmo sliku:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Bah! Da, vidimo hijerarhiju! To znači da resurse možete distribuirati u većim dijelovima: dodijelite odgovornog programera čvoru ove hijerarhije koji odgovara funkcionalnom podsustavu (kao što je "glazba" na slici) i priložite kvotu istoj razini hijerarhije. Ova hijerarhija također nam omogućuje da fleksibilnije organiziramo usluge radi lakšeg upravljanja. Na primjer, cijeli web dijelimo, budući da se radi o vrlo velikom grupiranju poslužitelja, u nekoliko manjih grupa, prikazanih na slici kao grupa1, grupa2.

Uklanjanjem dodatnih linija, svaki čvor naše slike možemo napisati u ravnijem obliku: grupa1.web.front, api.glazba.front, korisnički-cache.cache.

Tako dolazimo do koncepta "hijerarhijskog reda čekanja". Ima naziv poput "group1.web.front". Dodijeljena mu je kvota za resurse i korisnička prava. Dat ćemo osobi iz DevOps-a prava da pošalje uslugu u red čekanja, i takav zaposlenik može pokrenuti nešto u redu čekanja, a osoba iz OpsDeva će imati administratorska prava, i sada može upravljati redom čekanja, dodjeljivati ​​ljude tamo, dati tim ljudima prava, itd. Usluge koje se izvode u ovom redu čekanja izvodit će se unutar kvote reda. Ako računska kvota reda nije dovoljna za izvršenje svih usluga odjednom, tada će se one izvršavati sekvencijalno, formirajući tako sam red.

Pogledajmo pobliže usluge. Usluga ima potpuno kvalificirano ime, koje uvijek uključuje ime reda čekanja. Tada će prednja web usluga imati naziv ok-web.group1.web.front. Pozvat će se usluga aplikacijskog poslužitelja kojoj pristupa ok-app.group1.web.front. Svaka usluga ima manifest koji navodi sve potrebne informacije za postavljanje na određene strojeve: koliko resursa ovaj zadatak troši, koja je konfiguracija potrebna za njega, koliko replika treba biti, svojstva za rukovanje kvarovima ove usluge. A nakon što se usluga postavi izravno na strojeve, pojavljuju se njezine instance. Također su imenovani nedvosmisleno - kao broj instance i naziv usluge: 1.ok-web.group1.web.front, 2.ok-web.group1.web.front, …

Ovo je vrlo zgodno: gledajući samo naziv spremnika koji radi, možemo odmah saznati mnogo toga.

Sada pogledajmo pobliže što ove instance zapravo obavljaju: zadatke.

Izolacija zadataka

Svi zadaci u OK (i, vjerojatno, svugdje) mogu se podijeliti u grupe:

  • Zadaci s kratkim kašnjenjem - prod. Za takve zadatke i usluge vrlo je važno kašnjenje odgovora (latencija), koliko brzo će svaki od zahtjeva biti procesuiran od strane sustava. Primjeri zadataka: web frontovi, predmemorije, aplikacijski poslužitelji, OLTP pohrana itd.
  • Računski problemi - serija. Ovdje nije bitna brzina obrade svakog konkretnog zahtjeva. Za njih je važno koliko će izračuna ovaj zadatak napraviti u određenom (dugom) vremenskom razdoblju (propusnost). To će biti bilo koji zadaci MapReduce, Hadoop, strojno učenje, statistika.
  • Pozadinski zadaci - mirovanje. Za takve zadatke ni latencija ni propusnost nisu jako važni. To uključuje različite testove, migracije, ponovne izračune i konverziju podataka iz jednog formata u drugi. S jedne strane, slični su kalkuliranim, s druge strane nije nam bitno koliko brzo se završe.

Pogledajmo kako takvi zadaci troše resurse, na primjer, središnji procesor.

Zadaci s kratkim odgodama. Takav će zadatak imati obrazac potrošnje CPU-a sličan ovome:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Zahtjev od korisnika prima se na obradu, zadatak počinje koristiti sve dostupne CPU jezgre, obrađuje ga, vraća odgovor, čeka sljedeći zahtjev i zaustavlja se. Stigao je sljedeći zahtjev - opet smo odabrali sve što je bilo, izračunali i čekamo sljedeći.

Kako bismo zajamčili minimalnu latenciju za takav zadatak, moramo uzeti maksimum resursa koje on troši i rezervirati potreban broj jezgri na miljeu (stroj koji će izvršiti zadatak). Tada će formula rezervacije za naš problem biti sljedeća:

alloc: cpu = 4 (max)

a ako imamo minion stroj sa 16 jezgri, onda se na njega mogu staviti točno četiri takva zadatka. Posebno napominjemo da je prosječna potrošnja procesora kod ovakvih zadataka često vrlo niska – što je i vidljivo, jer značajan dio vremena zadatak čeka na zahtjev i ne radi ništa.

Računski zadaci. Njihov će uzorak biti malo drugačiji:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Prosječna potrošnja CPU resursa za takve zadatke je prilično visoka. Često želimo da se računski zadatak dovrši u određenom vremenu, pa moramo rezervirati minimalni broj procesora koji mu je potreban kako bi cijeli izračun bio dovršen u prihvatljivom vremenu. Njegova formula za rezervaciju izgledat će ovako:

alloc: cpu = [1,*)

"Molim vas, postavite ga na miljenika gdje postoji barem jedna slobodna jezgra, a onda koliko god ih ima, proždrijet će sve."

Ovdje je učinkovitost korištenja već puno bolja nego na zadacima s kratkom odgodom. Ali dobitak će biti puno veći ako obje vrste zadataka kombinirate na jednom stroju za minione i distribuirate njegove resurse u pokretu. Kada zadatak s kratkom odgodom zahtijeva procesor, on ga odmah prima, a kada resursi više nisu potrebni, prebacuju se na računski zadatak, tj. ovako:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Ali kako to učiniti?

Prvo, pogledajmo prod i njegov alloc: cpu = 4. Moramo rezervirati četiri jezgre. U Docker run to se može učiniti na dva načina:

  • S opcijom --cpuset=1-4, tj. dodijelite četiri određene jezgre na stroju za zadatak.
  • Za korištenje --cpuquota=400_000 --cpuperiod=100_000, dodijeliti kvotu za procesorsko vrijeme, tj. naznačiti da svakih 100 ms stvarnog vremena zadatak ne troši više od 400 ms procesorskog vremena. Dobivaju se iste četiri jezgre.

Ali koja je od ovih metoda prikladna?

cpuset izgleda prilično privlačno. Zadatak ima četiri namjenske jezgre, što znači da će predmemorije procesora raditi što učinkovitije. Ovo ima i lošu stranu: morali bismo preuzeti zadatak distribucije izračuna po neopterećenim jezgrama stroja umjesto OS-a, a to je prilično netrivijalan zadatak, pogotovo ako pokušamo staviti paketne zadatke na takav mašina. Testovi su pokazali da je opcija s kvotom prikladnija ovdje: na taj način operativni sustav ima više slobode u odabiru jezgre za obavljanje zadatka u trenutnom trenutku, a procesorsko vrijeme se učinkovitije raspoređuje.

Smislimo kako napraviti rezervacije u Dockeru na temelju minimalnog broja jezgri. Kvota za paketne zadatke više nije primjenjiva, jer nema potrebe ograničavati maksimum, dovoljno je samo zajamčiti minimum. I ovdje se opcija dobro uklapa docker run --cpushares.

Dogovorili smo se da ako serija zahtijeva jamstvo za barem jednu jezgru, tada ćemo to navesti --cpushares=1024, a ako postoje najmanje dvije jezgre, tada označavamo --cpushares=2048. CPU dionice ni na koji način ne ometaju raspodjelu procesorskog vremena sve dok ga ima dovoljno. Dakle, ako prod trenutno ne koristi sve svoje četiri jezgre, ništa ne ograničava skupne zadatke i oni mogu koristiti dodatno vrijeme procesora. Ali u situaciji kada postoji manjak procesora, ako je prod potrošio sve svoje četiri jezgre i dostigao svoju kvotu, preostalo procesorsko vrijeme će se podijeliti proporcionalno na cpushares, tj. u situaciji s tri slobodne jezgre, jedna će biti dano zadatku s 1024 cpusharea, a preostala dva bit će dana zadatku s 2048 cpusharea.

Ali korištenje kvota i dionica nije dovoljno. Moramo osigurati da zadatak s kratkom odgodom dobije prioritet nad skupnim zadatkom prilikom dodjele procesorskog vremena. Bez takvog određivanja prioriteta, skupni zadatak će zauzeti svo vrijeme procesora u trenutku kada je potrebno proizvodu. Ne postoje opcije prioritizacije spremnika u Docker run-u, ali pravila Linux CPU planera dobro dolaze. Možete pročitati o njima u detalje ovdje, au okviru ovog članka ćemo ih ukratko proći:

  • SCHED_OTHER
    Prema zadanim postavkama, svi normalni korisnički procesi na Linux stroju primaju.
  • SCHED_BATCH
    Dizajniran za procese koji zahtijevaju velike resurse. Prilikom postavljanja zadatka na procesor, uvodi se takozvana aktivacijska kazna: manja je vjerojatnost da će takav zadatak primiti resurse procesora ako ga trenutno koristi zadatak sa SCHED_OTHER
  • SCHED_IDLE
    Pozadinski proces s vrlo niskim prioritetom, čak nižim od lijepog -19. Koristimo našu knjižnicu otvorenog koda jedan-nio, kako biste postavili potrebnu politiku prilikom pokretanja spremnika pozivom

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

Ali čak i ako ne programirate u Javi, ista se stvar može učiniti pomoću naredbe chrt:

chrt -i 0 $pid

Sažmimo sve naše razine izolacije u jednu tablicu radi jasnoće:

Klasa izolacije
Primjer dodijeli
Opcije pokretanja Dockera
sched_setscheduler chrt*

Podsticaj
procesor = 4
--cpuquota=400000 --cpuperiod=100000
SCHED_OTHER

Serija
Cpu = [1, *)
--cpushares=1024
SCHED_BATCH

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

*Ako radite chrt iz spremnika, možda će vam trebati mogućnost sys_nice jer prema zadanim postavkama Docker uklanja ovu mogućnost prilikom pokretanja spremnika.

Ali zadaci ne troše samo procesor, već i promet, što utječe na latenciju mrežnog zadatka čak i više nego netočna dodjela resursa procesora. Stoga, naravno, želimo dobiti potpuno istu sliku za promet. To jest, kada prod zadatak šalje neke pakete na mrežu, ograničavamo maksimalnu brzinu (formula alloc: lan=[*,500mbps) ), s kojim prod to može učiniti. A za seriju jamčimo samo minimalni protok, ali ne ograničavamo maksimum (formula dodijeli: lan=[10Mbps,*) ) U ovom bi slučaju proizvodni promet trebao imati prioritet nad skupnim zadacima.
Ovdje Docker nema primitivne elemente koje možemo koristiti. Ali dolazi nam u pomoć Linux kontrola prometa. Uz pomoć discipline uspjeli smo doći do željenog rezultata Hijerarhijska krivulja poštene usluge. Uz njegovu pomoć razlikujemo dvije klase prometa: visokoprioritetni prod i niskoprioritetni batch/idle. Kao rezultat toga, konfiguracija za odlazni promet je ovakva:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

ovdje je 1:0 "korijenski qdisc" hsfc discipline; 1:1 - hsfc podređena klasa s ukupnim ograničenjem propusnosti od 8 Gbit/s, ispod koje se nalaze podređene klase svih spremnika; 1:2 - hsfc podređena klasa zajednička je za sve skupne i neaktivne zadatke s "dinamičkim" ograničenjem, o čemu se govori u nastavku. Preostale hsfc podređene klase su namjenske klase za trenutačno pokrenute proizvodne spremnike s ograničenjima koja odgovaraju njihovim manifestima - 450 i 400 Mbit/s. Svakoj hsfc klasi dodijeljen je qdisc red čekanja fq ili fq_codel, ovisno o verziji Linux kernela, kako bi se izbjegao gubitak paketa tijekom izbijanja prometa.

Tipično, tc discipline služe za određivanje prioriteta samo odlaznog prometa. Ali mi također želimo dati prioritet dolaznom prometu - uostalom, neki skupni zadatak može lako odabrati cijeli dolazni kanal, primajući, na primjer, veliki skup ulaznih podataka za map&reduce. Za to koristimo modul akob, koji stvara ifbX virtualno sučelje za svako mrežno sučelje i preusmjerava dolazni promet sa sučelja na odlazni promet na ifbX. Nadalje, za ifbX, sve iste discipline rade na kontroli odlaznog prometa, za koji će hsfc konfiguracija biti vrlo slična:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Tijekom eksperimenata otkrili smo da hsfc pokazuje najbolje rezultate kada je 1:2 klasa neprioritetnog paketnog/neaktivnog prometa ograničena na minion strojevima na najviše određenu slobodnu traku. Inače, neprioritetni promet ima previše utjecaja na latenciju prod zadataka. miniond utvrđuje trenutnu količinu slobodnog propusnog opsega svake sekunde, mjereći prosječnu potrošnju prometa svih prod-zadataka određenog miljea One-cloud - OS na razini podatkovnog centra u Odnoklassniki i oduzimajući ga od propusnosti mrežnog sučelja One-cloud - OS na razini podatkovnog centra u Odnoklassniki s malom marginom, tj.

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Opsezi se definiraju neovisno za dolazni i odlazni promet. A prema novim vrijednostima, miniond rekonfigurira ograničenje neprioritetne klase 1:2.

Tako smo implementirali sve tri izolacijske klase: proizvod, batch i idle. Ove klase uvelike utječu na karakteristike izvedbe zadataka. Stoga smo odlučili ovaj atribut postaviti na vrh hijerarhije, kako bi pri pogledu na naziv hijerarhijskog reda odmah bilo jasno o čemu imamo posla:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Svi naši prijatelji tkanje и glazba fronte se zatim postavljaju u hijerarhiju pod prod. Na primjer, pod seriju, stavimo uslugu glazbeni katalog, koji povremeno sastavlja katalog pjesama iz skupa mp3 datoteka prenesenih na Odnoklassniki. Primjer usluge u stanju mirovanja bio bi glazbeni transformator, koji normalizira razinu glasnoće glazbe.

S ponovnim uklanjanjem dodatnih linija, nazive naših usluga možemo pisati ravnije dodavanjem klase izolacije zadatka na kraj punog naziva usluge: web.front.prod, katalog.glazba.serija, transformator.glazba.mirovanje.

A sada, gledajući naziv usluge, razumijemo ne samo koju funkciju obavlja, već i njegovu klasu izolacije, što znači njegovu kritičnost itd.

Sve je super, ali ima jedna gorka istina. Nemoguće je potpuno izolirati zadatke koji se izvode na jednom stroju.

Ono što smo uspjeli postići: ako se serija intenzivno troši samo CPU resursa, zatim ugrađeni Linux CPU planer vrlo dobro obavlja svoj posao i praktički nema utjecaja na proizvodni zadatak. Ali ako ovaj paketni zadatak počne aktivno raditi s memorijom, tada se već pojavljuje međusobni utjecaj. To se događa jer se proizvodni zadatak "ispire" iz predmemorije memorije procesora - kao rezultat toga, povećava se broj promašaja predmemorije, a procesor sporije obrađuje proizvodni zadatak. Takav paketni zadatak može povećati latenciju našeg tipičnog proizvodnog spremnika za 10%.

Izolacija prometa je još teža zbog činjenice da moderne mrežne kartice imaju interni red čekanja paketa. Ako paket iz skupnog zadatka stigne prvi, tada će on biti prvi koji će biti poslan preko kabela i tu se ništa ne može učiniti.

Osim toga, do sada smo uspjeli riješiti samo problem prioritizacije TCP prometa: hsfc pristup ne radi za UDP. Čak i u slučaju TCP prometa, ako skupni zadatak generira mnogo prometa, to također daje oko 10% povećanja kašnjenja prod zadatka.

tolerancija kvarova

Jedan od ciljeva pri razvoju one-clouda bio je poboljšati otpornost na pogreške Odnoklassnikija. Stoga bih dalje želio detaljnije razmotriti moguće scenarije kvarova i nesreća. Počnimo s jednostavnim scenarijem – kvarom spremnika.

Sam spremnik može pokvariti na nekoliko načina. To može biti neka vrsta eksperimenta, bug ili pogreška u manifestu, zbog koje prod zadatak počinje trošiti više resursa nego što je navedeno u manifestu. Imali smo slučaj: programer je implementirao jedan složeni algoritam, preradio ga mnogo puta, predomislio se i postao toliko zbunjen da se na kraju problem zapetljao na vrlo netrivijalan način. A budući da prod task ima veći prioritet od svih ostalih na istim minionima, počeo je trošiti sve dostupne resurse procesora. U ovoj situaciji stvar je spasila izolacija, odnosno kvota CPU vremena. Ako je zadatku dodijeljena kvota, zadatak neće trošiti više. Stoga paketni i drugi proizvodni zadaci koji su se izvodili na istom stroju nisu primijetili ništa.

Drugi mogući problem je padanje posude. I tu nas spašavaju politike ponovnog pokretanja, svi ih znaju, sam Docker radi odličan posao. Gotovo svi proizvodni zadaci imaju pravilo uvijek ponovnog pokretanja. Ponekad koristimo on_failure za skupne zadatke ili za otklanjanje pogrešaka proizvodnih spremnika.

Što možete učiniti ako cijeli podanik nije dostupan?

Očito, pokrenite spremnik na drugom stroju. Ovdje je zanimljivo što se događa s IP adresom(ama) dodijeljenom spremniku.

Spremnicima možemo dodijeliti iste IP adrese kao i strojevima za pomoćnike na kojima se ti spremnici pokreću. Zatim, kada se spremnik pokrene na drugom računalu, njegova IP adresa se mijenja i svi klijenti moraju shvatiti da se spremnik premjestio i da sada moraju ići na drugu adresu, što zahtijeva zasebnu uslugu otkrivanja usluge.

Usluga Discovery je praktična. Na tržištu postoje mnoga rješenja različitog stupnja tolerancije na pogreške za organiziranje servisnog registra. Često takva rješenja implementiraju logiku balansera opterećenja, pohranjuju dodatnu konfiguraciju u obliku KV pohrane itd.
No, željeli bismo izbjeći potrebu implementacije zasebnog registra, jer bi to značilo uvođenje kritičnog sustava koji koriste sve službe u proizvodnji. To znači da je to potencijalna točka neuspjeha i da trebate odabrati ili razviti rješenje koje je vrlo otporno na pogreške, što je očito vrlo teško, dugotrajno i skupo.

I još jedan veliki nedostatak: da bi naša stara infrastruktura radila s novom, morali bismo prepisati apsolutno sve zadatke da koriste nekakav sustav za otkrivanje usluga. Posla ima PUNO, a na nekim mjestima gotovo nemoguće kada su u pitanju uređaji niske razine koji rade na razini OS kernela ili izravno s hardverom. Implementacija ove funkcionalnosti pomoću utvrđenih obrazaca rješenja, kao što je prikolica na nekim mjestima bi značilo dodatno opterećenje, na drugim - komplikaciju rada i dodatne scenarije kvara. Nismo htjeli komplicirati stvari, pa smo odlučili da korištenje Service Discovery bude opcionalno.

U one-cloudu, IP slijedi spremnik, tj. svaka instanca zadatka ima svoju IP adresu. Ova je adresa "statična": dodjeljuje se svakoj instanci kada se usluga prvi put šalje u oblak. Ako je usluga tijekom svog životnog vijeka imala različit broj instanci, tada će joj se na kraju dodijeliti onoliko IP adresa koliko je bilo maksimalno instanci.

Naknadno se te adrese ne mijenjaju: dodjeljuju se jednom i nastavljaju postojati tijekom trajanja usluge u proizvodnji. IP adrese slijede spremnike preko mreže. Ako se spremnik prenese na drugog miljenika, adresa će ga pratiti.

Stoga se preslikavanje naziva usluge na njen popis IP adresa mijenja vrlo rijetko. Ako ponovno pogledate nazive servisnih instanci koje smo spomenuli na početku članka (1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, …), primijetit ćemo da nalikuju FQDN-ovima koji se koriste u DNS-u. Tako je, za preslikavanje imena instanci usluge na njihove IP adrese, koristimo DNS protokol. Štoviše, ovaj DNS vraća sve rezervirane IP adrese svih spremnika - i aktivnih i zaustavljenih (recimo da se koriste tri replike, a mi tamo imamo pet rezerviranih adresa - svih pet će biti vraćeno). Klijenti će, nakon što dobiju te podatke, pokušati uspostaviti vezu sa svih pet replika – i tako odrediti one koje rade. Ova opcija za određivanje dostupnosti je puno pouzdanija, ne uključuje niti DNS niti Service Discovery, što znači da nema teških problema za rješavanje u osiguravanju relevantnosti informacija i tolerancije na pogreške ovih sustava. Štoviše, u kritičnim servisima o kojima ovisi rad cijelog portala, DNS uopće ne možemo koristiti, već samo IP adrese upisujemo u konfiguraciju.

Implementacija takvog IP prijenosa iza spremnika može biti netrivijalna - a mi ćemo pogledati kako funkcionira na sljedećem primjeru:

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Recimo da gospodar jednog oblaka daje naredbu miljeniku M1 da trči 1.ok-web.group1.web.front.prod sa adresom 1.1.1.1. Radi na minionima PTICA, koji oglašava ovu adresu posebnim poslužiteljima reflektor rute. Potonji imaju BGP sesiju s mrežnim hardverom, u koju se prevodi ruta adrese 1.1.1.1 na M1. M1 usmjerava pakete unutar spremnika pomoću Linuxa. Postoje tri routereflektor poslužitelja, budući da je to vrlo kritičan dio one-cloud infrastrukture – bez njih mreža u one-cloudu neće raditi. Smještamo ih u različite police, ako je moguće u različitim prostorijama podatkovnog centra, kako bismo smanjili vjerojatnost da sva tri ne uspiju u isto vrijeme.

Pretpostavimo sada da je veza između gospodara jednog oblaka i miljenika M1 izgubljena. One-cloud master sada će djelovati pod pretpostavkom da je M1 potpuno zakazao. To jest, dat će naredbu minionu M2 za lansiranje web.group1.web.front.prod sa istom adresom 1.1.1.1. Sada imamo dvije sukobljene rute na mreži za 1.1.1.1: na M1 i na M2. Kako bismo riješili takve sukobe, koristimo Multi Exit Discriminator, koji je naveden u BGP najavi. Ovo je broj koji pokazuje težinu oglašene rute. Među sukobljenim rutama bit će odabrana ruta s nižom MED vrijednošću. One-cloud master podržava MED kao sastavni dio IP adresa spremnika. Prvi put se adresa ispisuje s dovoljno velikim MED = 1 000 000. U situaciji takvog hitnog prijenosa kontejnera, master smanjuje MED, a M2 će već dobiti naredbu za oglašavanje adrese 1.1.1.1 s MED = 999 999. Instanca koja se izvodi na M1 ostat će na u ovom slučaju nema veze, a njegova nas daljnja sudbina malo zanima dok se veza s masterom ne uspostavi, kada će biti zaustavljen kao staro.

nesreće

Svi sustavi upravljanja podatkovnim centrima uvijek prihvatljivo rješavaju manje kvarove. Prelijevanje kontejnera je norma gotovo posvuda.

Pogledajmo kako postupamo u hitnim slučajevima, kao što je nestanak struje u jednoj ili više prostorija podatkovnog centra.

Što nesreća znači za sustav upravljanja podatkovnim centrom? Prije svega, radi se o masovnom jednokratnom kvaru mnogih strojeva, a kontrolni sustav mora migrirati mnogo spremnika istovremeno. Ali ako je katastrofa vrlo velikih razmjera, tada se može dogoditi da se svi zadaci ne mogu preraspodijeliti drugim miljenicima, jer kapacitet resursa podatkovnog centra padne ispod 100% opterećenja.

Često su nesreće popraćene kvarom kontrolnog sloja. To se može dogoditi zbog kvara njegove opreme, ali češće zbog činjenice da se nesreće ne testiraju, a sam kontrolni sloj pada zbog povećanog opterećenja.

Što možete učiniti u vezi svega ovoga?

Masovne migracije znače da se u infrastrukturi odvija velik broj aktivnosti, migracija i implementacija. Svaka od migracija može potrajati neko vrijeme potrebno za isporuku i raspakiranje slika spremnika minionima, pokretanje i inicijaliziranje spremnika itd. Stoga je poželjno da se važniji zadaci pokreću prije manje važnih.

Pogledajmo ponovno hijerarhiju usluga s kojom smo upoznati i pokušajmo odlučiti koje zadatke želimo prve pokrenuti.

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Naravno, radi se o procesima koji izravno sudjeluju u obradi korisničkih zahtjeva, tj. prod. To označavamo sa prioritet plasmana — broj koji se može dodijeliti redu čekanja. Ako red čekanja ima viši prioritet, njegove usluge se postavljaju na prvo mjesto.

Na prod dodjeljujemo više prioritete, 0; na seriji - malo niže, 100; u mirovanju - još niže, 200. Prioriteti se primjenjuju hijerarhijski. Svi zadaci niži u hijerarhiji imat će odgovarajući prioritet. Ako želimo da se predmemorije unutar proizvoda pokreću prije sučelja, tada dodjeljujemo prioritete predmemoriji = 0 i prednjim podredovima = 1. Ako, na primjer, želimo da se glavni portal prvo pokrene s prednje strane, a samo glazbeni prednji onda, onda ovom drugom možemo dodijeliti niži prioritet - 10.

Sljedeći problem je nedostatak sredstava. Dakle, otkazala je velika količina opreme, čitave hale podatkovnog centra, a mi smo ponovno pokrenuli toliko usluga da sada nema dovoljno resursa za sve. Morate odlučiti koje ćete zadatke žrtvovati kako biste nastavili raditi glavne kritične usluge.

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Za razliku od prioriteta postavljanja, ne možemo neselektivno žrtvovati sve skupne zadatke; neki od njih su važni za rad portala. Stoga smo posebno istaknuli prednost prvenstva zadaci. Kada se postavi, zadatak višeg prioriteta može preduhitriti, tj. zaustaviti zadatak nižeg prioriteta ako više nema slobodnih minija. U tom će slučaju zadatak s niskim prioritetom vjerojatno ostati nepostavljen, tj. za njega više neće postojati odgovarajući minion s dovoljno slobodnih resursa.

U našoj hijerarhiji, vrlo je jednostavno navesti prioritet prioriteta tako da prod i batch zadaci ispredaju ili zaustavljaju zadatke u mirovanju, ali ne jedni druge, određivanjem prioriteta za mirovanje jednak 200. Baš kao u slučaju prioriteta postavljanja, mi može koristiti našu hijerarhiju kako bi opisao složenija pravila. Na primjer, naznačimo da žrtvujemo glazbenu funkciju ako nemamo dovoljno resursa za glavni web portal, postavljajući niži prioritet za odgovarajuće čvorove: 10.

Cijele DC nesreće

Zašto bi cijeli podatkovni centar mogao propasti? Element. Bio je to dobar post uragan je utjecao na rad podatkovnog centra. Elementi se mogu smatrati beskućnicima koji su jednom spalili optiku u razdjelniku, a podatkovni centar potpuno izgubio kontakt s drugim mjestima. Uzrok kvara može biti i ljudski faktor: operater će izdati takvu naredbu da će cijeli podatkovni centar pasti. To bi se moglo dogoditi zbog velike greške. Općenito, kolaps podatkovnih centara nije neuobičajen. Ovo nam se događa jednom u nekoliko mjeseci.

I to je ono što radimo kako bismo spriječili bilo koga da tweeta #alive.

Prva strategija je izolacija. Svaka instanca jednog oblaka izolirana je i može upravljati strojevima u samo jednom podatkovnom centru. Odnosno, gubitak oblaka zbog grešaka ili netočnih naredbi operatera je gubitak samo jednog podatkovnog centra. Spremni smo za to: imamo politiku redundantnosti prema kojoj se replike aplikacije i podataka nalaze u svim podatkovnim centrima. Koristimo baze podataka otporne na pogreške i povremeno testiramo kvarove.
Budući da danas imamo četiri podatkovna centra, to znači četiri odvojene, potpuno izolirane instance jednog oblaka.

Ovaj pristup ne samo da štiti od fizičkog kvara, već može zaštititi i od pogreške operatera.

Što se još može učiniti s ljudskim faktorom? Kada operater oblaku izda neku čudnu ili potencijalno opasnu naredbu, od njega se može iznenada tražiti da riješi mali problem kako bi se vidjelo koliko je dobro razmislio. Na primjer, ako je ovo neka vrsta masovnog zaustavljanja mnogih replika ili samo čudna naredba - smanjenje broja replika ili promjena naziva slike, a ne samo broja verzije u novom manifestu.

One-cloud - OS na razini podatkovnog centra u Odnoklassniki

Rezultati

Prepoznatljive značajke one-clouda:

  • Hijerarhijska i vizualna shema imenovanja za usluge i spremnike, koji vam omogućuje da vrlo brzo saznate o kakvom se zadatku radi, na što se odnosi i kako funkcionira te tko je za to odgovoran.
  • Mi primjenjujemo naše tehnika kombiniranja proizvodnje i serijezadaci na miljenicima za poboljšanje učinkovitosti dijeljenja strojeva. Umjesto cpuset-a koristimo CPU kvote, dijeljenja, pravila CPU planera i Linux QoS.
  • Nije bilo moguće potpuno izolirati spremnike koji rade na istom stroju, ali njihov međusobni utjecaj ostaje unutar 20%.
  • Organiziranje usluga u hijerarhiju pomaže u automatskom oporavku od katastrofe prioriteti postavljanja i prvenstva.

Pitanja

Zašto nismo uzeli već gotovo rješenje?

  • Različite klase izolacije zadataka zahtijevaju različitu logiku kada se postavljaju na miljenike. Ako se proizvodni zadaci mogu postaviti jednostavnim rezerviranjem resursa, tada se moraju postaviti paketni i neaktivni zadaci, prateći stvarnu iskorištenost resursa na miljeničkim strojevima.
  • Potreba da se uzmu u obzir resursi koje troše zadaci, kao što su:
    • propusnost mreže;
    • vrste i “vretena” diskova.
  • Potreba za označavanjem prioriteta usluga tijekom odgovora na hitne slučajeve, prava i kvota naredbi za resurse, što se rješava pomoću hijerarhijskih redova čekanja u jednom oblaku.
  • Potreba za ljudskim imenovanjem spremnika kako bi se smanjilo vrijeme odgovora na nesreće i incidente
  • Nemogućnost jednokratne široke implementacije Service Discovery-a; potreba za dugotrajnim koegzistiranjem sa zadacima koji se nalaze na hardverskim hostovima - nešto što se rješava "statičkim" IP adresama koje slijede spremnike, i, kao posljedica toga, potreba za jedinstvenom integracijom s velikom mrežnom infrastrukturom.

Sve te funkcije zahtijevale bi značajne modifikacije postojećih rješenja kako bi nam odgovarale, a procijenivši količinu posla, uvidjeli smo da možemo razviti vlastito rješenje uz približno iste troškove rada. Ali vaše će rješenje biti puno lakše za rad i razvoj - ono ne sadrži nepotrebne apstrakcije koje podržavaju funkcionalnost koja nam nije potrebna.

Onima koji su pročitali posljednje retke, hvala na strpljenju i pažnji!

Izvor: www.habr.com

Dodajte komentar