Varastada: kes varastab virtuaalmasinatest protsessori aega

Varastada: kes varastab virtuaalmasinatest protsessori aega

Tere! Ma tahan teile lihtsate sõnadega rääkida virtuaalmasinate sees varastamise mehhanismidest ja mõningatest ebaselgetest artefaktidest, mis meil õnnestus selle uurimise käigus välja selgitada ja millesse mul tuli pilveplatvormi tehnilise direktorina sukelduda. Mail.ru pilvelahendused. Platvorm töötab KVM-is.

CPU varastamise aeg on aeg, mille jooksul virtuaalmasin ei saa oma täitmiseks protsessori ressursse. Seda aega arvestatakse ainult virtualiseerimiskeskkondade külalisoperatsioonisüsteemides. Põhjused, kuhu need enim eraldatud vahendid lähevad, nagu elus, on väga ebamäärased. Kuid otsustasime selle välja mõelda ja tegime isegi mitmeid katseid. Asi pole selles, et me nüüd varastamise kohta kõike teame, kuid me räägime teile nüüd midagi huvitavat.

1. Mis on varastamine

Seega on varastamine mõõdik, mis näitab protsessori ajapuudust virtuaalmasinas toimuvate protsesside jaoks. Nagu kirjeldatud KVM-i kerneli paigasStealth on aeg, mille jooksul hüperviisor käivitab host OS-is muid protsesse, kuigi ta on seadnud virtuaalmasina protsessi täitmiseks järjekorda. See tähendab, et varastamine arvutatakse kui erinevus aja vahel, mil protsess on täitmiseks valmis, ja aja vahel, mil protsessile on eraldatud protsessori aeg.

Virtuaalmasina tuum saab hüperviisorilt varastamise mõõdiku. Samal ajal ei täpsusta hüperviisor täpselt, milliseid protsesse see töötab, vaid ütleb lihtsalt "kuni ma olen hõivatud, ei saa ma teile aega anda." KVM-is on lisatud varastamise arvutamise tugi plaastrid. Siin on kaks põhipunkti:

  • Virtuaalmasin õpib varastamist hüperviisorilt. See tähendab, et kadude seisukohast on virtuaalmasinas endas olevate protsesside puhul tegemist kaudse mõõtmisega, mis võib olla erinevate moonutuste all.
  • Hüpervisor ei jaga virtuaalmasinaga infot selle kohta, millega ta veel tegeleb – peaasi, et ta sellele aega ei pühendaks. Seetõttu ei suuda virtuaalmasin ise tuvastada varastamise indikaatori moonutusi, mida saab hinnata konkureerivate protsesside olemuse järgi.

2. Mis mõjutab vargust

2.1. Varastada arvutus

Põhimõtteliselt arvutatakse varastamine ligikaudu sama palju kui tavaline protsessori kasutusaeg. Selle kohta, kuidas ringlussevõttu arvestatakse, pole palju teavet. Ilmselt seetõttu, et enamik inimesi peab seda küsimust ilmseks. Kuid siin on ka lõkse. Selle protsessiga tutvumiseks võite lugeda Brendan Greggi artikkel: saate teada palju nüansse kasutamise arvutamisel ja olukordadest, kus see arvutus on ekslik järgmistel põhjustel:

  • Protsessor kuumeneb üle, põhjustades tsüklite vahelejätmist.
  • Luba/keela turbovõimendus, mis muudab protsessori taktsagedust.
  • Ajalõigu pikkuse muutus, mis ilmneb protsessori energiasäästutehnoloogiate (nt SpeedStep) kasutamisel.
  • Keskmise arvutamise probleem: ühe minuti kasutuse prognoosimine 80%-ni võib varjata lühiajalist 100%-list tõusu.
  • Pöörlemislukk põhjustab protsessori taaskasutamise, kuid kasutajaprotsess ei näe selle täitmisel mingit edenemist. Selle tulemusena on protsessori arvutuslik kasutamine protsessis sada protsenti, kuigi protsess ei võta füüsiliselt protsessori aega.

Ma ei leidnud artiklit, mis kirjeldaks sarnast varguse arvutust (kui teate, jagage seda kommentaarides). Kuid lähtekoodi järgi otsustades on arvutusmehhanism sama, mis ringlussevõtu puhul. Kernelisse lisatakse lihtsalt teine ​​loendur, otse KVM-protsessi jaoks (virtuaalmasina protsess), mis loendab protsessori aega ootava KVM-protsessi kestuse. Loendur võtab protsessori kohta teavet selle spetsifikatsioonidest ja kontrollib, kas virtuaalmasina protsess kasutab kõiki selle linnukesi. Kui see on kõik, siis eeldame, et protsessor oli hõivatud ainult virtuaalse masina protsessiga. Vastasel juhul anname teada, et protsessor tegi midagi muud, ilmus vargus.

Varaste loendamise protsessiga kaasnevad samad probleemid, mis tavalise ringlussevõtu loendamisega. Mitte öelda, et sellised probleemid tekivad sageli, kuid need tunduvad heidutavad.

2.2. KVM-i virtualiseerimise tüübid

Laias laastus on kolme tüüpi virtualiseerimist, mida kõiki toetab KVM. Varastamise mehhanism võib sõltuda virtualiseerimise tüübist.

Ringhääling. Sel juhul toimib virtuaalmasina operatsioonisüsteem füüsiliste hüperviisoriseadmetega umbes järgmiselt:

  1. Külalisoperatsioonisüsteem saadab oma külalisseadmele käsu.
  2. Külalisseadme draiver saab käsu, genereerib päringu seadme BIOS-i jaoks ja saadab selle hüperviisorile.
  3. Hüpervisori protsess tõlgib füüsilise seadme käsuks, muutes selle muu hulgas turvalisemaks.
  4. Füüsiline seadme draiver aktsepteerib muudetud käsu ja saadab selle füüsilisele seadmele endale.
  5. Käskude täitmise tulemused lähevad tagasi sama rada pidi.

Tõlke eeliseks on see, et see võimaldab teil emuleerida mis tahes seadet ega vaja operatsioonisüsteemi tuuma spetsiaalset ettevalmistamist. Kuid selle eest tuleb maksta ennekõike kiirusega.

Riistvara virtualiseerimine. Sel juhul mõistab riistvarataseme seade operatsioonisüsteemi käske. See on kiireim ja parim viis. Kuid kahjuks ei toeta seda kõik füüsilised seadmed, hüperviisorid ja külaliste operatsioonisüsteemid. Praegu on peamised riistvara virtualiseerimist toetavad seadmed protsessorid.

Paravirtualiseerimine. Kõige tavalisem võimalus seadmete virtualiseerimiseks KVM-is ja üldiselt kõige levinum virtualiseerimisrežiim külaliste operatsioonisüsteemide jaoks. Selle eripära on see, et töö mõne hüperviisori alamsüsteemiga (näiteks võrgu- või kettapinuga) või mälulehtede eraldamine toimub hüperviisori API abil, ilma madala taseme käske tõlkimata. Selle virtualiseerimismeetodi puuduseks on see, et külalisoperatsioonisüsteemi kernelit tuleb muuta nii, et see saaks suhelda hüperviisoriga selle API abil. Kuid see lahendatakse tavaliselt spetsiaalsete draiverite installimisega külalisoperatsioonisüsteemi. KVM-is nimetatakse seda API-d virtio API.

Paravirtualiseerimisega võrreldes leviedastusega väheneb füüsilise seadmeni jõudmine oluliselt, kui virtuaalmasinast saadetakse käsklused otse hosti hüperviisori protsessi. See võimaldab kiirendada kõigi virtuaalmasina sees olevate juhiste täitmist. KVM-is teeb seda virtio API, mis töötab ainult teatud seadmete, näiteks võrgu- või kettaadapteri puhul. Seetõttu installitakse virtio draiverid virtuaalmasinatesse.

Selle kiirenduse negatiivne külg on see, et kõik virtuaalmasina sees töötavad protsessid ei jää selle sisse. See loob mõned eriefektid, mille tulemuseks võib olla varastamine. Soovitan alustada selle probleemi üksikasjalikku uurimist API virtuaalse I/O jaoks: virtio.

2.3. "Õiglane" ajakava

Hüperviisori virtuaalmasin on tegelikult tavaline protsess, mis järgib Linuxi tuumas ajastamise (ressursside jaotamise protsesside vahel) seadusi, seega vaatame seda lähemalt.

Linux kasutab niinimetatud CFS-i, Completely Fair Scheduleri, millest on saanud vaikeplaneerija alates kerneli versioonist 2.6.23. Selle algoritmi mõistmiseks võite lugeda Linuxi tuumaarhitektuuri või lähtekoodi. CFS-i olemus on protsessori aja jaotamine protsesside vahel sõltuvalt nende täitmise kestusest. Mida rohkem protsessoriaega protsess nõuab, seda vähem protsessoriaega see saab. See tagab, et kõik protsessid täidetakse "õiglaselt" – nii et üks protsess ei hõivaks pidevalt kõiki protsessoreid ja ka teised protsessid saaksid käivituda.

Mõnikord toob see paradigma kaasa huvitavaid esemeid. Tõenäoliselt mäletavad kauaaegsed Linuxi kasutajad tavalise tekstiredaktori külmumist töölaual ressursimahukate rakenduste (nt kompilaatori) töötamise ajal. See juhtus seetõttu, et töölauarakenduste mitteressursimahukad ülesanded konkureerisid ressursimahukate ülesannetega, näiteks kompilaatoriga. CFS arvab, et see on ebaõiglane, seetõttu peatab see perioodiliselt tekstiredaktori ja laseb protsessoril kompilaatori ülesandeid täita. See parandati mehhanismi abil sched_autogroup, kuid paljud muud funktsioonid protsessori aja jaotusest ülesannete vahel jäid alles. Tegelikult pole see lugu sellest, kui halvasti kõik CFS-is on, vaid katse juhtida tähelepanu tõsiasjale, et protsessori aja “õiglane” jaotus pole just kõige triviaalsem ülesanne.

Teine oluline punkt ajakavas on eelisostu. See on vajalik selleks, et protsessorist naerutamisprotsess välja lüüa ja teistel tööle lasta. Väljutusprotsessi nimetatakse konteksti vahetamiseks. Sel juhul säilib kogu ülesande kontekst: pinu, registrite jne olek, misjärel saadetakse protsess ootama ja selle asemele tuleb teine. See on OS-i jaoks kallis toiming ja seda kasutatakse harva, kuid sellel pole oma olemuselt midagi halba. Sage konteksti vahetamine võib viidata OS-i probleemile, kuid tavaliselt on see pidev ega näita midagi konkreetset.

Nii pikka juttu on vaja ühe fakti selgitamiseks: mida rohkem protsessoriressursse ausas Linuxi planeerijas protsess kulutada püüab, seda kiiremini see peatatakse, et ka teised protsessid saaksid töötada. Kas see on õige või mitte, on keeruline küsimus, mida saab erinevate koormuste korral erinevalt lahendada. Windowsis keskendus plaanija kuni viimase ajani töölauarakenduste prioriteetsele töötlemisele, mis võib põhjustada taustaprotsesside külmumist. Sun Solarisel oli viis erinevat ajakavade klassi. Kui käivitasime virtualiseerimise, lisasime kuuenda, Õiglase jagamise ajakava, sest eelmised viis ei töötanud Solarise tsoonide virtualiseerimisega piisavalt. Soovitan alustada selle probleemi üksikasjalikku uurimist selliste raamatutega nagu Solarise sisemised: Solaris 10 ja OpenSolaris Kernel Architecture või Linuxi tuuma mõistmine.

2.4. Kuidas vargusi jälgida?

Varguse jälgimine virtuaalmasinas, nagu iga muu protsessori mõõdik, on lihtne: saate kasutada mis tahes protsessori mõõdikute tööriista. Peaasi, et virtuaalmasin oleks Linuxis. Millegipärast ei anna Windows seda teavet oma kasutajatele. 🙁

Varastada: kes varastab virtuaalmasinatest protsessori aega
Ülemise käsu väljund: protsessori koormuse üksikasjad, kõige parempoolses veerus - varastada

Raskus tekib siis, kui proovite seda teavet hüperviisorilt hankida. Võite proovida varastada hostmasinas näiteks parameetri Load Average (LA) abil – täitmisjärjekorras ootavate protsesside arvu keskmist väärtust. Selle parameetri arvutamise meetod ei ole lihtne, kuid üldiselt, kui protsessori lõimede arvuga normaliseeritud LA on suurem kui 1, näitab see, et Linuxi server on millegagi üle koormatud.

Mida kõik need protsessid ootavad? Ilmselge vastus on protsessor. Kuid vastus pole täiesti õige, sest mõnikord on protsessor vaba, kuid LA läheb skaalalt välja. Pea meeles kuidas NFS kukub ja kuidas LA kasvab. Sama võib juhtuda ketta ja muude sisend-/väljundseadmetega. Kuid tegelikult võivad protsessid oodata mis tahes luku lõppu, olgu see siis füüsiline, mis on seotud I/O seadmega, või loogiline, näiteks mutex. See hõlmab ka lukustamist riistvara tasemel (sama vastus kettalt) või loogika (nn lukustusprimitiivid, mis sisaldab hunnikut olemeid, mutex adaptiiv- ja spin, semafoore, tingimusmuutujaid, rw lukke, ipc lukke ...).

LA veel üks omadus on see, et seda peetakse operatsioonisüsteemi keskmiseks. Näiteks 100 protsessi võistlevad ühe faili pärast ja siis LA=50. Nii suur väärtus viitab ilmselt sellele, et operatsioonisüsteem on halb. Kuid muu viltu kirjutatud koodi puhul võib see olla normaalne olek, hoolimata sellest, et ainult see on halb ja muud operatsioonisüsteemi protsessid ei kannata.

Selle keskmistamise tõttu (ja mitte vähem kui minutiga) ei ole LA-indikaatori järgi millegi määramine kõige tasuvam ülesanne, konkreetsetel juhtudel on tulemused väga ebakindlad. Kui proovite seda välja mõelda, leiate, et Vikipeedia artiklid ja muud saadaolevad allikad kirjeldavad ainult kõige lihtsamaid juhtumeid, ilma protsessi põhjaliku selgituseta. Saadan kõigile huvilistele taas siia Brendan Greggile  - järgige allolevaid linke. Kes on liiga laisk, et inglise keelt rääkida - tema populaarse artikli tõlge LA kohta.

3. Eriefektid

Vaatame nüüd peamisi vargusjuhtumeid, millega me kokku puutusime. Ma ütlen teile, kuidas need tulenevad kõigest ülaltoodust ja kuidas need on seotud hüperviisori näitajatega.

Taaskasutus. Lihtsaim ja levinum: hüperviisorit on taaskasutatud. Tõepoolest, töötavaid virtuaalmasinaid on palju, nende sees on suur protsessori tarbimine, suur konkurents, LA kasutus on üle 1 (protsessori lõimede järgi normaliseeritud). Kõikide virtuaalmasinate sees aeglustub. Kasvab ka hüperviisorist edastatud varastamine, vaja on koormust ümber jaotada või keegi välja lülitada. Üldiselt on kõik loogiline ja arusaadav.

Paravirtualiseerimine vs üksikjuhtumid. Hüperviisoril on ainult üks virtuaalmasin, see tarbib sellest väikese osa, kuid tekitab suure I/O koormuse, näiteks kettale. Ja kuskilt ilmub sinna väike vargus, kuni 10% (nagu on näidanud mitmed katsed).

Juhtum on huvitav. Steal ilmub siin just paravirtualiseeritud draiverite tasemel blokeerimise tõttu. Virtuaalses masinas luuakse katkestus, mida draiver töötleb ja saadetakse hüperviisorile. Hüpervisori katkestuste käsitlemise tõttu näeb virtuaalmasina jaoks välja nagu saadetud päring, see on täitmiseks valmis ja ootab protsessorit, kuid sellele ei anta protsessori aega. Virtuaaltüdruk arvab, et see aeg on varastatud.

See juhtub puhvri saatmise hetkel, see läheb hüperviisori tuumaruumi ja hakkame seda ootama. Kuigi virtuaalmasina seisukohalt peaks ta kohe tagasi pöörduma. Seetõttu loetakse see aeg varastatud arvutusalgoritmi järgi varastatuks. Tõenäoliselt võib selles olukorras olla muid mehhanisme (näiteks mõne teise süsteemikõne töötlemine), kuid need ei tohiks palju erineda.

Planeerija versus kõrgelt koormatud virtuaalmasinad. Kui üks virtuaalmasin kannatab varastamise all rohkem kui teised, on selle põhjuseks planeerija. Mida rohkem protsess protsessorit koormab, seda varem ajakava koostaja selle välja lööb, et ka teised saaksid töötada. Kui virtuaalmasin tarbib vähe, siis vaevalt ta vargust ei näe: selle protsess ausalt istus ja ootas, peame sellele rohkem aega andma. Kui virtuaalmasin toodab maksimaalset koormust kõigile oma tuumadele, lüüakse see sageli protsessorist välja ja sellele püütakse mitte palju aega anda.

Veelgi hullem on see, kui virtuaalmasina sees olevad protsessid proovivad hankida rohkem protsessorit, kuna nad ei saa andmetöötlusega hakkama. Siis pakub hüperviisori operatsioonisüsteem ausa optimeerimise tõttu üha vähem protsessori aega. See protsess toimub nagu laviin ja varastamine hüppab taevasse, kuigi teised virtuaalmasinad ei pruugi seda peaaegu märgata. Ja mida rohkem südamikke, seda halvem on mõjutatud masin. Lühidalt öeldes kannatavad kõige rohkem kõrgelt koormatud ja paljude tuumadega virtuaalmasinad.

Madal LA, kuid seal on varastada. Kui LA on ligikaudu 0,7 (see tähendab, et hüperviisor näib olevat alakoormatud), kuid üksikutes virtuaalmasinates täheldatakse vargust:

  • Eespool juba kirjeldatud paravirtualiseerimisega variant. Virtuaalmasin võib vastu võtta varguse näitajaid, kuigi hüperviisor on korras. Meie katsete tulemuste kohaselt ei ületa see varastamisvõimalus 10% ja see ei tohiks virtuaalses masinas rakenduste jõudlust oluliselt mõjutada.
  • LA parameeter on valesti arvutatud. Täpsemalt, igal konkreetsel hetkel arvutatakse see õigesti, kuid ühe minuti keskmisena osutub see alahinnatuks. Näiteks kui üks virtuaalmasin hüperviisori kolmandiku kohta tarbib kõiki oma protsessoreid täpselt pool minutit, siis on LA minutis hüperviisoril 0,15; neli sellist virtuaalmasinat samaaegselt töötavad annavad 0,6. Ja seda, et kummalgi pool minutit oli LA indikaatori järgi 25% metsik varastamine, ei saa enam välja tõmmata.
  • Jällegi ajakava koostaja pärast, kes otsustas, et keegi sööb liiga palju ja lasi sellel kellelgi oodata. Vahepeal vahetan konteksti, käsitlen katkestusi ja hoolitsen muude oluliste süsteemiasjade eest. Selle tulemusena ei näe mõned virtuaalsed masinad mingeid probleeme, samas kui teised kogevad jõudluse tõsist halvenemist.

4. Muud moonutused

Virtuaalses masinas protsessori aja õiglase tasuvuse moonutamiseks on veel miljon põhjust. Näiteks tekitavad hüperlõime ja NUMA arvutusi raskusi. Need ajavad protsessi täitmiseks kerneli valiku täiesti segadusse, kuna planeerija kasutab koefitsiente – kaalusid, mis muudavad arvutamise konteksti vahetamisel veelgi keerulisemaks.

Moonutused on tingitud sellistest tehnoloogiatest nagu turbo boost või vastupidi, energiasäästurežiim, mis võib kasutuse arvutamisel kunstlikult suurendada või vähendada sagedust või isegi ajalõiku serveris. Turbo võimenduse lubamine vähendab ühe protsessori lõime jõudlust teise protsessori jõudluse suurenemise tõttu. Praegusel hetkel ei edastata virtuaalmasinale infot protsessori hetkesageduse kohta ja see usub, et keegi varastab selle aega (näiteks küsis sagedust 2 GHz, aga sai poole sellest).

Üldiselt võib moonutustel olla palju põhjuseid. Konkreetsest süsteemist võite leida midagi muud. Parem on alustada raamatutest, mille lingid ülal andsin, ja statistika hankimisest hüperviisorist selliste utiliitide abil nagu perf, sysdig, systemtap, millest kümneid.

5. Järeldused

  1. Paravirtualiseerimise tõttu võib esineda mõningane vargus ja seda võib pidada normaalseks. Nad kirjutavad Internetis, et see väärtus võib olla 5-10%. Sõltub virtuaalses masinas olevatest rakendustest ja koormusest, mida see oma füüsilistele seadmetele annab. Siin on oluline pöörata tähelepanu sellele, kuidas rakendused virtuaalmasinates tunnevad.
  2. Hüpervisori koormuse ja virtuaalmasina varastamise suhe ei ole alati omavahel selgelt seotud; mõlemad varastamise hinnangud võivad konkreetsetes olukordades erinevatel koormustel olla ekslikud.
  3. Planeerija suhtub halvasti protsessidesse, mis küsivad palju. Ta püüab anda vähem neile, kes rohkem küsivad. Suured virtuaalmasinad on kurjad.
  4. Väike varastamine võib olla norm ka ilma paravirtualiseerimiseta (võttes arvesse virtuaalmasina sisemist koormust, naabrite koormuse omadusi, koormuse jaotust lõimede vahel ja muid tegureid).
  5. Kui tahad konkreetses süsteemis varguse selgeks teha, tuleb uurida erinevaid võimalusi, koguda mõõdikuid, neid hoolikalt analüüsida ja mõelda, kuidas koormust ühtlaselt jaotada. Kõikidest juhtumitest on võimalikud kõrvalekalded, mida tuleb katseliselt kinnitada või vaadata kerneli siluris.

Allikas: www.habr.com

Lisa kommentaar