
Aloha, everyone! My name is Oleg Anastasyev, and I work at Odnoklassniki in the Platform team. Besides me, there is a lot of hardware at Odnoklassniki. We have four data centers, which house about 500 racks with over 8 thousand servers. At some point, we realized that implementing a new management system would allow us to utilize the equipment more efficiently, simplify access management, automate the (re)distribution of computing resources, speed up the launch of new services, and accelerate responses to large-scale failures.
So, what did we achieve from this?
In addition to myself and the hardware, there are also people who work with this hardware: engineers who are directly in the data centers; network specialists who configure the networking equipment; admins, or SREs, who ensure the reliability of the infrastructure; and development teams, each responsible for part of the portal's functionalities. The software they create operates somewhat like this:

User requests come to both the frontend of the main portal , as well as to others, for example, the music API frontends. They call an application server to handle the business logic, which, during the processing of the request, invokes the necessary specialized microservices â one-graph (graph of social connections), user-cache (cache of user profiles), and so on.
Each of these services is deployed on multiple machines, and each has responsible developers who oversee the functioning of the modules, their operation, and technological development. All these services run on physical servers, and until recently, we would launch exactly one task per server, meaning it was specialized for a specific task.
Why is that? This approach had several advantages:
- It simplifies mass management. Suppose a task requires certain libraries and configurations. Then the server is assigned to a specific group, and a cfengine policy for this group is described (or it is already described), and this configuration is centrally and automatically deployed across all servers in that group.
- It simplifies diagnostics. Le të supozojmë se po shikoni një ngarkesë të rritur të procesorit qendror dhe e kuptoni se kjo ngarkesë mund të jetë gjeneruar vetëm nga ajo detyrë që po punon në këtë procesor hardware. Kërkimi i fajtorëve përfundon shumë shpejt.
- It simplifies monitorimi. Nëse ka diçka që nuk shkon me serverin, monitori njofton për këtë, dhe ju e dini saktësisht se kush është fajtor.
ShĂ«rbimi i pĂ«rbĂ«rĂ« nga disa replica, i cakton disa servera â njĂ« pĂ«r secilĂ«n. AtĂ«herĂ« burimi llogaritĂ«s pĂ«r shĂ«rbimin ndahen shumĂ« thjeshtĂ«: sa mĂ« shumĂ« servera ka shĂ«rbimi, aq mĂ« shumĂ« burime ai mund tĂ« konsumojĂ« maksimalisht. "ThjeshtĂ«" kĂ«tu nuk Ă«shtĂ« nĂ« kuptimin se Ă«shtĂ« e lehtĂ« pĂ«r t'u pĂ«rdorur, por se ndarja e burimeve ndodh manualisht.
Ky qasje gjithashtu na lejon të krijojmë konfiguracione të specializuara të hardware për detyrat që ekzekutohen në këtë server. Nëse detyra mban volumes të mëdha të dhënash, atëherë ne përdorim një server 4U me shasi për 38 disqe. Nëse detyra është thjesht llogaritëse, mund të blejmë një server 1U më të lirë. Kjo është efikase në raport me burimet llogaritëse. Kështu, ky qasje na lejon të përdorim katër herë më pak makina për ngarkesë që është e ngjashme me një rrjet social që na është miqësor.
Kjo efikasitet në përdorimin e burimeve llogaritëse duhet të sigurojë gjithashtu efikasitet ekonomik, nëse e marrim parasysh premisën se më e shtrenjta janë serverat. Për një kohë të gjatë, më e shtrenjtë ka qenë pikërisht hardware-i, dhe ne kemi investuar shumë në uljen e kostos së hardware-it, duke krijuar algoritmo për sigurimin e qëndrueshmërisë për të ulur kërkesat për besueshmërinë e pajisjeve. Dhe sot kemi arritur në një fazë ku kostoja e serverit nuk është më përcaktuese. Nëse nuk e marrim parasysh eksotikun më të fundit, konfigurimi specifik i serverëve në raft nuk ka rëndësi. Tani na ka lindur një problem tjetër - çmimi i hapësirës së mbajtur nga serveri në qendrën e të dhënave, pra, hapësira në raft.
Duke kuptuar se kjo është kështu, ne vendosëm të llogarisim se sa efikasisht po përdorim raftet.
Kemi marrë çmimin e serverit më të fuqishëm nga një këndvështrim ekonomik, llogaritëm se sa nga këta serverë mund të vendosnim në raftet e serverëve, sa detyra do të nisnim në bazë të modelit të vjetër "një server = një detyrë" dhe sa detyra do të ishin në gjendje të përdornin pajisjet. Llogaritëm dhe u emocionuam. Doli se efikasiteti i përdorimit të raftit ishte rreth 11%. Konkluzioni është i qartë: duhet të rritet efikasiteti i përdorimit të qendrave të të dhënave. Mund të duket si një zgjidhje e qartë: duhet të fillojmë disa detyra në një server të vetëm. Por këtu fillojnë vështirësitë.
Konfigurimi masiv komplikohet ndjeshĂ«m â tani Ă«shtĂ« e pamundur tĂ« caktohet njĂ« grup i vetĂ«m serverit. Sepse tani nĂ« njĂ« server mund tĂ« jenĂ« tĂ« nisura disa detyra nga skuadra tĂ« ndryshme. PĂ«r mĂ« tepĂ«r, konfigurimi mund tĂ« jetĂ« nĂ« konflikt pĂ«r aplikacione tĂ« ndryshme. Diagnostikimi gjithashtu komplikohet: nĂ«se shihni njĂ« rritje tĂ« konsumit tĂ« procesorĂ«ve ose disqeve nĂ« server, nuk e dini se cila nga detyrat po shkakton probleme.
Por e rĂ«ndĂ«sishmja Ă«shtĂ« se mes detyrave, tĂ« nisura nĂ« njĂ« makinĂ«, nuk ka izolim. PĂ«r shembull, grafiku i mesatarit tĂ« kohĂ«s sĂ« pĂ«rgjigjes pĂ«r njĂ« detyrĂ« nĂ« server para dhe pas nisjes sĂ« njĂ« aplikacioni tjetĂ«r, tĂ« pa lidhur me tĂ« parin â koha e marrjes sĂ« pĂ«rgjigjes pĂ«r detyrĂ«n kryesore Ă«shtĂ« rritur ndjeshĂ«m.

Qartë, duhet të nisnim detyrat ose në kontejnerë, ose në makina virtuale. Duke qenë se pothuajse të gjitha detyrat tona nisin nën menaxhimin e një sistemi operativ (Linux) ose janë përshtatur për të, mbajtja e shumë sistemeve operative të ndryshme nuk është e nevojshme. Prandaj, virtualizimi nuk është i nevojshëm, për shkak të shpenzimeve shtesë ai do të jetë më pak efikas se kontejnerizimi.
Si njĂ« realizim i konteinerĂ«ve pĂ«r tĂ« ekzekutuar detyra drejtpĂ«rdrejt nĂ« serverĂ«t Docker â Ă«shtĂ« njĂ« kandidat i mirĂ«: imazhet e sistemeve tĂ« skedarĂ«ve zgjidhin mirĂ« problemet me konfigurimet nĂ« konflikt. Ajo qĂ« imazhet mund tĂ« pĂ«rbĂ«hen nga disa nivele na lejon tĂ« zvogĂ«lojmĂ« ndjeshĂ«m volumet e tĂ« dhĂ«nave qĂ« nevojiten pĂ«r vendosjen e tyre nĂ« infrastrukturĂ«, duke ndarĂ« pjesĂ«t e pĂ«rbashkĂ«ta nĂ« nivele themelore tĂ« veçanta. AtĂ«herĂ« nivelet themelore (dhe mĂ« tĂ« mĂ«dhatĂ«) do tĂ« cache-ohen mjaft shpejt nĂ« tĂ« gjithĂ« infrastrukturĂ«n, dhe pĂ«r tĂ« dorĂ«zuar njĂ« shumĂ«llojshmĂ«ri aplikacionesh dhe versionesh, do tĂ« jetĂ« e nevojshme tĂ« dĂ«rgohen vetĂ«m nivele tĂ« vogla.
Plus, regjistri i gatshëm dhe etiketimi i imazheve në Docker na japin primitivë të gatshëm për versionim dhe dorëzim të kodit në production.
Docker, si çdo teknologji tjetĂ«r e ngjashme, na ofron njĂ« nivel tĂ« caktuar izolimi tĂ« konteinerĂ«ve nga kuti. PĂ«r shembull, izolimi i memories â çdo kontejner merr njĂ« kufi pĂ«r pĂ«rdorimin e memories sĂ« makinĂ«s, pĂ«rtej tĂ« cilit nuk do ta konsumojĂ«. Gjithashtu, mund tĂ« izoloheshin konteinerĂ«t pĂ«r pĂ«rdorimin e CPU-sĂ«. SidoqoftĂ«, pĂ«r ne, izolimi standard ishte i pamjaftueshĂ«m. Por pĂ«r kĂ«tĂ« â mĂ« poshtĂ«.
Ekzekutimi i drejtpërdrejtë i konteinerëve në serverë është vetëm një pjesë e problemeve. Një pjesë tjetër lidhet me vendosjen e konteinerëve në serverë. Duhet të kuptojmë se cili kontejner mund të vendoset në cilin server. Kjo nuk është një detyrë e thjeshtë, sepse konteinerët duhet të vendosen në serverë sa më ngushtë të jetë e mundur, pa ulur shpejtësinë e punës së tyre. Kjo vendosje mund të jetë e komplikuar dhe në aspektin e disponueshmërisë. Shpesh ne duam të vendosim replika të njëjtit shërbim në raftet e ndryshme ose madje në sallat e ndryshme të qendrës së të dhënave, në mënyrë që në rast të disfatës së raftit ose sallës, të mos humbasim të gjitha replikat e shërbimit menjëherë.
Derdhja e konteinerĂ«ve me dorĂ« â nuk Ă«shtĂ« njĂ« opsion, kur ke 8 mijĂ« serverĂ« dhe 8â16 mijĂ« konteinerĂ«.
Përveç kësaj, ne donim t'u japim zhvilluesve më shumë autonomi në shpërndarjen e burimeve, në mënyrë që të mund të vendosnin shërbimet e tyre në production, pa ndihmën e administratorit. Në të njëjtën kohë, donim të ruanim kontrollin, në mënyrë që ndonjë shërbim dytësor të mos konsumonte të gjithë burimet e qendrave tona të të dhënave.
Qartë është se na nevojitet një shtresë menaxhuese, e cila do merret automatikisht me këto.
Ja kemi në një imazh të thjeshtë dhe të qartë, të cilin e adhurojnë të gjithë arkitektët: tre katrorë.

one-cloud masters â njĂ« klaster i besueshĂ«m qĂ« Ă«shtĂ« pĂ«rgjegjĂ«s pĂ«r orkestrimin e cloud-it. Zhvilluesi dĂ«rgon nĂ« master njĂ« manifest, nĂ« tĂ« cilin pĂ«rmban tĂ« gjitha informacionet e nevojshme pĂ«r vendosjen e shĂ«rbimit. Masteri, mbi kĂ«tĂ« bazĂ«, jep komanda minjoneve tĂ« zgjedhura (makinave tĂ« destinuara pĂ«r tĂ« drejtuar kontejnerĂ«t). NĂ« minjone ka agjentin tonĂ«, i cili merr komandĂ«n, i jep komandat e tij Docker-it dhe Docker-i konfiguron kernelin linux pĂ«r tĂ« ndezur kontejnerin pĂ«rkatĂ«s. PĂ«rveç ekzekutimit tĂ« komandave, agjenti vazhdimisht i raporton masterit pĂ«r ndryshimet nĂ« gjendjen e minjoneve dhe kontejnerĂ«ve tĂ« ndezur mbi to.
Shpërndarja e burimeve
Tani le të merremi me detyrën e shpërndarjes më të ndërlikuar të burimeve për shumë minjone.
Burimi llogaritës në one-cloud është:
- Kapaciteti llogaritës i procesorit, i konsumuar nga një detyrë specifike.
- Sasia e memories, e disponueshme për detyrën.
- Trafiku i rrjetit. Ădo minjon ka njĂ« interfaks tĂ« caktuar rrjeti me njĂ« kapacitet tĂ« kufizuar, kĂ«shtu qĂ« nuk mund tĂ« shpĂ«rndahen detyra pa marrĂ« parasysh sasinĂ« e tĂ« dhĂ«nave qĂ« kalohen pĂ«rmes rrjetit.
- DiskĂ«t. PĂ«rveç, natyrisht, vendit pĂ«r tĂ« dhĂ«nat e detyrĂ«s, ne gjithashtu caktuam llojin e diskut: HDD ose SSD. DiskĂ«t mund tĂ« shĂ«rbejnĂ« njĂ« numri tĂ« caktuar kĂ«rkesash nĂ« sekondĂ« â IOPS. Prandaj, pĂ«r detyrat qĂ« gjenerojnĂ« mĂ« shumĂ« IOPS sesa mund tĂ« shĂ«rbejĂ« njĂ« disk, ne gjithashtu caktuam "spindles" â dmth. disa pajisje disku qĂ« duhet tĂ« rezervohen ekskluzivisht pĂ«r detyrĂ«n.
Atëherë për ndonjë shërbim, për shembull për user-cache, ne mund ta shkruajmë konsumin e burimeve në këtë mënyrë: 400 bërthama procesori, 2.5 TByte memorie, 50 Gbit/s trafik në të dy drejtimet, 6 TByte hapësirë në HDD, e vendosur në 100 spindles. Ose në një formë më të njohur për ne kështu:
alloc:
cpu: 400
mem: 2500
lan_in: 50g
lan_out: 50g
hdd:100x6TBurimet e shërbimit user-cache konsumojnë vetëm një pjesë të gjitha burimeve të disponueshme në infrastrukturën e prodhimit. Prandaj, dëshirojmë të bëjmë në mënyrë që, papritur, për shkak të një gabimi nga operatori ose jo, user-cache të mos konsumojë më shumë burime se sa i janë caktuar. Kështu, ne duhet të limitojmë burimet. Por çfarë mund të lidhim me kuotën?
Le tĂ« kthehemi nĂ« skemĂ«n tonĂ« tĂ« thjeshtuar tĂ« bashkĂ«punimit tĂ« komponentĂ«ve dhe ta rrisim atĂ« me mĂ« shumĂ« detaje â kĂ«shtu:

ĂfarĂ« bie nĂ« sy:
- Frontend-i i uebit dhe muzika përdorin klastere izoluese të së njëjtës server aplikacionesh.
- Mund të dallojmë nivele logjike, të cilat përfshijnë këto klastere: frontet, cache-t, niveli i ruajtjes dhe menaxhimit të të dhënave.
- Frontend-i është i ndryshëm, janë në sistemet funksionale të ndryshme.
- Cache-t gjithashtu mund të shpërndahen nëpër nën-sistemin, të dhënat të cilat ato i ruajnë.
Le të rrisim përsëri figurën:

Ooo! Ne shohim njĂ« hierarki! Kjo do tĂ« thotĂ« se mund tĂ« ndajmĂ« burimet mĂ« shpesh: tĂ« caktojmĂ« njĂ« zhvillues pĂ«rgjegjĂ«s pĂ«r njĂ« nyje tĂ« kĂ«saj hierarkie, pĂ«rkatĂ«sisht pĂ«r nĂ«n-sistemin funksional (si âmusicâ nĂ« figurĂ«), dhe ky nivel hierarkie do tĂ« lidhet me kuotĂ«n. Kjo hierarki gjithashtu na lejon tĂ« organizojmĂ« shĂ«rbime mĂ« fleksibĂ«l pĂ«r njĂ« menaxhim mĂ« tĂ« lehtĂ«. PĂ«r shembull, tĂ« gjithĂ« web, pasi Ă«shtĂ« njĂ« grumbull shumĂ« i madh serverĂ«sh, e ndajmĂ« nĂ« disa grupe mĂ« tĂ« vogla, tĂ« cilat paraqiten nĂ« figurĂ« si group1, group2.
Duke hequr vijat e tepërta, mund të shkruajmë çdo nyje të figurës sonë në një formë më të sheshtë: group1.web.front, api.music.front, user-cache.cache.
KĂ«shtu arrijmĂ« te koncepti i âradhĂ«s hierarkikeâ. Ajo ka emrin, si âgroup1.web.frontâ. PĂ«r tĂ« caktohet njĂ« kuotĂ« pĂ«r burimet dhe tĂ« drejtat e pĂ«rdoruesve. NjĂ« person nga DevOps do t'i japĂ« tĂ« drejtat pĂ«r tĂ« dĂ«rguar shĂ«rbimin nĂ« radhĂ«, dhe ky punonjĂ«s mund tĂ« fillojĂ« diçka nĂ« radhĂ«, ndĂ«rsa njĂ« person nga OpsDev do tĂ« ketĂ« tĂ« drejta administrimi, dhe tani ai mund tĂ« menaxhojĂ« radhĂ«n, t'u caktojĂ« njerĂ«z, t'u japĂ« kĂ«tyre njerĂ«zve tĂ« drejta etj. ShĂ«rbimet e filluara nĂ« kĂ«tĂ« radhĂ« do tĂ« ekzekutohen brenda kuotĂ«s sĂ« radhĂ«s. NĂ«se kuota kompjuterike e radhĂ«s nuk Ă«shtĂ« e mjaftueshme pĂ«r tĂ« ekzekutuar tĂ« gjitha shĂ«rbimet njĂ«kohĂ«sisht, ato do tĂ« ekzekutohen njĂ« nga njĂ«, duke formuar kĂ«shtu pikĂ«risht radhĂ«n.
TĂ« shqyrtojmĂ« shĂ«rbimet mĂ« nĂ« detaje. NjĂ« shĂ«rbim ka njĂ« emĂ«r tĂ« plotĂ«, i cili gjithmonĂ« pĂ«rfshin emrin e radhĂ«s. AtĂ«herĂ« shĂ«rbimi i frontend-it tĂ« web do tĂ« ketĂ« emrin ok-web.group1.web.front. NdĂ«rsa shĂ«rbimi i serverit tĂ« aplikacioneve, me tĂ« cilin ai lidhet, do tĂ« emĂ«rohet ok-app.group1.web.frontĂdo shĂ«rbim ka njĂ« manifest, nĂ« tĂ« cilin pĂ«rcaktohen tĂ« gjitha informacionet e nevojshme pĂ«r vendosjen nĂ« makinat pĂ«rkatĂ«se: sa burime konsumon kjo detyrĂ«, çfarĂ« konfigure i nevojitet, sa kopje duhet tĂ« jenĂ«, vetitĂ« pĂ«r pĂ«rballimin e dĂ«shtimeve tĂ« kĂ«tij shĂ«rbimi. Dhe pas vendosjes sĂ« shĂ«rbimit nĂ« makinat, shfaqen instancat e tij. Ato emĂ«rtohen gjithashtu nĂ« mĂ«nyrĂ« unike â si numri i instancĂ«s dhe emri i shĂ«rbimit: 1.ok-web.group1.web.front, 2.ok-web.group1.web.front, âŠ
Kjo është shumë e dobishme: duke parë vetëm emrin e enjtës së nisur, ne mund të zbulojmë shumë.
Tani le të njiheni më afër me atë që këto instanca, në të vërtetë, bëjnë: me detyrat.
Klasa e izolimit të detyrave
Të gjitha detyrat në OK (dhe ndoshta kudo) mund të ndahen në grupe:
- Detyrat me vonesĂ« tĂ« shkurtĂ«r â prodhimi. PĂ«r kĂ«to detyra dhe shĂ«rbime, vonesa e pĂ«rgjigjes (latencija) Ă«shtĂ« shumĂ« e rĂ«ndĂ«sishme, sa shpejt çdo kĂ«rkesĂ« do tĂ« pĂ«rpunojĂ« sistemi. Shembuj tĂ« detyrave: frontet web, cache, serverĂ«t e aplikacioneve, depozitat OLTP dhe kĂ«shtu me radhĂ«.
- Detyrat e llogaritjes â grumbuj. KĂ«tu shpejtĂ«sia e pĂ«rpunimit tĂ« çdo kĂ«rkese tĂ« veçantĂ« nuk Ă«shtĂ« e rĂ«ndĂ«sishme. E rĂ«ndĂ«sishme Ă«shtĂ« sa llogaritje gjithsej pĂ«r njĂ« (tĂ« madh) interval kohor kjo detyrĂ« do tĂ« bĂ«jĂ« (shpejtĂ«sia). KĂ«to do tĂ« jenĂ« çdo detyrĂ« MapReduce, Hadoop, mĂ«simi i makinerisĂ«, statistika.
- Detyrat anĂ«sore â papunĂ«. PĂ«r kĂ«to detyra as latency as shpejtĂ«sia nuk janĂ« shumĂ« tĂ« rĂ«ndĂ«sishme. KĂ«tu pĂ«rfshihen teste tĂ« ndryshme, migrime, llogaritje, konvertime tĂ« tĂ« dhĂ«nave nga njĂ« format nĂ« atĂ« tjetĂ«r. Nga njĂ«ra anĂ«, ato duken si detyrat e llogaritjes, nga ana tjetĂ«r â nuk Ă«shtĂ« shumĂ« e rĂ«ndĂ«sishme se sa shpejt do tĂ« pĂ«rfundojnĂ«.
Le të shikojmë si konsumojnë këto detyra burime, për shembull, të procesorit qendror.
Detyrat me vonesë të shkurtër. Një detyrë e tillë do të ketë një model konsumi të CPU-së si ky:

KĂ«rkesa vije nga pĂ«rdoruesi, detyra fillon tĂ« pĂ«rdorĂ« tĂ« gjitha bĂ«rthamat e disponueshme tĂ« CPU-sĂ«, pĂ«rfundon, kthen njĂ« pĂ«rgjigje, pret kĂ«rkesĂ«n tjetĂ«r dhe qĂ«ndron. Vjen kĂ«rkesa tjetĂ«r â pĂ«rsĂ«ri dĂ«gjohen tĂ« gjitha ato qĂ« ishin, pĂ«rpunohen, presim kĂ«rkesĂ«n tjetĂ«r.
Për të garantuar vonesën minimale për një detyrë të tillë, ne duhet të marrim maksimumin e burimeve të konsumuar prej saj dhe të rezervojmë numrin e nevojshëm të bërthamave në minjon (makina që do të kryejë detyrën). Atëherë formula e rezervimit për detyrën tonë do të jetë si kjo:
alloc: cpu = 4 (maks)Dhe nĂ«se kemi njĂ« server mini me 16 bĂ«rthama, atĂ«herĂ« mund tĂ« vendosim pikĂ«risht katĂ«r nga kĂ«to detyra. ShĂ«noni se konsumi mesatar i procesorit pĂ«r kĂ«to detyra shpesh Ă«shtĂ« shumĂ« i ulĂ«t â çka Ă«shtĂ« e qartĂ«, pasi njĂ« pjesĂ« tĂ« madhe tĂ« kohĂ«s detyra Ă«shtĂ« nĂ« pritje tĂ« njĂ« kĂ«rkese dhe nuk bĂ«n asgjĂ«.
Detyrat e llogaritjes. Ato do të kenë një model paksa ndryshe:

Konsumi mesatar i burimeve të procesorit për këto detyra është mjaft i lartë. Shpesh ne duam që detyra e llogaritjes të përfundojë brenda një kohe të caktuar, prandaj duhen rezervuar numrin minimal të procesorëve që i nevojiten asaj, në mënyrë që llogaritja të përfundojë brenda një kohe të pranueshme. Formula e saj për rezervimin do të duket kështu:
alloc: cpu = [1,*)«TĂ« lutem, vendose nĂ« mini, ku ka tĂ« paktĂ«n njĂ« bĂ«rthamĂ« tĂ« lirĂ«, dhe pastaj gjithçka qĂ« ka mbetur â do ta konsumojë».
KĂ«tu efikasiteti i pĂ«rdorimit Ă«shtĂ« tashmĂ« ndjeshĂ«m mĂ« i mirĂ« se pĂ«r detyrat me vonesĂ« tĂ« shkurtĂ«r. Por fitimi do tĂ« jetĂ« shumĂ« mĂ« i madh nĂ«se kombinojmĂ« tĂ« dyja llojet e detyrave nĂ« njĂ« server mini dhe shpĂ«rndajmĂ« burimet e saj nĂ« lĂ«vizje. Kur detyra me vonesĂ« tĂ« shkurtĂ«r kĂ«rkon procesorin â ajo e merr atĂ« menjĂ«herĂ«, dhe kur burimet nuk janĂ« mĂ« tĂ« nevojshme â ato i kalohen detyrĂ«s sĂ« llogaritjes, pra, diçka si kjo:

Por si ta bëjmë këtë?
Së pari, le të kuptojmë prodhimin dhe alloc: cpu = 4. Na duhen katër bërthama të rezervuara. Në Docker run, kjo mund të bëhet në dy mënyra:
- Me opsionin
--cpuset=1-4, dmth. të alokosh katër bërthama të caktuara për detyrën në server. - Përdorni
--cpuquota=400_000 --cpuperiod=100_000, të caktosh një kuotë për kohën e procesorit, dmth. të tregosh se për çdo 100 ms të kohës reale detyra konsumon jo më shumë se 400 ms të kohës së procesorit. Kështu, arrijmë të njëjtat katër bërthama.
Por cili nga këto mënyra i përshtatet?
Duket mjaft tërheqëse cpuset. Detyra ka katër bërthama të dedikuara, kështu që caches e procesorëve do të punojnë sa më efikashtë. Kjo ka dhe anën e saj të errët: do të na duhej të merrnim përsipër shpërndarjen e llogaritjeve për bërthamat e papopulluara të makinës në vend të OS-së, gjë që është një detyrë mjaft e ndërlikuar, veçanërisht nëse përpiqemi të vendosim detyrat batch në një makinë të tillë. Testet treguan se opsioni me kuotë përshtatet më mirë këtu: kështu që sistemi operativ ka më shumë liri në zgjedhjen e bërthamës për ekzekutimin e detyrës në momentin aktual dhe koha e procesorit shpërndahet më efikasht.
Le të shohim si të bëjmë rezervë në docker me numrin minimal të bërthamave. Kuota për detyrat batch tashmë nuk është e përdorshme, sepse nuk është e nevojshme të kufizohet maksimumi, mjafton të garantohet minimumi. Dhe këtu përshtatet mirë opsioni docker run --cpushares.
Kemi rënë dakord që nëse batch kërkon garanci minimale për një bërthamë, atëherë ne tregojmë --cpushares=1024, dhe nëse minimumi është për dy bërthama, atëherë tregojmë --cpushares=2048. Cpu shares nuk ndihmojnë në shpërndarjen e kohës së procesorit deri sa ajo të mjaftojë. Kështu, nëse prodhimi nuk përdor të katra bërthamën e tij, asgjë nuk e kufizon detyrat batch dhe ato mund të përdorin kohë shtesë të procesorit. Por në rastin kur ka mungesë procesori, nëse prodhimi ka konsumuar të katër bërthatë dhe ka arritur kuotën, koha e mbetur e procesorit do të ndahet proporcionalisht sipas cpushares, dmth. në situatën me tre bërthama të lira, njëra do ta marrë detyra me 1024 cpushares, dhe dy të tjera do ta marrin detyra me 2048 cpushares.
Por përdorimi i kuotës dhe aksioneve nuk është mjaft. Na nevojitet që detyra me vonesë të shkurtër të ketë përparësi mbi detyrën batch gjatë shpërndarjes së kohës së procesorit. Pa një përprioritizim të tillë, detyra batch do të marrë të gjitha kohën e procesorit në momentin kur ajo nevojitet për prodhim. Në Docker run nuk ka opsione të përprioritizimit të konteinerëve, por ndihmohen nga politikashin e planifikuesit të procesorëve në Linux. Mund të lexoni më shumë për to , dhe në këtë artikull ne do të kalojmë për to shkurtimisht:
- SCHED_OTHER
Fillimisht marrin të gjithë proceset normale të përdoruesve në një makinë Linux. - SCHED_BATCH
E përshtatur për procese kërkuese për burime. Kur vendoset një detyrë në procesor, hyn një ndëshkim i quajtur aktivizim: një detyrë e tillë me probabilitet të vogël do të marrë burime nga procesori, nëse në atë moment po përdoret nga një detyrë me SCHED_OTHER. - SCHED_IDLE
NjĂ« proces i sfondit me prioritet shumĂ« tĂ« ulĂ«t, edhe mĂ« tĂ« ulĂ«t se nice â19. Ne pĂ«rdorim bibliotekĂ«n tonĂ« me kod tĂ« hapur. , pĂ«r tĂ« vendosur politikĂ«n e nevojshme gjatĂ« lançimit tĂ« kontejnerit pĂ«rmes thirrjes.
one.nio.os.Proc.sched_setscheduler( pid, Proc.SCHED_IDLE )Por edhe nëse nuk programoni në Java, të njëjtën gjë mund ta bëni me komandën chrt:
chrt -i 0 $pidDo t'i përmbledhim të gjitha nivelet tona të izolimit në një tabelë për qartësi:
Klasa e izolimit
Shembulli alloc
Opsionet Docker run
sched_setscheduler chrt*
Prod
cpu = 4
--cpuquota=400000 --cpuperiod=100000
SCHED_OTHER
Batch
Cpu = [1, * )
--cpushares=1024
SCHED_BATCH
Përgjithësisht
Cpu= [2, *)
--cpushares=2048
SCHED_IDLE
*Nëse bëni chrt nga brenda kontejnerit, mund të nevojitet kapaciteti sys_nice, sepse në mënyrë të paracaktuar Docker e heq këtë kapacitet gjatë lançimit të kontejnerit.
Por detyrat nuk konsumojnë vetëm procesorin, por gjithashtu trafikun, i cili ndikon në vonesën e detyrave rrjetërore edhe më shumë se shpërndarja e gabuar e burimeve të procesorit. Prandaj, natyrisht, duam të kemi një pamje të njëjtë edhe për trafikun. Kjo do të thotë, kur detyra prodhimi dërgon disa paketa në rrjet, ne caktuar shpejtësinë maksimale (formula alloc: lan=[*,500mbps) ), me të cilën prodhimi mund ta bëjë këtë. Dhe për batch ne garantojmë vetëm kapacitetin minimal, por nuk e kufizojmë maksimalin (formula alloc: lan=[10Mbps,*) ) Në këtë rast, trafiku prodhim duhet të ketë prioritet mbi detyrat batch.
Këtu Docker nuk ka asnjë primitiv që mund të përdorim. Por na vjen në ndihmë . Ne arritëm rezultatet e dëshiruara përmes disiplinës . Me ndihmën e saj, ne ndajmë dy klasa trafiku: prodhimi me prioritet të lartë dhe batch/i papunë me prioritet të ulët. Si rezultat, konfigurimi për trafikun e daljes është kjo:
kĂ«tu 1:0 â «qdisc rrĂ«njĂ«sor» i disiplinĂ«s hsfc; 1:1 â klasa nĂ«npunĂ«s hsfc me njĂ« kufi tĂ« pĂ«rgjithshĂ«m tĂ« kapacitetit prej 8 Gbit/s, nĂ«n tĂ« cilĂ«n vendosen klasat nĂ«npunĂ«se tĂ« tĂ« gjithĂ« konteinerĂ«ve; 1:2 â klasa nĂ«npunĂ«s hsfc e cila Ă«shtĂ« e pĂ«rbashkĂ«t pĂ«r tĂ« gjitha detyrat batch dhe idle me njĂ« limit «dinamik», pĂ«r tĂ« cilin do tĂ« flasim mĂ« poshtĂ«. Klasa tĂ« tjera nĂ«npunĂ«s hsfc janĂ« klasa tĂ« dedikuara pĂ«r konteinerĂ«t prodhues qĂ« punojnĂ« aktualisht me kufij qĂ« pĂ«rkojnĂ« me manifestet e tyre, â 450 dhe 400 Mbit/s. Ădo klasĂ« hsfc ka njĂ« radhĂ« qdiscip fq ose fq_codel, nĂ« varĂ«si tĂ« versionit tĂ« kernelit linux, pĂ«r tĂ« shmangur humbjet e pacjeve gjatĂ« shpĂ«rthimeve tĂ« trafikut.
Zakonisht disiplinat tc shĂ«rbejnĂ« pĂ«r tĂ« prioritarizuar vetĂ«m trafikun e daljes. Por ne duam tĂ« prioritarizojmĂ« edhe trafik hyrĂ«s â sepse ndonjĂ« detyrĂ« batch mund tĂ« zgjedhĂ« lehtĂ«sisht tĂ« gjithĂ« kanalin hyrĂ«s, duke marrĂ«, pĂ«r shembull, njĂ« paketĂ« tĂ« madhe tĂ« tĂ« dhĂ«nave hyrĂ«se pĂ«r map&reduce. PĂ«r kĂ«tĂ« ne pĂ«rdorim modulin , i cili krijon njĂ« ndĂ«rfaqe virtuale ifbX pĂ«r çdo ndĂ«rfaqe rrjeti dhe ndihmon nĂ« ridrejktimin e trafikut hyrĂ«s nga ndĂ«rfaqja nĂ« daljen pĂ«r ifbX. MĂ« pas pĂ«r ifbX funksionojnĂ« tĂ« gjitha ato disiplinat pĂ«r kontrollin e trafikut tĂ« daljes, pĂ«r tĂ« cilat konfigurimi hsfc do tĂ« jetĂ« shumĂ« i ngjashĂ«m:
Gjatë eksperimenteve, zbuluam se rezultatet më të mira hsfc shfaqen kur klasa 1:2 e trafikut batch/idle pa prioritet kufizohet në makinat-minion jo më shumë se deri në një bandë të lirë. Në të kundërt, trafiku pa prioritet ndikon shumë në vonesat e detyrave prodhuese. Vlera aktuale e bandës së lirë miniond përcaktohet çdo sekondë, duke matur mesataren e konsumit të trafikut nga të gjitha detyrat prodhuese të këtij minioni
dhe duke e zbritur atë nga kapaciteti i ndërfaqes rrjetit
me një rezervë të vogël, dmth.

Banda përcaktohet për trafikun hyrës dhe dalës në mënyrë të pavarur. Dhe në përputhje me vlerat e reja, miniond rindërton limitin e klasës pa prioritet 1:2.
Kështu kemi realizuar të tri klasat e izolimit: prod, batch dhe idle. Këto klasa ndikon shumë në karakteristikat e ekzekutimit të detyrave. Prandaj vendosëm që ta vendosim këtë tipar në majë të hierarkisë, në mënyrë që në një shikim mbi emrin e radhës hierarkike të kuptohet menjëherë me çfarë kemi të bëjmë:

Të gjitha frontet tona të njohura web dhe music atëherë vendosen në hierarki nën prod. Për shembull, nën batch le të vendosim shërbimin music catalog, i cili her pas krijon një katalog këngësh nga një grup skedash mp3 të ngarkuara në «Odnoklassniki». Një shembull shërbimi nën idle mund të jetë transformuesi muzikor, i cili normalizon nivelin e volumit të muzikës.
Me heqjen e vijave të panevojshme, ne mund ta shkruajmë emrin e shërbimeve tona më të sheshta, duke shtuar klasën e izolimit të detyrës në fund të emrit të plotë të shërbimit: web.front.prod, catalog.music.batch, transformer.music.idle.
Dhe tani, duke e parë emrin e shërbimit, ne kuptojmë jo vetëm se çfarë funksioni kryen, por edhe klasën e tij të izolimit, dhe për këtë arsye, kritikësinë e tij, etj.
Gjithçka është e shkëlqyer, por ka një të vërtetë të hidhur. Izolimi i plotë i detyrave që funksionojnë në një makinë është i pamundur.
Ajo çfarĂ« arritĂ«m: nĂ«se batch konsumon shumĂ« tĂ« burime tĂ« procesorit, atĂ«herĂ« planifikuesi i integruar i CPU Linux e bĂ«n shumĂ« mirĂ« punĂ«n e tij, dhe ndikimi nĂ« detyrĂ«n prod Ă«shtĂ« praktikisht i padukshĂ«m. Por nĂ«se kjo detyrĂ« batch fillon tĂ« punojĂ« aktivisht me memorien, atĂ«herĂ« ndikimi ndĂ«rmjet tyre fillon tĂ« shfaqet. Kjo ndodh sepse te detyra prod âhiqenâ cache-t e procesorit nga memoria â si rezultat, rriten humbjet nĂ« cache, dhe procesori e pĂ«rpunon detyrĂ«n prod mĂ« ngadalĂ«. NjĂ« detyrĂ« e tillĂ« batch mund tĂ« rrisĂ« vonesat e kontejnerit tonĂ« tipik prod me 10%.
Izolimi i trafikut Ă«shtĂ« edhe mĂ« i komplikuar pĂ«r shkak se kartat moderne tĂ« rrjetit kanĂ« njĂ« radhĂ« tĂ« brendshme paketash. NĂ«se njĂ« paketĂ« nga detyra batch arrin aty e para, atĂ«herĂ« ajo do tĂ« dĂ«rgohet e para nĂ«pĂ«r kabllin, dhe kĂ«tu sâka çfarĂ« tĂ« bĂ«sh.
Përveç kësaj, deri tani kemi arritur të zgjidhim vetëm detyrën e prioritetizimit të trafikut TCP: për UDP, qasja me hsfc nuk funksionon. Dhe madje në rastin e trafikut TCP, nëse detyra batch gjeneron shumë trafik, kjo gjithashtu jep rreth 10% rritje të vonesës së detyrës prod.
Qëndrueshmëri
NjĂ« nga qĂ«llimet gjatĂ« zhvillimit tĂ« one-cloud ishte pĂ«rmirĂ«simi i qĂ«ndrueshmĂ«risĂ« sĂ« Odnoklassniki. Prandaj, mĂ« pas do tĂ« doja tĂ« shqyrtoj skenaret e mundshme tĂ« dĂ«shtimeve dhe fatkeqĂ«sive. Le tĂ« fillojmĂ« me njĂ« skenar tĂ« thjeshtĂ« â me dĂ«shtimin e kontejnerit.
Kontejneri mund të dështojnë në disa mënyra. Kjo mund të jetë një eksperiment, një gabim ose një problem në manifest, që bën që detyra prodhuese të konsumojë më shumë burime se ç'është përcaktuar në manifest. Kemi pasur një rast: një zhvillues implementoi një algoritëm të komplikuar, e rishikoi atë shumë herë, e komplikoi vetveten dhe u ngatërrua deri sa në fund detyra filloi të humbiste rreth. Dhe për shkak se detyra prodhuese ka përparësi mbi të gjitha të tjerat në këto minj, ajo filloi të konsumonte të gjitha burimet e disponueshme të procesorit. Në këtë situatë, izolimi ndihmoi, ose më saktë, kuota e kohës së procesorit. Nëse detyrës i është caktuar një kuotë, ajo nuk do të konsumojë më shumë. Prandaj, detyrat e lotit dhe të tjera prodhuese që punonin në të njëjtën makinë nuk vunë re asgjë.
Një problem tjetër i mundshëm është rënia e konteinerit. Dhe këtu na shpëtojnë politikat e rikthimit, të cilat të gjithë i njohin, Docker përballohet shkëlqyeshëm me këtë. Praktikisht të gjitha detyrat prodhuese kanë një politikë rikthimi gjithmonë. Ndonjëherë përdorim on_failure për detyrat e lotit ose për rikthimin e konteinerëve prodhues.
Por çfarë mund të bëjmë kur një minjë e tërë është e paqëndrueshme?
Sigurisht, mund të nisim një kontejner në një makinë tjetër. Gjëja më interesante këtu është se çfarë ndodh me adresat IP (adresat), që i janë caktuar kontejnerit.
Ne mund të caktojmë kontejnerëve të njëjtat adresa IP si ato të makinave-minj, ku këta kontejnerë po nisin. Pastaj, kur kontejneri nis në një makinë tjetër, adresa e tij IP ndryshon, dhe të gjithë klientët duhet të kuptojnë se kontejneri ka shpërngulur, tani duhet të shkojnë në një adresë tjetër, e cila kërkon një shërbim të veçantë të Zbulimit të Shërbimeve.
Zbulimi i Shërbimeve është i këndshëm. Në treg ka shumë zgjidhje të niveleve të ndryshme të besueshmërisë për organizimin e regjistrit të shërbimeve. Shpesh në këto zgjidhje implementohet logjika e balancuesit të ngarkesës, ruajtja e konfigurimeve të tjera në formë të ruajtjes KV etj.
Megjithatë, ne do të preferonim të ishim pa nevojën për të implementuar një regjistër të veçantë, sepse kjo do të nënkuptonte hyrjen e një sistemi kritik, i cili përdoret nga të gjitha shërbimet në prodhim. Dhe kjo do të thoshte se është një pikë e mundshme dështimi, dhe duhet të zgjidhni ose të zhvilloni një zgjidhje shumë të besueshme, e cila, është e qartë, është shumë e komplikuar, e gjatë dhe e shtrenjtë.
Një tjetër mangësi e madhe është se për ta bërë infrastrukturën tonë të vjetër të funksionojë me të re, do të duhej të rishkruanim çdo detyrë për t'u përshtatur me ndonjë sistem të Zbulimit të Shërbimeve. Ka shumë punë, madje në disa raste është e pamundur, sidomos kur flitet për pajisje të nivelit të ulët që funksionojnë në nivelin e bërthamës së sistemit operativ ose direkt me harduerin. Realizimi i kësaj funksionaliteti me anë të modeleve të njohura të zgjidhjeve, si p.sh. do të nënkuptonte ndonjëherë ngarkesë shtesë, ndonjëherë - komplikim në operacione dhe skenarë të tjerë dështimi. Ne nuk dëshironim ta komplikonim këtë, prandaj vendosëm që përdorimi i Zbulimit të Shërbimeve të ishte opsional.
Në one-cloud, IP-ja i ndjek kontejnerin, domethënë çdo instancë e detyrës ka adresën e saj të vetme IP. Kjo adresë është "statike": ajo përfshihet për çdo instancë në momentin e parë të aktivizimit të shërbimit në cloud. Nëse gjatë jetës së shërbimit ka pasur një numër të ndryshëm instancash - atëherë në përfundim do të ketë aq shumë adresa IP sa instanca maksimale që kanë ekzistuar.
Pas kësaj, këto adresa nuk ndryshojnë: ato i janë caktuar një herë dhe vazhdojnë të ekzistojnë gjatë gjithë jetës së shërbimit në prodhim. Adresat IP i ndjekin kontejnerët përmes rrjetit. Nëse një kontejner transferohet në një minion tjetër, atëherë adresa do të kalojë gjithashtu pas tij.
KĂ«shtu, pĂ«rputhja e emrit tĂ« shĂ«rbimit me listĂ«n e adresave tĂ« tij IP ndryshon shumĂ« rrallĂ«. NĂ«se herĂ« tjetĂ«r shohim emrat e instancave tĂ« shĂ«rbimit, tĂ« cilat i pĂ«rmendĂ«m nĂ« fillim tĂ« artikullit (1.ok-web.group1.web.front.prod, 2.ok-web.group1.web.front.prod, âŠ), ne do tĂ« vĂ«rejmĂ« se ato i ngjajnĂ« FQDN-ve qĂ« pĂ«rdoren nĂ« DNS. KĂ«shtu, pĂ«r tĂ« shfaqur emrat e instancave tĂ« shĂ«rbimeve nĂ« IP-tĂ« e tyre, ne pĂ«rdorim protokollin DNS. NĂ« fakt, ky DNS kthen tĂ« gjitha adresat IP tĂ« rezervuara pĂ«r tĂ« gjithĂ« kontenierĂ«t â si ata qĂ« janĂ« nĂ« punĂ«, ashtu edhe tĂ« ndaluarit (pĂ«r shembull, nĂ«se pĂ«rdoren tri replika, ndĂ«rsa kemi pesĂ« adresa tĂ« rezervuara â tĂ« pesĂ« do tĂ« kthehen). KlientĂ«t, duke marrĂ« kĂ«tĂ« informacion, do tĂ« pĂ«rpiqen tĂ« lidhin me tĂ« pesĂ« replikat â dhe kĂ«shtu do tĂ« identifikojnĂ« ata qĂ« janĂ« nĂ« punĂ«. Ky variant i pĂ«rcaktimit tĂ« disponueshmĂ«risĂ« Ă«shtĂ« dukshĂ«m mĂ« i besueshĂ«m, pasi nuk angazhon as DNS-nĂ«, as Zbulimin e ShĂ«rbimeve, duke e bĂ«rĂ« kĂ«shtu tĂ« pamundur zgjidhjen e problemeve me ruajtjen e informacionit tĂ« saktĂ« dhe qĂ«ndrueshmĂ«rinĂ« e kĂ«tyre sistemeve. PĂ«r mĂ« tepĂ«r, nĂ« shĂ«rbime kritike, nga tĂ« cilat varet funksionimi i portalit tĂ«rĂ«, ne mund tĂ« mos pĂ«rdorim fare DNS-nĂ«, por thjesht tĂ« shkruajmĂ« adresat IP nĂ« konfigurim.
Implementimi i njĂ« transferimi tĂ« tillĂ« tĂ« IP-ve pas kontenierĂ«ve mund tĂ« jetĂ« jo trivial â dhe do tĂ« ndalemi nĂ« atĂ« se si funksionon, nĂ« shembullin e ardhshĂ«m:

Supozoni se master-i i one-cloud jep komandĂ«n minion-it M1 tĂ« niste 1.ok-web.group1.web.front.prod me adresĂ«n 1.1.1.1. NĂ« minion punon , i cili e njofton kĂ«tĂ« adresĂ« nĂ« serverat e veçantĂ« . KĂ«ta tĂ« fundit kanĂ« njĂ« seancĂ« BGP me paisjen rrjetĂ«, nĂ« tĂ« cilĂ«n transmetohet rruge e adresĂ«s 1.1.1.1 te M1. M1 pastaj rrugeton paketat brenda kontenierit duke pĂ«rdorur mjetet Linux. Ka tre serverĂ« route reflector, pasi kjo Ă«shtĂ« njĂ« pjesĂ« shumĂ« kritike e infrastrukturĂ«s one-cloud â pa to, rrjeti nĂ« one-cloud nuk do tĂ« funksionojĂ«. Ne i vendosim ato nĂ« raftĂ« tĂ« ndryshĂ«m, sa mĂ« shumĂ« qëështĂ« e mundur, nĂ« salla tĂ« ndryshme tĂ« qendrĂ«s sĂ« tĂ« dhĂ«nave, pĂ«r tĂ« minimizuar mundĂ«sinĂ« e dĂ«shtimit tĂ« njĂ«kohshĂ«m tĂ« tĂ« treve.
Tani le të supozojmë se lidhja midis master-it one-cloud dhe minion-it M1 ka humbur. Master-i one-cloud tani do të veprojë, duke u nisur nga supozimi se M1 ka dështuar plotësisht. Do të thotë se do të japë urdhrin minion-it M2 të niste web.group1.web.front.prod me të njëjtin adresë 1.1.1.1. Tani kemi dy rrugë konfliktuale në rrjet për 1.1.1.1: në M1 dhe në M2. Për të zgjidhur konflikte të tilla, ne përdorim Multi Exit Discriminator, i cili specifikohet në njoftimin BGP. Ky numër tregon peshën e rrugës së njoftuar. Nga konfliktualet do të zgjidhet rruga me vlerën më të vogël MED. Masteri one-cloud mbështet MED si një pjesë integrale e IP adresave të kontejnerëve. Në herën e parë adresa shpërndahet me një MED mjaft të madh = 1 000 000. Në situatën e një transferimi të tillë emergjent të kontejnerit, masteri e ul MED, dhe M2 tashmë do të marrë komandën të njoftojë adresën 1.1.1.1 me MED = 999 999. Ndërsa instanca që punon në M1 do të mbetet pa lidhje, dhe ardhmëria e saj na intereson pak derisa të rikthehet lidhja me masterin, kur do të ndalet si një kopje e vjetër.
Aksidentet
Të gjitha sistemet e menaxhimit të qendrave të të dhënave gjithmonë e përballojnë me sukses dështimet e vogla. Rënia e kontejnerit është një normë pothuajse në çdo vend.
Le të shqyrtojmë se si ne i përballojmë aksidentet, për shembull dështimin e energjisë në një ose më shumë sallat e qendrës së të dhënave.
ĂfarĂ« do tĂ« thotĂ« aksident pĂ«r sistemin e menaxhimit tĂ« qendrĂ«s sĂ« tĂ« dhĂ«nave? NĂ« radhĂ« tĂ« parĂ«, kjo Ă«shtĂ« njĂ« dĂ«shtim masiv dhe njĂ«kohĂ«sisht i shumĂ« makinave, dhe sistemi i menaxhimit duhet tĂ« migrojĂ« njĂ« numĂ«r tĂ« madh kontejnerĂ«sh njĂ«kohĂ«sisht. Por nĂ«se aksidenti Ă«shtĂ« shumĂ« i gjerĂ«, ndodh qĂ« tĂ« gjitha detyrat nuk mund tĂ« ricaktohen nĂ« minibotĂ« tĂ« tjerĂ«, sepse kapaciteti burimor i qendrĂ«s sĂ« tĂ« dhĂ«nave bie nĂ«n 100% tĂ« ngarkesĂ«s.
Shpesh aksidentet shoqërohen me dështimin e nivelit menaxhues. Kjo mund të ndodhë për shkak të dështimit të pajisjeve të tij, por më shpesh për shkak se aksidentet nuk testohet, dhe niveli menaxhues vetë bie nga ngarkesa e rritur.
ĂfarĂ« mund tĂ« bĂ«jmĂ« me tĂ« gjitha kĂ«to?
Migrazione masive nĂ«nkuptojnĂ« se nĂ« infrastrukturĂ« krijohet njĂ« numĂ«r i madh veprimesh, migracionesh dhe vendosjesh. Ădo migracion mund tĂ« marrĂ« njĂ«farĂ« kohe tĂ« nevojshme pĂ«r tĂ« dorĂ«zuar dhe paketa imazhet e kontejnerĂ«ve deri te minibotĂ«t, pĂ«r tĂ« nisur dhe inicializuar kontejnerĂ«t etj. Prandaj, Ă«shtĂ« e preferueshme qĂ« detyrat mĂ« tĂ« rĂ«ndĂ«sishme tĂ« nisin pĂ«rpara atyre mĂ« pak tĂ« rĂ«ndĂ«sishme.
Le të shohim përsëri hierarkinë e njohur të shërbimeve dhe të përpiqemi të vendosim se cilat detyra dëshirojmë të nisim fillimisht.

Sigurisht, kĂ«to janĂ« proceset qĂ« marrin pjesĂ« drejtpĂ«rdrejt nĂ« pĂ«rpunimin e kĂ«rkesave tĂ« pĂ«rdoruesve, pra, prod. Ne e specifikojmĂ« kĂ«tĂ« me prioritetin e vendosjes â njĂ« numĂ«r qĂ« mund t'i caktohet radhĂ«s. NĂ«se ndonjĂ« radhĂ« ka njĂ« prioritet mĂ« tĂ« lartĂ«, shĂ«rbimet e saj vendosen sĂ« pari.
NĂ« prod ne caktojmĂ« prioritetet mĂ« tĂ« larta, 0; nĂ« batch â pak mĂ« tĂ« ulĂ«ta, 100; nĂ« idle â akoma mĂ« tĂ« ulĂ«ta, 200. Prioritetet aplikohen nĂ« mĂ«nyrĂ« hierarkike. TĂ« gjitha detyrat nĂ«n hierarkinĂ« do tĂ« kenĂ« prioritetin pĂ«rkatĂ«s. NĂ«se duam qĂ« brenda prod caching tĂ« nisĂ« pĂ«rpara frontend-eve, atĂ«herĂ« caktojmĂ« prioritetet pĂ«r cache = 0 dhe pĂ«r frontin e nĂ«nradhĂ«s = 1. NĂ«se, pĂ«r shembull, duam qĂ« nga frontet tĂ« niset sĂ« pari portali kryesor, ndĂ«rsa fronti i muzikĂ«s mĂ« pas, mund t'i caktojmĂ« kĂ«tij tĂ« fundit njĂ« prioritet mĂ« tĂ« ulĂ«t â 10.
Problemi tjetër është mungesa e burimeve. Pra, na ka dështuar një numër i madh pajisjesh, të tëra sallat e qendrës së të dhënave, ndërsa kemi nisur kaq shumë shërbime saqë tani nuk ka burime të mjaftueshme për të gjithë. Duhet të vendosim se për cilat detyra do të sakrifikojmë që shërbimet kryesore kritike të funksionojnë.

Në dallim nga prioriteti i vendosjes, nuk mund të sakrifikojmë pa dallim të gjitha detyrat batch, disa prej të cilave janë të rëndësishme për funksionimin e portalit. Prandaj ne kemi ndarë veçmas prioritetin e dëbimit të detyrave. Kur vendoset, një detyrë me prioritet më të lartë mund të dëbojë, pra, të ndalë një detyrë me prioritet më të ulët, nëse nuk ka më minion të lirë. Në këtë rast, detyra me prioritet më të ulët, me shumë mundësi, do të mbetet e pa vendosur, pra, për të nuk do të ketë më minion të përshtatshëm me burime të mjaftueshme të lira.
Në hierarkinë tonë është shumë e thjeshtë të specifikohet një prioritet i tillë dëbimi, që detyrat e prod dhe batch të dëbojnë ose ndalin detyrat idle, por jo njëra-tjetrën, duke caktuar për idle një prioritet të barabartë me 200. Po ashtu si në rastin e prioritetit të vendosjes, mund të përdorim hierarkinë tonë për të përshkruar rregulla më të komplikuara. Për shembull, do të specifikojmë se për funksionin e muzikës do të sakrifikojmë nëse na mungojnë burimet për portalin kryesor të uebit, duke vendosur për nodet përkatëse prioritet më të ulët: 10.
Aksidentet e Qendrës së të Dhënave tërësisht
Pse mund tĂ« dĂ«shtojĂ« e gjithĂ« qendra e tĂ« dhĂ«nave? Natyror. Kishte njĂ« post tĂ« shkĂ«lqyer se si . Elementi i jashtĂ«m mund tĂ« pĂ«rfshijnĂ« ata qĂ« me njĂ« herĂ« nĂ« njĂ« kolektor dogjĂ«n fiber optikĂ« dhe qendra e tĂ« dhĂ«nave humbi plotĂ«sisht lidhjen me vendet e tjera. Shkaqet e daljes jashtĂ« funksionit ndodhin gjithashtu pĂ«r shkak tĂ« faktorĂ«ve njerĂ«zorĂ«: operatori mund tĂ« japĂ« njĂ« komandĂ« tĂ« tillĂ« qĂ« e bĂ«n tĂ«rĂ«sisht tĂ« pamundur qendrĂ«n e tĂ« dhĂ«nave. Kjo mund tĂ« ndodhĂ« pĂ«r shkak tĂ« njĂ« defekti tĂ« madh. NĂ« pĂ«rgjithĂ«si, qendrat e tĂ« dhĂ«nave bie â nuk Ă«shtĂ« njĂ« fenomen i zakontĂ«. Kjo ndodh njĂ« herĂ« nĂ« disa muaj.
Dhe ja se çfarë bëjmë që askush #okzhivi të mos postojë në Twitter.
Strategjia e parĂ« Ă«shtĂ« izolimi. Ădo instancĂ« e one-cloud Ă«shtĂ« e izoluar dhe mund tĂ« menaxhojĂ« makinat vetĂ«m e njĂ« qendĂ«r tĂ« dhĂ«nash. Pra, humbja e njĂ« reje pĂ«r shkak tĂ« defekteve ose komandave tĂ« gabuara tĂ« operatorit â Ă«shtĂ« humbje vetĂ«m e njĂ« qendĂ«r tĂ« dhĂ«nash. Jemi tĂ« pĂ«rgatitur pĂ«r kĂ«tĂ«: ekziston njĂ« politikĂ« rezervimi, ku replika e aplikacionit dhe tĂ« dhĂ«nave vendosen nĂ« tĂ« gjitha qendrat e tĂ« dhĂ«nave. Ne pĂ«rdorim baza tĂ« tĂ« dhĂ«nave tĂ« qĂ«ndrueshme dhe rregullisht testojmĂ« dĂ«shtimet.
Duke patur parasysh se sot kemi katër qendra të të dhënash, ka edhe katër eksperimentale të plota dhe të izoluar të one-cloud.
Ky qasje jo vetëm që mbron nga dështimet fizike, por gjithashtu mund të mbrojë nga gabimet e operatorit.
ĂfarĂ« mund tĂ« bĂ«jmĂ« pĂ«r faktorĂ«t njerĂ«zorĂ«? Kur operatori i jep re njĂ« komandĂ« tĂ« çuditshme ose potencialisht tĂ« rrezikshme, ai mund tĂ« kĂ«rkohet papritur tĂ« zgjidhĂ« njĂ« problem tĂ« vogĂ«l pĂ«r tĂ« verifikuar se sa mirĂ« ka menduar. PĂ«r shembull, nĂ«se Ă«shtĂ« njĂ« ndalje masive e shumĂ« replikave ose thjesht njĂ« komandĂ« e çuditshme â reduktimi i numrit tĂ« replikave ose ndryshimi i emrit tĂ« imazhit, jo vetĂ«m numri i versionit nĂ« manifestin e ri.
Përfundime
Karakteristikat dalluese të one-cloud:
- Një skemë hierarkike dhe vizuale e emrave të shërbimeve dhe kontejnerëve, e cila lejon shumë shpejt të kuptoni se çfarë është kjo detyrë, për çfarë i takon dhe si punon dhe kush është përgjegjës për të.
- Ne përdorim teknikën tonë të bashkimit të detyrave prod- dhe batch-në minj, për të rritur efikasitetin e ndarjes së makinave. Në vend të cpuset përdorim quota të CPU, aksione, politika të planifikuesit të CPU dhe Linux QoS.
- Nuk arritëm të izolojmë plotësisht kontejnerët që punojnë në një makinë, por ndikimi i tyre mbetet brenda 20%.
- Organizimi i shërbimeve në një hierarki ndihmon në eliminimin automatik të emergjencave përmes prioriteteve të vendosjes dhe zëvendësimit..
FAQ
Pse nuk morëm një zgjidhje të gatshme.
- Klasat e ndryshme të izolimit të detyrave kërkojnë logjikë të ndryshme gjatë vendosjes në mini. Ndërsa detyrat prodhuese mund të vendosen me rezervimin e thjeshtë të burimeve, detyrat batch dhe idle duhet të vendosen duke ndjekur shfrytëzimin e vërtetë të burimeve në makinat mini.
- Nevoja për të marrë parasysh burimet e konsumuar nga detyrat, siç janë:
- kapaciteti i rrjetit;
- tipet dhe "spindlet" e disqeve.
- Nevoja për të specifikuar prioritetet e shërbimeve gjatë largimit të aksidenteve, të drejtat dhe kuotat e ekipeve për burimet, që arrihet përmes radhëve hierarkike në one-cloud.
- Nevoja për të pasur emra njerëzorë për kontejnerët për të reduktuar kohën e reagimit ndaj aksidenteve dhe incidenteve.
- Pamundësia për të zbatuar njëkohësisht në mënyrë universale Zbulimin e Shërbimeve; nevoja për të bashkëjetuar për një kohë të gjatë me detyrat e vendosura në hostët harduerikë, e cila zgjidhet me adresat IP "statike", që ndjekin kontejnerët, dhe si pasojë, nevoja për një integrim unik me infrastrukturën e gjerë rrjetore.
Të gjitha këto funksione do të kërkonin rikonstruksione të thella të zgjidhjeve ekzistuese dhe, duke vlerësuar sasinë e punës, ne kuptuam se mund të zhvillonim një zgjidhje tonën me të njëjtat shpenzime pune. Por zgjidhja jonë do të ishte ndjeshëm më e lehtë për t'u eksploruar dhe zhvilluar - nuk ka abstraksione të panevojshme që mbështesin funksionalitetin e panevojshëm për ne.
Atyre që lexojnë rreshtat e fundit - faleminderit për qëndrueshmërinë dhe vëmendjen!
Burimi: habr.com
