One-cloud - OS à livellu di centru di dati in Odnoklassniki

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Aloha, ghjente! Mi chjamu Oleg Anastasyev, aghju travagliatu in Odnoklassniki in a squadra di a piattaforma. È in più di mè, ci hè assai hardware chì travaglia in Odnoklassniki. Avemu quattru centri di dati cù circa 500 racks cù più di 8 mila servitori. À un certu puntu, avemu capitu chì l'intruduzioni di un novu sistema di gestione ci permetterà di carricà l'equipaggiu in modu più efficau, facilità a gestione di l'accessu, automatizà a (re)distribuzione di risorse di l'informatica, accelerà u lanciu di novi servizii, è accelerà e risposte. à accidenti à grande scala.

Chì ne hè vinutu ?

In più di mè è una mansa di hardware, ci sò ancu persone chì travaglianu cù questu hardware: ingegneri chì si trovanu direttamente in centri di dati; networkers chì creanu un software di rete; amministratori, o SRE, chì furnisce a resilienza di l'infrastruttura; e squadre di sviluppu, ognunu di elli hè rispunsevuli di una parte di e funzioni di u portale. U software chì creanu funziona qualcosa cusì:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

E dumande di l'utilizatori sò ricevute sia nantu à i fronti di u portale principale www.ok.ru, è in altri, per esempiu in i fronti di l'API di musica. Per processà a logica di l'affari, chjamanu u servitore di l'applicazioni, chì, in u processu di a dumanda, chjama i microservizii specializati necessarii - un graficu (graficu di cunnessione suciale), cache d'utilizatore (cache di profili d'utilizatori), etc.

Ognunu di sti servizii hè implementatu in parechje macchine, è ognunu hà sviluppatori rispunsevuli di u funziunamentu di i moduli, u so funziunamentu è u sviluppu tecnologicu. Tutti questi servizii funzionanu nantu à i servitori di hardware, è finu à pocu tempu avemu lanciatu esattamente un compitu per servitore, vale à dì chì era specializatu per un compitu specificu.

Perchè hè questu? Stu approcciu avia parechji vantaghji:

  • Rilievu gestione di massa. Diciamu chì un compitu richiede alcune biblioteche, certi paràmetri. E poi u servitore hè attribuitu à esattamente un gruppu specificu, a pulitica di cfengine per questu gruppu hè descritta (o hè digià stata descritta), è sta cunfigurazione hè cintrali è automaticamente rolled out à tutti i servitori in stu gruppu.
  • Simplificatu diagnostichi. Diciamu chì fighjate à a carica aumentata nantu à u processore cintrali è capisce chì sta carica puderia esse generata solu da u compitu chì corre nantu à stu processore hardware. A ricerca di qualcunu à culpèvule finisce assai rapidamente.
  • Simplificatu surviglianza. Se qualcosa hè sbagliatu cù u servitore, u monitoru l'informa, è sapete esattamente quale hè a culpa.

Un serviziu custituitu di parechje rèpliche hè attribuitu parechji servitori - unu per ognunu. Allora a risorsa di l'informatica per u serviziu hè attribuita assai simplice: u numeru di servitori chì u serviziu hà, a quantità massima di risorse chì pò cunsumà. "Facile" quì ùn significa micca chì hè faciule d'utilizà, ma in u sensu chì l'assignazione di risorse hè fatta manualmente.

Stu approcciu ci hà ancu permessu di fà cunfigurazioni di ferru specializate per un compitu in esecuzione nantu à stu servitore. Se u compitu guarda una grande quantità di dati, allora usemu un servitore 4U cù un chassis cù dischi 38. Se u compitu hè puramente computazionale, allora pudemu cumprà un servitore 1U più prezzu. Questu hè un calculu efficiente. Frà altre cose, stu approcciu ci permette di utilizà quattru volte menu macchine cù una carica paragunabili à una rete suciale amichevule.

Una tale efficienza in l'usu di e risorse di l'informatica deve ancu assicurà l'efficienza ecunomica, se procedemu da a premessa chì u più caru hè i servitori. Per un bellu pezzu, l'hardware era u più caru, è avemu fattu assai sforzu per riduce u prezzu di l'hardware, venendu cù algoritmi di toleranza di difetti per riduce i requisiti di affidabilità di hardware. È oghje avemu ghjuntu à u stadiu in quale u prezzu di u servitore hà cessatu di esse decisivu. Se ùn avete micca cunsideratu l'ultimi esotici, allora a cunfigurazione specifica di i servitori in u rack ùn importa micca. Avà avemu un altru prublema - u prezzu di u spaziu occupatu da u servitore in u centru di dati, questu, u spaziu in u rack.

Capendu chì questu era u casu, avemu decisu di calculà quantu effittivamenti avemu usatu i rack.
Avemu pigliatu u prezzu di u servitore più putente da i ghjustificate ecunomicamenti, hà calculatu quanti servitori tali puderemu mette in rack, quanti travaglii avemu da eseguisce nantu à elli basatu annantu à u vechju mudellu "un servitore = un compitu" è quantu tali. i travaglii puderanu aduprà l'equipaggiu. Cuntavanu è pienghjenu. Hè risultatu chì a nostra efficienza in l'usu di racks hè di circa 11%. A cunclusione hè ovvia: avemu bisognu di aumentà l'efficienza di l'usu di i centri di dati. Sembra chì a suluzione hè ovvia: avete bisognu di eseguisce parechje attività in un servitore à una volta. Ma hè quì chì cumincianu e difficultà.

A cunfigurazione di massa diventa drammaticamente più cumplicata - avà hè impussibile di assignà un gruppu à un servitore. Dopu tuttu, avà parechji compiti di cumandamenti diffirenti ponu esse lanciati in un servitore. Inoltre, a cunfigurazione pò esse cunflittu per diverse applicazioni. U diagnosticu diventa ancu più cumplicatu: se vede u cunsumu di CPU o di discu aumentatu in un servitore, ùn sapete micca quale compitu hè causatu prublemi.

Ma a cosa principal hè chì ùn ci hè micca isolamentu trà i travaglii in esecuzione nantu à a stessa macchina. Eccu, per esempiu, hè un gràficu di u tempu di risposta mediu di un servitore prima è dopu chì una altra applicazione computazionale hè stata lanciata nantu à u stessu servitore, in nisuna manera ligata à u primu - u tempu di risposta di u travagliu principale hè aumentatu significativamente.

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Ovviamente, avete bisognu di eseguisce i travaglii in cuntenituri o in macchine virtuali. Siccomu quasi tutti i nostri compiti funzionanu sottu un OS (Linux) o sò adattati per questu, ùn avemu micca bisognu di supportà parechji sistemi operativi diffirenti. Per quessa, a virtualizazione ùn hè micca necessaria; per via di l'overhead addiziale, serà menu efficiente cà a containerizazione.

Cum'è una implementazione di cuntenituri per eseguisce i travaglii direttamente nantu à i servitori, Docker hè un bonu candidatu: l'imaghjini di u sistema di fugliale risolve bè i prublemi cù cunfigurazioni cunflittu. U fattu chì l'imaghjini ponu esse cumposti da parechji strati ci permette di riduce significativamente a quantità di dati necessarii per implementà nantu à l'infrastruttura, sepandu e parti cumuni in strati di basa separati. Allora i strati di basa (è più voluminosi) saranu cache abbastanza rapidamente in tutta l'infrastruttura, è per furnisce assai tipi d'applicazioni è versioni, solu i strati chjuchi duverà esse trasferitu.

In più, un registru prontu è l'etichettatura di l'imaghjini in Docker ci danu primitivi pronti per versioni è furnisce codice à a produzzione.

Docker, cum'è qualsiasi altra tecnulugia simili, ci furnisce un certu livellu di isolamentu di u containeru fora di a scatula. Per esempiu, l'isolamentu di a memoria - ogni cuntinuu hè datu un limitu à l'usu di a memoria di a macchina, oltre chì ùn cunsumerà micca. Pudete ancu isolà cuntenituri basatu annantu à l'usu di CPU. Per noi, però, l'insulazione standard ùn era micca abbastanza. Ma più nantu à quì sottu.

L'esecuzione diretta di cuntenituri nantu à i servitori hè solu una parte di u prublema. L'altra parte hè ligata à l'ospitu di cuntenituri nantu à i servitori. Avete bisognu di capisce quale cuntainer pò esse piazzatu nantu à quale servitore. Questu ùn hè micca un compitu cusì faciule, perchè i cuntenituri deve esse posti nantu à i servitori u più densamente pussibule senza riduce a so velocità. Un tali piazzamentu pò ancu esse difficiule da un puntu di vista di tolleranza di difetti. Spessu vulemu pusà rèpliche di u stessu serviziu in diverse racks o ancu in diverse stanze di u centru di dati, perchè se un rack o una stanza falla, ùn perdemu micca immediatamente tutte e repliche di serviziu.

A distribuzione di cuntenituri manualmente ùn hè micca una opzione quandu avete 8 mila servitori è 8-16 mila cuntenituri.

Inoltre, avemu vulutu dà à i sviluppatori più indipendenza in l'assignazione di risorse per ch'elli puderanu ospitu i so servizii in a produzzione elli stessi, senza l'aiutu di un amministratore. À u listessu tempu, vulemu mantene u cuntrollu in modu chì qualchì serviziu minore ùn cunsuma micca tutte e risorse di i nostri centri di dati.

Ovviamente, avemu bisognu di una strata di cuntrollu chì faria questu automaticamente.

Allora avemu ghjuntu à una stampa simplice è comprensibile chì tutti l'architetti adoranu: trè piazze.

One-cloud - OS à livellu di centru di dati in Odnoklassniki

one-cloud masters hè un cluster failover rispunsevule per l'orchestrazione di nuvola. U sviluppatore manda un manifestu à u maestru, chì cuntene tutte l'infurmazioni necessarii per ospitu u serviziu. Basatu nantu à questu, u maestru dà cumandamenti à i servitori selezziunati (macchine pensate per eseguisce cuntenituri). I minions anu u nostru agente, chì riceve u cumandamentu, emette i so cumandamenti à Docker, è Docker cunfigura u kernel linux per lancià u cuntainer currispundente. In più di eseguisce cumandamenti, l'agente informa continuamente à u maestru nantu à i cambiamenti in u statu di a macchina minion è di i cuntenituri in esecuzione.

Allocazione di risorse

Avà fighjemu u prublema di l'allocazione di risorse più cumplessu per parechji minions.

Una risorsa informatica in una sola nuvola hè:

  • A quantità di putenza di processore cunsumata da un compitu specificu.
  • A quantità di memoria dispunibule per u compitu.
  • U trafficu di a rete. Ognunu di i minions hà una interfaccia di rete specifica cù una larghezza di banda limitata, per quessa hè impussibile di distribuisce i travaglii senza piglià in contu a quantità di dati chì trasmettenu nantu à a reta.
  • Dischi. In più, ovviamente, à u spaziu per questi compiti, assignemu ancu u tipu di discu: HDD o SSD. I dischi ponu serve un numeru finitu di richieste per seconda - IOPS. Dunque, per i travaglii chì generanu più IOPS di quellu chì un discu unicu pò trattà, assignemu ancu "spindles" - vale à dì, i dispositi di discu chì devenu esse riservati solu per u compitu.

Allora per qualchì serviziu, per esempiu per user-cache, pudemu registrà e risorse cunsumate in questu modu: 400 core di processore, 2,5 TB di memoria, 50 Gbit / s trafficu in i dui sensi, 6 TB di spaziu HDD situatu nantu à 100 spindles. O in una forma più familiare cum'è questu:

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

E risorse di serviziu di cache di l'utilizatori cunsumanu solu una parte di tutte e risorse dispunibili in l'infrastruttura di produzzione. Dunque, vogliu assicurà chì di colpu, per via di un errore di l'operatore o micca, u cache di l'utilizatori ùn cunsuma più risorse ch'elli sò attribuiti. Vale à dì, duvemu limità e risorse. Ma à chì pudemu ligà a quota ?

Riturnemu à u nostru schema assai simplificatu di l'interazzione di cumpunenti è ridisegnate cù più dettagli - cum'è questu:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Ciò chì cattura l'ochju:

  • U frontend web è a musica utilizanu clusters isolati di u stessu servitore d'applicazione.
  • Pudemu distingue i strati lògichi à quale appartenenu questi clusters: fronti, cache, almacenamentu di dati è strati di gestione.
  • U frontend hè eterogeneu; hè custituitu da diversi sottosistemi funzionali.
  • I cache ponu ancu esse spargugliati in u sottosistema chì i dati cachenu.

Ridisegnemu a figura di novu:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Bah! Iè, vedemu una ghjerarchia ! Questu significa chì pudete distribuisce risorse in pezzi più grossi: assignate un sviluppatore rispunsevule à un node di sta gerarchia chì currisponde à u subsistema funziunale (cum'è "musica" in a stampa), è aghjunghje una quota à u listessu livellu di a gerarchia. Questa ghjerarchia ci permette ancu di urganizà i servizii in modu più flexible per facilità di gestione. Per esempiu, dividimu tuttu u web, postu chì questu hè un gruppu assai grande di servitori, in parechji gruppi più chjuchi, mostrati in a stampa cum'è group1, group2.

Eliminate e linee extra, pudemu scrive ogni nodu di a nostra stampa in una forma più flat: gruppu1.web.front, api.music.front, user-cache.cache.

Questu hè cumu venemu à u cuncettu di "fila gerarchica". Hà un nome cum'è "group1.web.front". Una quota per i risorse è i diritti di l'utilizatori hè assignatu. Daremu à a persona di DevOps i diritti di mandà un serviziu à a fila, è un tali impiigatu pò lancià qualcosa in a fila, è a persona di OpsDev averà i diritti di amministratore, è avà pò gestisce a fila, assignà e persone quì, dà i diritti di sti pirsuni, etc. I servizii chì currenu nantu à sta fila curriranu in a quota di a fila. Se a quota di l'informatica di a fila ùn hè micca abbastanza per eseguisce tutti i servizii in una volta, allora saranu eseguiti sequenzialmente, formandu cusì a fila stessu.

Fighjemu un ochju più vicinu à i servizii. Un serviziu hà un nome cumplettamente qualificatu, chì include sempre u nome di a fila. Allora u serviziu web di fronte avarà u nome ok-web.group1.web.front. È u serviziu di u servitore di l'applicazioni à quale accede serà chjamatu ok-app.group1.web.front. Ogni serviziu hà un manifestu, chì specifica tutte l'infurmazioni necessarii per u piazzamentu nantu à i machini specifichi: quante risorse consuma stu compitu, quale cunfigurazione hè necessariu per questu, quante rèpliche duverebbe esse, proprietà per trattà i fallimenti di stu serviziu. È dopu chì u serviziu hè piazzatu direttamente nantu à e macchine, i so casi appariscenu. Sò ancu chjamati senza ambiguità - cum'è u numeru di istanza è u nome di serviziu: 1.ok-web.group1.web.front, 2.ok-web.group1.web.front, ...

Questu hè assai cunvenutu: fighjendu solu u nome di u cuntinuu in esecuzione, pudemu immediatamente scopre assai.

Avà fighjemu un sguardu più vicinu à ciò chì sti casi realizà in realtà: compiti.

Classi di isolamentu di u travagliu

Tutti i travaglii in OK (è, probabilmente, in ogni locu) ponu esse divisi in gruppi:

  • Tasks di Latenza Corta - prod. Per tali compiti è servizii, u ritardu di risposta (latenza) hè assai impurtante, quantu rapidamente ogni dumanda serà processata da u sistema. Esempii di compiti: fronti web, cache, servitori di applicazioni, almacenamiento OLTP, etc.
  • Problemi di calculu - batch. Quì, a vitezza di trasfurmazioni di ogni dumanda specifica ùn hè micca impurtante. Per elli, hè impurtante quantu calculi stu compitu farà in un certu (longu) periodu di tempu (throughput). Quessi seranu qualsiasi attività di MapReduce, Hadoop, machine learning, statistiche.
  • Attività di fondo - inattivu. Per tali compiti, nè latenza nè throughput sò assai impurtanti. Stu include diversi testi, migrazzioni, recalculations, è cunversione di dati da un furmatu à un altru. Da una banda, sò simili à quelli calculati, da l'altra banda, ùn ci importa micca quantu rapidamente sò cumpletati.

Videmu cumu tali compiti cunsuma risorse, per esempiu, u processatore cintrali.

I travaglii di ritardu brevi. Un tali compitu averà un mudellu di cunsumu CPU simile à questu:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Una dumanda da l'utilizatore hè ricevutu per u processu, u compitu principia à utilizà tutti i nuclei CPU dispunibuli, u processa, torna una risposta, aspetta a prossima dumanda è si ferma. A prossima dumanda hè ghjunta - novu avemu sceltu tuttu ciò chì era quì, calculatu, è aspittàmu per u prossimu.

Per guarantisce a latenza minima per un tali compitu, duvemu piglià e risorse massime chì cunsuma è riservà u numeru necessariu di core nantu à u minion (a macchina chì eseguirà u compitu). Allora a formula di riservazione per u nostru prublema serà a siguenti:

alloc: cpu = 4 (max)

è s'è no avemu una macchina minion cù 16 cores, allura esattamente quattru tali compiti ponu esse posti nantu à questu. Notemu soprattuttu chì u cunsumu mediu di u processatore di tali compiti hè spessu assai bassu - chì hè ovvi, postu chì una parte significativa di u tempu chì u compitu aspetta una dumanda è ùn faci nunda.

I travagli di calculu. U so mudellu serà un pocu sfarente:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

U cunsumu mediu di risorse CPU per tali compiti hè abbastanza altu. Spessu vulemu chì un compitu di calculu compie in una certa quantità di tempu, cusì avemu bisognu di riservà u numeru minimu di processori chì hà bisognu per chì u calculu tutale hè cumpletu in un tempu accettabile. A so formula di riservazione serà cusì:

alloc: cpu = [1,*)

"Per piacè mettelu nantu à un servitore induve ci hè almenu un core liberu, è poi quant'è ci sò, divorerà tuttu".

Quì l'efficienza di l'usu hè digià assai megliu cà nantu à i travaglii cù un brevi ritardu. Ma u guadagnu serà assai più grande se combina i dui tipi di compiti in una macchina minion è distribuisce e so risorse in viaghju. Quandu un compitu cù un brevi ritardu richiede un processatore, u riceve immediatamente, è quandu i risorse ùn sò più necessarii, sò trasferiti à u compitu computazionale, vale à dì qualcosa di questu:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Ma cumu fà què?

Prima, fighjemu prod è u so alloc: cpu = 4. Avemu bisognu di riservà quattru core. In Docker run questu pò esse fattu in duie manere:

  • Utilizendu l'opzione --cpuset=1-4, vale à dì assignà quattru core specifichi nantu à a macchina à u compitu.
  • Aduprate --cpuquota=400_000 --cpuperiod=100_000, assignate una quota per u tempu di processore, vale à dì indicà chì ogni 100 ms di tempu reale u compitu cunsuma micca più di 400 ms di tempu di processore. I stessi quattru core sò ottenuti.

Ma quale di sti metudi hè adattatu?

cpuset pare abbastanza attraente. U compitu hà quattru nuclei dedicati, chì significa chì i caches di u processatore funzionaranu in modu efficientemente pussibule. Questu hà ancu un inconveniente: duvemu piglià u compitu di distribuisce i calculi à traversu i nuclei scaricati di a macchina invece di l'OS, è questu hè un compitu piuttostu micca trivial, soprattuttu s'è no pruvemu di mette in batch tasks in un tali. macchina. I testi anu dimustratu chì l'opzione cù una quota hè più adattata quì: questu modu u sistema operatore hà più libertà di sceglie u core per eseguisce u compitu in u mumentu attuale è u tempu di u processatore hè distribuitu in modu più efficau.

Scupritemu cumu fà riserve in Docker basatu annantu à u minimu numeru di core. A quota per i travaglii di batch ùn hè più applicabile, perchè ùn ci hè bisognu di limità u massimu, hè abbastanza per guarantiscia solu u minimu. E quì l'opzione si adatta bè docker run --cpushares.

Avemu accunsentutu chì se un batch necessita una guaranzia per almenu un core, allora indichemu --cpushares=1024, è s'ellu ci sò almenu dui nuclei, allora indichemu --cpushares=2048. L'azzioni di CPU ùn interferiscenu micca in ogni modu cù a distribuzione di u tempu di u processatore, sempre chì ci hè abbastanza. Cusì, se prod ùn hè micca attualmente aduprendu tutti i so quattru nuclei, ùn ci hè nunda chì limita i travaglii di batch, è ponu utilizà u tempu di processore supplementu. Ma in una situazione induve ci hè una carenza di prucessori, se prod hà cunsumatu tutti i quattru nuclei è hà righjuntu a so quota, u tempu restante di u processore serà divisu proporzionalmente à cpushares, vale à dì in una situazione di trè core liberi, unu serà. datu à un compitu cù 1024 cpushares, è i dui rimanenti seranu datu à un compitu cù 2048 cpushares.

Ma l'usu di quota è azzioni ùn hè micca abbastanza. Avemu bisognu di assicurà chì un compitu cù un brevi ritardu riceve a priorità annantu à un compitu batch quandu assigna u tempu di u processatore. Senza una tale priorità, u compitu batch piglià tuttu u tempu di u processatore à u mumentu chì hè necessariu da u prod. Ùn ci hè micca opzioni di priorità di cuntenituri in Docker run, ma e pulitiche di pianificazione di CPU Linux sò utili. Pudete leghje nantu à elli in detail ccà, è in u quadru di stu articulu avemu da passà per elli brevemente:

  • SCHED_OTHER
    Per automaticamente, tutti i prucessi normali di l'utilizatori nantu à una macchina Linux ricevenu.
  • SCHED_BATCH
    Cuncepitu per prucessi intensivi di risorse. Quandu si mette un compitu nantu à un processore, hè introduttu una cusì chjamata penalità di attivazione: una tale attività hè menu prubabile di riceve risorse di processore s'ellu hè attualmente utilizatu da un compitu cù SCHED_OTHER
  • SCHED_IDLE
    Un prucessu di fondu cù una priorità assai bassu, ancu più bassu di bellu -19. Utilizemu a nostra biblioteca open source unu-niu, Per stabilisce a pulitica necessaria quandu principia u cuntinuu chjamendu

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

Ma ancu s'ellu ùn avete micca prugrammatu in Java, a listessa cosa pò esse fatta cù u cumandimu chrt:

chrt -i 0 $pid

Riassumemu tutti i nostri livelli di isolamentu in una tavola per a chiarezza:

Classe d'isolamentu
Alloc esempiu
Opzioni di esecuzione di Docker
sched_setscheduler chrt*

Pruduzzione
CPU = 4
--cpuquota=400000 --cpuperiod=100000
SCHED_OTHER

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

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

* Se fate chrt da l'internu di un cuntinuu, pudete avè bisognu di a capacità sys_nice, perchè per difettu Docker elimina sta capacità quandu principia u cuntinuu.

Ma i travaglii cunsumanu micca solu u processatore, ma ancu u trafficu, chì affetta a latenza di un travagliu di rete ancu più cà l'attribuzione incorrecta di risorse di processatore. Dunque, vulemu naturalmente ottene esattamente a stessa stampa per u trafficu. Vale à dì, quandu un compitu di pruduzzione manda alcuni pacchetti à a reta, limitemu a velocità massima (formula alloc: lan=[[*,500mbps) ), cù quale prod pò fà questu. È per u batch guarantimu solu u throughput minimu, ma ùn limità micca u massimu (formula alloc: lan=[10 Mbps,*) ) In questu casu, u trafficu di pruduzzione deve riceve priorità nantu à i travaglii batch.
Quì Docker ùn hà micca primitivi chì pudemu usà. Ma vene à u nostru aiutu Controlu di u trafficu Linux. Pudemu ottene u risultatu desideratu cù l'aiutu di a disciplina Curva di serviziu di fiera gerarchica. Cù u so aiutu, distinguemu duie classi di trafficu: prod d'alta priorità è batch/idle di priorità bassa. In u risultatu, a cunfigurazione per u trafficu in uscita hè cusì:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

quì 1: 0 hè u "root qdisc" di a disciplina hsfc; 1: 1 - classa di u zitellu hsfc cù un limitu di larghezza di banda tutale di 8 Gbit/s, sottu à quale sò posti i classi di i zitelli di tutti i cuntenituri; 1: 2 - a classa di u zitellu hsfc hè cumuna per tutti i batch è i travaglii inattivi cù un limitu "dinamicu", chì hè discututu quì sottu. I restanti classi di i zitelli hsfc sò classi dedicate per i cuntenituri prod attualmente in esecuzione cù limiti chì currispondenu à i so manifesti - 450 è 400 Mbit/s. Ogni classa hsfc hè assignatu un qdisc queue fq o fq_codel, secondu a versione di u kernel Linux, per evità a perdita di pacchetti durante u trafficu.

Di genere, i disciplini di tc servenu per priurità solu u trafficu in uscita. Ma vulemu prioritizà ancu u trafficu in entrata - dopu à tuttu, una certa attività batch pò facilmente selezziunà tuttu u canali di entrata, ricevendu, per esempiu, un grande batch di dati di input per map&reduce. Per questu avemu aduprà u modulu ifb, chì crea una interfaccia virtuale ifbX per ogni interfaccia di rete è redirige u trafficu entrante da l'interfaccia à u trafficu in uscita in ifbX. In più, per ifbX, tutte e listesse discipline travaglianu per cuntrullà u trafficu in uscita, per quale a cunfigurazione hsfc serà assai simile:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Duranti l'esperimenti, avemu scupertu chì hsfc mostra i megliu risultati quandu a classa 1: 2 di u trafficu batch / idle non-priorità hè limitata à e macchine minion à micca più di una certa strada libera. Altrimenti, u trafficu senza priorità hà troppu impattu nantu à a latenza di i travaglii prod. miniond determina a quantità attuale di larghezza di banda libera ogni seconda, misurandu u cunsumu mediu di trafficu di tutti i prod-tasks di un determinatu minion. One-cloud - OS à livellu di centru di dati in Odnoklassniki è sottraendu da a larghezza di banda di l'interfaccia di a rete One-cloud - OS à livellu di centru di dati in Odnoklassniki cù un picculu margine, i.e.

One-cloud - OS à livellu di centru di dati in Odnoklassniki

E bande sò definite indipindentamente per u trafficu entrante è in uscita. È sicondu i novi valori, miniond reconfigures u limitu di classi non priurità 1: 2.

Cusì, avemu implementatu e trè classi di isolamentu: prod, batch è idle. Queste classi influenzanu assai e caratteristiche di rendiment di i travaglii. Per quessa, avemu decisu di mette stu attributu à a cima di a ghjerarchia, per quessa, quandu fighjendu u nome di a fila gerarchica, sia immediatamente chjaru ciò chì avemu trattatu:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Tutti i nostri amichi Web и musica i fronti sò poi posti in a ghjerarchia sottu prod. Per esempiu, sottu batch, mettemu u serviziu catalogu di musica, chì compile periodicamente un catalogu di tracce da un settore di schedari mp3 uploaded to Odnoklassniki. Un esempiu di serviziu sottu idle seria trasformatore di musica, chì nurmalizeghja u livellu di volume di musica.

Cù e linee extra sguassate di novu, pudemu scrive i nostri nomi di serviziu più flat, aghjunghjendu a classa di isolamentu di u travagliu à a fine di u nome di serviziu cumpletu: web.front.prod, catalogu.musica.batch, transformer.music.idle.

È avà, fighjendu u nome di u serviziu, avemu capitu micca solu a funzione chì eseguisce, ma ancu a so classa di isolamentu, chì significa a so criticità, etc.

Tuttu hè grande, ma ci hè una verità amara. Hè impussibile di isolà cumplettamente i travaglii in esecuzione in una macchina.

Ciò chì avemu riesciutu à ottene: se batch intensively consumes solu Risorse di CPU, allora u pianificatore di CPU Linux integratu face u so travagliu assai bè, è ùn ci hè praticamente micca impattu nantu à a pruduzzione. Ma s'è stu compitu batch cumencia à travaglià attivamente cù a memoria, allura l'influenza mutuale appare digià. Questu succede perchè u prucedimentu hè "lavatu" da i cache di memoria di u processatore - in u risultatu, i cache miss aumentanu, è u processatore processa u prucedimentu più lentamente. Un tali compitu batch pò aumentà a latenza di u nostru cuntainer tipicu di prod da 10%.

Isulà u trafficu hè ancu più difficiule per via di u fattu chì e carte di rete muderne anu una fila interna di pacchetti. Se u pacchettu da u travagliu batch ghjunghje prima, allora serà u primu à esse trasmessu nantu à u cable, è nunda ùn pò esse fattu.

Inoltre, finu à quì avemu solu riisciutu à risolve u prublema di priorità u trafficu TCP: l'approcciu hsfc ùn hè micca travagliatu per UDP. E ancu in u casu di u trafficu TCP, se u batch task genera assai trafficu, questu dà ancu circa un 10% d'aumentu di u ritardu di u travagliu prod.

tolleranza à i difetti

Unu di l'ugettivi in ​​u sviluppu di una sola nuvola era di migliurà a toleranza di colpa di Odnoklassniki. Dunque, in seguitu, mi piacerebbe cunsiderà in più detail i pussibuli scenarii di fallimenti è accidenti. Cuminciamu cù un scenariu simplice - un fallimentu di u containeru.

U cuntinuu stessu pò fallu in parechje manere. Questu puderia esse un tipu d'esperimentu, bug o errore in u manifestu, per via di quale u compitu prod principia à cunsumà più risorse di ciò chì hè indicatu in u manifestu. Avemu avutu un casu: un sviluppatore hà implementatu un algoritmu cumplessu, l'hà rielaboratu parechje volte, s'hè sopravvissatu è hè diventatu cusì cunfusu chì, in fine, u prublema hè stata chjappata in una manera assai micca triviale. E postu chì u prucedimentu hà una priorità più altu ch'è tutti l'altri nantu à i stessi minions, hà cuminciatu à cunsumà tutte e risorse di processore dispunibili. In questa situazione, l'isolamentu, o megliu a quota di u tempu di CPU, hà salvatu u ghjornu. Se un compitu hè attribuitu una quota, u compitu ùn cunsumerà più. Dunque, batch è altre attività prod chì currianu nantu à a listessa macchina ùn anu nutatu nunda.

U sicondu prublema pussibule hè a caduta di u containeru. E quì e pulitiche di riavvia ci salvanu, tutti li cunnosci, Docker stessu faci un bellu travagliu. Quasi tutti i travaglii di pruduzzione anu una pulitica di riavvia sempre. A volte usemu on_failure per i travaglii di batch o per debugging containers prod.

Chì pudete fà se un minion interu ùn hè micca dispunibule?

Ovviamente, eseguite u cuntinuu nantu à una altra macchina. A parte interessante quì hè ciò chì succede à l'indirizzu (i) IP assignati à u cuntinuu.

Pudemu assignà cuntenituri i stessi indirizzi IP cum'è e macchine minion nantu à quale questi cuntenituri funzionanu. Allora, quandu u cuntinuu hè lanciatu nantu à una altra macchina, u so indirizzu IP cambia, è tutti i clienti devenu capisce chì u cuntinuu hè spustatu, è avà anu bisognu à andà à un altru indirizzu, chì deve esse un serviziu di Discovery Service separatu.

Service Discovery hè cunvene. Ci sò parechje soluzioni nantu à u mercatu cù varii gradi di toleranza di difetti per urganizà un registru di serviziu. Spessu tali soluzioni implementanu a logica di bilanciu di carica, almacenanu cunfigurazioni supplementari in forma di almacenamiento KV, etc.
Tuttavia, vulemu evità a necessità di implementà un registru separatu, perchè questu significaria l'introduzione di un sistema criticu chì hè utilizatu da tutti i servizii in a produzzione. Questu significa chì questu hè un puntu potenziale di fallimentu, è avete bisognu di sceglie o di sviluppà una suluzione assai tolerante à i difetti, chì hè ovviamente assai difficiuli, tempu è caru.

È un altru grande svantaghju: per a nostra vechja infrastruttura per travaglià cù a nova, duvemu riscrivite assolutamente tutti i travaglii per utilizà un sistema di Service Discovery. Ci hè assai travagliu, è in certi lochi hè quasi impussibile quandu si tratta di dispositi di livellu bassu chì travaglianu à u nivellu di u kernel OS o direttamente cù u hardware. Implementazione di sta funziunalità utilizendu mudelli di suluzione stabilitu, cum'è side-car significaria in certi lochi una carica supplementu, in altri - una cumplicazione di l'operazione è scenarii di fallimentu supplementari. Ùn vulemu micca cumplicà e cose, cusì avemu decisu di fà l'usu di Service Discovery opzionale.

In una sola nuvola, l'IP seguita u cuntinuu, vale à dì chì ogni istanza di attività hà u so propiu indirizzu IP. Questu indirizzu hè "staticu": hè assignatu à ogni istanza quandu u serviziu hè mandatu prima à u nuvulu. Se un serviziu hà avutu un nùmeru sfarente di istanze durante a so vita, allora à a fine serà attribuitu quant'è indirizzi IP quant'è ci era istanze massimu.

In seguitu, sti indirizzi ùn cambianu micca: sò assignati una volta è cuntinueghjanu à esiste in tutta a vita di u serviziu in a produzzione. L'indirizzi IP seguitanu i cuntenituri in tutta a reta. Se u cuntinuu hè trasferitu à un altru minion, l'indirizzu seguitarà.

Cusì, a mappatura di un nome di serviziu à a so lista di indirizzi IP cambia assai raramenti. Se guardate torna à i nomi di l'istanze di serviziu chì avemu citatu à u principiu di l'articulu (1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, ...), avemu nutatu chì s'assumiglia à i FQDN utilizati in DNS. Hè propiu, per mapà i nomi di l'istanze di serviziu à i so indirizzi IP, usemu u protocolu DNS. Inoltre, stu DNS torna tutti l'indirizzi IP riservati di tutti i cuntenituri - sia in esecuzione sia fermati (dicemu chì trè repliche sò aduprate, è avemu cinque indirizzi riservati quì - tutti i cinque seranu tornati). I clienti, avè ricevutu sta informazione, pruvate à stabilisce una cunnessione cù tutti i cinque rèplichi - è cusì determinanu quelli chì travaglianu. Questa opzione per determinà a dispunibilità hè assai più affidabile; ùn implica nè DNS nè Service Discovery, chì significa chì ùn ci sò micca prublemi difficili per risolve per assicurà a pertinenza di l'infurmazioni è a tolleranza di difetti di questi sistemi. Inoltre, in i servizii critichi nantu à quale dipende u funziunamentu di u portale sanu, ùn pudemu micca aduprà DNS in tuttu, ma simpricimenti inserisce l'indirizzi IP in a cunfigurazione.

Implementà un tali trasferimentu IP daretu à i cuntenituri pò esse micca triviale - è guardemu cumu funziona cù l'esempiu seguente:

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Dicemu chì u maestru di una sola nuvola dà u cumandimu à minion M1 per correre 1.ok-web.group1.web.front.prod cù l'indirizzu 1.1.1.1. Funziona nantu à un servitore BIRDU, chì annuncia stu indirizzu à i servitori speciali riflettore di a strada. L'ultimi anu una sessione BGP cù u hardware di a rete, in quale a strada di l'indirizzu 1.1.1.1 in M1 hè tradutta. M1 indirizza i pacchetti in u containeru utilizendu Linux. Ci sò trè servitori di riflettori di rotte, postu chì questu hè una parte assai critica di l'infrastruttura di una sola nuvola - senza elli, a reta in una sola nuvola ùn funziona micca. Pudemu in diverse racks, se pussibule situate in diverse stanze di u centru di dati, per riduce a probabilità di tutti i trè fallimenti à u stessu tempu.

Assumimu avà chì a cunnessione trà u maestru di una sola nuvola è u minion M1 hè persa. U maestru di una sola nuvola agirà avà nantu à l'assunzione chì M1 hà fallutu cumplettamente. Questu hè, darà u cumandimu à u minion M2 per lancià web.group1.web.front.prod cù u listessu indirizzu 1.1.1.1. Avà avemu dui percorsi cunflitti nantu à a reta per 1.1.1.1: in M1 è in M2. Per risolve tali cunflitti, usemu u Discriminatore Multi Exit, chì hè specificatu in l'annunziu BGP. Questu hè un numeru chì mostra u pesu di a strada annunziata. Frà e rotte cunflittu, a strada cù u valore MED più bassu serà sceltu. U maestru one-cloud supporta MED cum'è una parte integrante di l'indirizzi IP di u containeru. Per a prima volta, l'indirizzu hè scrittu cù un MED abbastanza grande = 1 000 000. In a situazione di un tali trasferimentu di cuntainer d'urgenza, u maestru riduce u MED, è M2 hà digià ricevutu u cumandimu per publicità l'indirizzu 1.1.1.1 cù MED = 999 999. L'istanza chì corre nantu à M1 ferma in questu casu ùn ci hè micca una cunnessione, è u so destinu ulteriore ci interessa pocu finu à chì a cunnessione cù u maestru hè restauratu, quandu ellu serà firmatu cum'è un vechju piglià.

accidenti

Tutti i sistemi di gestione di u centru di dati sempre trattanu fallimenti minori in modu accettabile. L'overflow di u containeru hè a norma quasi in ogni locu.

Fighjemu cumu gestisce una emergenza, cum'è una mancanza di energia in una o più stanze di un centru di dati.

Chì significà un accidentu per un sistema di gestione di u centru di dati? Prima di tuttu, questu hè un fallimentu massivu di una sola volta di parechje machini, è u sistema di cuntrollu hà bisognu di migrà assai cuntenituri à u stessu tempu. Ma s'è u disastru hè assai grande, allura pò accade chì tutti i travaglii ùn ponu esse ri-assignati à altri minions, perchè a capacità di risorsa di u centru di dati cade sottu à 100% di a carica.

Spessu accidenti sò accumpagnati da fallimentu di a strata di cuntrollu. Questu pò succorsu per u fallimentu di u so equipamentu, ma più spessu per u fattu chì l'accidenti ùn sò micca pruvati, è a capa di cuntrollu stessu casca per via di a carica aumentata.

Chì pudete fà per tuttu questu?

E migrazioni di massa significanu chì ci hè un gran numaru d'attività, migrazioni è implementazioni chì sò in l'infrastruttura. Ciascuna di e migrazioni pò piglià un pocu di tempu necessariu per trasmette è unpack l'imaghjini di cuntenituri à i minions, lanciari è inizializza cuntenituri, etc. Per quessa, hè desideratu chì i travaglii più impurtanti sò lanciati prima di quelli menu impurtanti.

Fighjemu di novu à a ghjerarchia di i servizii chì avemu familiarizatu è pruvate di decide quali compiti vulemu eseguisce prima.

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Di sicuru, questi sò i prucessi chì sò direttamente implicati in u trattamentu di e dumande di l'utilizatori, vale à dì prod. Avemu indicatu questu cun priorità di piazzamentu - un numeru chì pò esse assignatu à a fila. Se una fila hà una priorità più alta, i so servizii sò posti prima.

On prod assignemu priorità più altu, 0; nantu à u batch - un pocu più bassu, 100; in idle - ancu più bassu, 200. I priurità sò appiicati hierarchicamente. Tutti i travaglii più bassi in a ghjerarchia anu una priorità currispondente. Se vulemu cache in prod per esse lanciatu prima di frontends, allora assignemu priorità à cache = 0 è à front subqueues = 1. Se, per esempiu, vulemu chì u portale principale sia lanciatu da i fronti prima, è u fronte di musica solu. allora, pudemu assignà una priorità più bassa à l'ultimi - 10.

U prublema dopu hè a mancanza di risorse. Allora, una grande quantità di l'equipaggiu, sala intera di u centru di dati, falliu, è avemu rilanciatu tanti servizii chì avà ùn sò micca abbastanza risorse per tutti. Avete bisognu di decisu quali compiti sacrificà per mantene i principali servizii critichi in funzione.

One-cloud - OS à livellu di centru di dati in Odnoklassniki

A cuntrariu di a priorità di piazzamentu, ùn pudemu micca sacrificà indiscriminatamente tutti i travaglii di batch; alcuni di elli sò impurtanti per u funziunamentu di u portale. Dunque, avemu evidenziatu separatamente priorità di preemption compiti. Quandu si mette, un compitu di priorità più altu pò preempt, vale à dì piantà, un compitu di priorità più bassa se ùn ci sò più servitori gratuiti. In questu casu, un compitu cù una priorità bassa prubabilmente restarà senza postu, vale à dì chì ùn ci sarà più un minion adattatu per ellu cù abbastanza risorse gratuiti.

In a nostra ghjerarchia, hè assai simplice di specificà una priorità di preemption such that prod and batch tasks preempt or stop idle tasks, ma micca l'una à l'altra, specificendu una priorità per idle uguale à 200. Cum'è in u casu di priorità di piazzamentu, avemu ponu aduprà a nostra ghjerarchia per discrivà e regule più cumplesse. Per esempiu, indichemu chì sacrificemu a funzione di musica se ùn avemu micca abbastanza risorse per u portale web principale, stabilisce a priorità per i nodi currispondenti più bassi: 10.

Incidenti interi DC

Perchè tuttu u centru di dati pò fallu? Elementu. Era un bonu postu l'uraganu hà affettatu u travagliu di u centru di dati. L'elementi ponu esse cunsideratu persone senza casa chì una volta brusgiatu l'ottica in u manifold, è u centru di dati persu completamente u cuntattu cù altri siti. A causa di u fallimentu pò ancu esse un fattore umanu: l'operatore emette un tali cumanda chì tuttu u centru di dati cascarà. Questu pò accade per via di un grande bug. In generale, u colapsu di i centri di dati ùn hè micca pocu cumuni. Questu succede à noi una volta ogni pochi mesi.

È questu hè ciò chì facemu per impedisce à qualcunu di tweeting #alive.

A prima strategia hè l'isulazione. Ogni istanza di una sola nuvola hè isolata è pò gestisce e macchine in un solu centru di dati. Vale à dì, a perdita di una nuvola per via di bug o cumandamenti di l'operatore incorrecte hè a perdita di un solu centru di dati. Semu pronti per questu: avemu una pulitica di redundancy in quale repliche di l'applicazione è e dati sò situati in tutti i centri di dati. Utilizemu basa di dati toleranti à i difetti è testemu periodicamente per i fallimenti.
Dapoi oghje avemu quattru centri di dati, questu significa quattru casi separati, completamente isolati di una sola nuvola.

Stu approcciu ùn solu prutege contr'à fallimentu fisicu, ma pò ancu prutegge contra l'errore di l'operatore.

Chì altru pò esse fattu cù u fattore umanu? Quandu un operatore dà à a nuvola un cumandamentu stranu o potenzialmente periculosu, pò esse dumandatu di colpu à risolve un picculu prublema per vede quantu pensava bè. Per esempiu, s'ellu hè un tipu di stop massa di parechje rèpliche o solu un cumandamentu stranu - riducendu u numeru di rèpliche o cambià u nome di l'imaghjini, è micca solu u numeru di versione in u novu manifestu.

One-cloud - OS à livellu di centru di dati in Odnoklassniki

Risultati

Funzioni distintive di una sola nuvola:

  • Schema di nomi gerarchicu è visuale per i servizii è cuntenituri, chì vi permette di sapè assai rapidamente quale hè u compitu, ciò chì hè in relazione è cumu si travaglia è quale hè rispunsevule per questu.
  • Avemu applicà u nostru tecnica di cumminazione di prudutti è batchcompiti nantu à i minions per migliurà l'efficienza di spartera di a macchina. Invece di cpuset usemu quote di CPU, azzioni, pulitiche di pianificazione di CPU è QoS Linux.
  • Ùn era micca pussibule di isolà cumplettamente i cuntenituri chì currenu nantu à a stessa macchina, ma a so influenza mutuale resta in u 20%.
  • L'urganizazione di i servizii in una gerarchia aiuta cù a ricuperazione automatica di u disastru priorità di piazzamentu è preemption.

FAQ

Perchè ùn avemu micca pigliatu una suluzione pronta ?

  • Diverse classi di isolamentu di u travagliu necessitanu una logica diversa quandu si mette nantu à i servitori. Se i travaglii di pruduzzione ponu esse piazzati solu riservendu risorse, allora i travaglii batch è inattivi sò deve esse piazzati, seguitendu l'utilizazione attuale di e risorse nantu à e macchine minion.
  • A necessità di piglià in contu e risorse cunsumate da i travaglii, cum'è:
    • larghezza di banda di a reta;
    • tipi è "spindles" di discu.
  • A necessità di indicà e priorità di i servizii durante a risposta d'urgenza, i diritti è i quote di cumandamenti per i risorsi, chì sò risolti cù file gerarchiche in una sola nuvola.
  • A necessità di avè un nome umanu di cuntenituri per riduce u tempu di risposta à l'accidenti è incidenti
  • L'impossibilità di una implementazione diffusa una volta di Service Discovery; a necessità di coexiste per un bellu pezzu cù i travaglii allughjati nantu à l'ospiti di hardware - qualcosa chì hè risolta da l'indirizzi IP "statici" chì seguitanu cuntenituri, è, in cunseguenza, a necessità di integrazione unica cù una grande infrastruttura di rete.

Tutte queste funzioni avaristi bisognu di mudificazioni impurtanti di e soluzioni esistenti per cunvene à noi, è, dopu avè valutatu a quantità di travagliu, avemu capitu chì pudemu sviluppà a nostra propria suluzione cù circa i stessi costi di travagliu. Ma a vostra suluzione serà assai più faciule per uperà è sviluppà - ùn cuntene micca astrazioni innecessarii chì sustenenu funziunalità chì ùn avemu micca bisognu.

À quelli chì leghjenu l'ultime righe, grazie per a vostra pacienza è attenzione !

Source: www.habr.com

Add a comment