Lop: ki lopja a CPU-időt a virtuális gépekről

Lop: ki lopja a CPU-időt a virtuális gépekről

Helló! Egyszerűen szeretném elmondani a virtuális gépeken belüli lopás mechanikájáról és néhány nem nyilvánvaló műtermékről, amelyeket a kutatás során sikerült kiderítenünk, és amelyekbe egy felhőplatform műszaki igazgatójaként kellett belemerülnöm. Mail.ru Cloud Solutions. A platform KVM-en fut.

A CPU ellopási ideje az az idő, amely alatt a virtuális gép nem kap processzorerőforrásokat a végrehajtásához. Ezt az időt csak a virtualizációs környezetekben lévő vendég operációs rendszerekben számolják. Az okok, hogy hová kerülnek ezek a legtöbb forrásból, mint az életben, nagyon homályosak. De úgy döntöttünk, hogy kitaláljuk, és még számos kísérletet is végrehajtottunk. Nem arról van szó, hogy most már mindent tudunk a lopásról, de most elárulunk valami érdekeset.

1. Mi a lopás

Tehát a lopás egy olyan mérőszám, amely a processzoridő hiányát jelzi a virtuális gépen belüli folyamatokhoz. A leírás alapján a KVM kernel javításábanA lopakodó az az idő, amely alatt a hypervisor más folyamatokat hajt végre a gazdagép operációs rendszeren, még akkor is, ha sorba állította a virtuális gép folyamatát a végrehajtáshoz. Ez azt jelenti, hogy a lopást a folyamat végrehajtására készenléti idő és a processzoridő lefoglalása közötti különbségként számítják ki.

A virtuális gép kernelje megkapja a lopási metrikát a hypervisortól. Ugyanakkor a hypervisor nem határozza meg pontosan, hogy milyen más folyamatokat futtat, egyszerűen azt mondja: „amíg el vagyok foglalva, nem tudok időt adni”. A KVM-en a lopás számítás támogatása hozzáadásra került foltok. Itt két kulcsfontosságú pont van:

  • A virtuális gép megtanulja a lopást a hypervisortól. Vagyis a veszteségek szempontjából magán a virtuális gépen lévő folyamatok számára ez egy közvetett mérés, amely különféle torzításoknak lehet kitéve.
  • A hypervisor nem oszt meg információkat a virtuális géppel arról, hogy mit csinál még – a lényeg az, hogy ne szánjon rá időt. Emiatt maga a virtuális gép nem képes észlelni a lopásjelzőben lévő torzulásokat, amelyek a versengő folyamatok jellege alapján értékelhetőek.

2. Mi befolyásolja a lopást

2.1. Lop számítás

Lényegében a lopás számítása megközelítőleg megegyezik a normál CPU kihasználtsági idővel. Nem sok információ áll rendelkezésre arról, hogy az újrahasznosítást hogyan kell figyelembe venni. Valószínűleg azért, mert a legtöbb ember ezt a kérdést nyilvánvalónak tartja. De itt is vannak buktatók. A folyamat megismeréséhez olvassa el Brendan Gregg cikke: sok árnyalatot fog megtudni a kihasználtság kiszámításakor, és olyan helyzetekről, amikor ez a számítás a következő okok miatt hibás lesz:

  • A processzor túlmelegszik, ami a ciklusok kihagyását okozza.
  • Engedélyezze/letiltja a turbóerősítést, amely megváltoztatja a processzor órajelét.
  • Az időszelet hosszának változása a processzor energiatakarékos technológiáinak, például a SpeedStepnek a használatakor.
  • A probléma az átlag kiszámításával: az egyperces kihasználtság 80%-ra becsülése rövid távú 100%-os kitörést rejthet.
  • A centrifugálás zárolása a processzor visszanyerését eredményezi, de a felhasználói folyamat nem lát előrehaladást a végrehajtásában. Ennek eredményeként a processzor számított kihasználtsága száz százalékos lesz, bár a folyamat fizikailag nem fogyaszt processzoridőt.

Nem találtam olyan cikket, amely leírna hasonló számítást a lopásra (ha tudod, oszd meg a megjegyzésekben). De a forráskódból ítélve a számítási mechanizmus ugyanaz, mint az újrahasznosításnál. Egyszerűen egy másik számláló kerül a kernelbe, közvetlenül a KVM folyamathoz (virtuális gépi folyamat), amely számolja a KVM folyamat CPU idejére váró időtartamát. A számláló információt vesz a processzorról a specifikációjából, és ellenőrzi, hogy a virtuális gép folyamata felhasználja-e az összes tickjét. Ha ez minden, akkor feltételezzük, hogy a processzort csak a virtuális gép folyamata foglalta el. Ellenkező esetben közöljük, hogy a processzor mást csinált, lopás jelent meg.

A lopás számlálási folyamata ugyanazoknak a problémáknak van kitéve, mint a szokásos újrahasznosítási számlálás. Nem azt mondom, hogy az ilyen problémák gyakran megjelennek, de elkeserítőnek tűnnek.

2.2. A virtualizáció típusai a KVM-en

Általánosságban elmondható, hogy háromféle virtualizáció létezik, amelyek mindegyikét támogatja a KVM. A lopás előfordulásának mechanizmusa a virtualizáció típusától függhet.

Adás. Ebben az esetben a virtuális gép operációs rendszerének működése fizikai hipervizor eszközökkel a következőképpen történik:

  1. A vendég operációs rendszer parancsot küld vendégeszközének.
  2. A vendégeszköz-illesztőprogram megkapja a parancsot, kérést generál az eszköz BIOS-ához, és elküldi a hipervizornak.
  3. A hypervisor folyamat a parancsot parancsra fordítja a fizikai eszköz számára, így többek között biztonságosabb.
  4. A fizikai eszközillesztő elfogadja a módosított parancsot, és elküldi magának a fizikai eszköznek.
  5. A parancsok végrehajtásának eredménye ugyanazon az úton megy vissza.

A fordítás előnye, hogy lehetővé teszi bármilyen eszköz emulálását, és nincs szükség az operációs rendszer kernelének speciális előkészítésére. De ezért elsősorban gyorsasággal kell fizetni.

Hardveres virtualizáció. Ebben az esetben az eszköz hardver szinten megérti az operációs rendszer parancsait. Ez a leggyorsabb és legjobb módszer. Sajnos azonban nem minden fizikai eszköz, hipervizor és vendég operációs rendszer támogatja. Jelenleg a hardveres virtualizációt támogató fő eszközök a processzorok.

Paravirtualizáció. Az eszközvirtualizáció leggyakoribb lehetősége KVM-en, és általában a vendég operációs rendszerek leggyakoribb virtualizációs módja. Sajátossága, hogy egyes hypervisor alrendszerekkel (például hálózattal vagy lemezveremekkel) való munkavégzés vagy a memórialapok lefoglalása a hypervisor API használatával történik, alacsony szintű parancsok fordítása nélkül. Ennek a virtualizációs módszernek az a hátránya, hogy a vendég operációs rendszer kernelt módosítani kell, hogy ezen az API-n keresztül tudjon kommunikálni a hypervisorral. De ezt általában úgy oldják meg, hogy speciális illesztőprogramokat telepítenek a vendég operációs rendszerre. A KVM-ben ezt az API-t hívják virtio API.

A paravirtualizációnál a szóráshoz képest a fizikai eszköz elérési útja jelentősen lecsökken azáltal, hogy a parancsokat közvetlenül a virtuális gépről küldik a gazdagép hipervizor folyamatába. Ez lehetővé teszi az összes utasítás végrehajtásának felgyorsítását a virtuális gépen belül. A KVM-ben ezt a virtio API végzi, amely csak bizonyos eszközökön, például hálózati vagy lemezadapteren működik. Ez az oka annak, hogy a virtio illesztőprogramokat a virtuális gépeken belül telepítik.

Ennek a gyorsításnak az a hátránya, hogy nem minden, a virtuális gépen belül futó folyamat marad meg benne. Ez olyan speciális effektusokat hoz létre, amelyek lopáskor kialakulhatnak. Azt javaslom, hogy kezdje el a probléma részletes tanulmányozását Egy API virtuális I/O-hoz: virtio.

2.3. "Tisztességes" ütemezés

A hypervisoron lévő virtuális gép valójában egy közönséges folyamat, amely betartja az ütemezés (a folyamatok közötti erőforrás-elosztás) törvényeit a Linux kernelben, ezért nézzük meg közelebbről.

A Linux az úgynevezett CFS-t, a Completely Fair Scheduler-t használja, amely a 2.6.23-as kernel óta az alapértelmezett ütemező. Az algoritmus megértéséhez elolvashatja a Linux kernel architektúráját vagy a forráskódot. A CFS lényege, hogy a processzoridőt elosztja a folyamatok között a végrehajtásuk időtartamától függően. Minél több CPU-időt igényel egy folyamat, annál kevesebb CPU-időt kap. Ez biztosítja, hogy minden folyamat "tisztességesen" lehessen végrehajtani – így egy folyamat nem foglalja le folyamatosan az összes processzort, és más folyamatok is végrehajthatók.

Néha ez a paradigma érdekes műtermékekhez vezet. A régebbi Linux-felhasználók valószínűleg emlékeznek arra, hogy egy hagyományos szövegszerkesztő lefagyott az asztalon, miközben erőforrás-igényes alkalmazásokat, például fordítót futtatnak. Ez azért történt, mert az asztali alkalmazások nem erőforrás-igényes feladatai versenyeztek az erőforrás-igényes feladatokkal, például a fordítóval. A CFS ezt igazságtalannak tartja, ezért időnként leállítja a szövegszerkesztőt, és hagyja, hogy a processzor kezelje a fordítói feladatokat. Ezt egy mechanizmussal korrigálták sched_autogroup, de a processzoridő feladatok közötti elosztásának számos egyéb jellemzője megmaradt. Tulajdonképpen ez nem arról szól, hogy a CFS-ben minden rossz, hanem arra próbáljuk felhívni a figyelmet, hogy a processzoridő „tisztességes” elosztása nem a legtriviálisabb feladat.

Egy másik fontos pont az ütemezőben az elővásárlás. Erre azért van szükség, hogy a nevetés folyamatát kiűzzük a processzorból, és hagyjuk, hogy mások dolgozzanak. A kilökési folyamatot kontextusváltásnak nevezik. Ebben az esetben a feladat teljes kontextusa megmarad: a verem állapota, a regiszterek stb., ami után a folyamat várakozik, és egy másik lép a helyére. Ez költséges művelet az operációs rendszer számára, és ritkán használják, de nincs vele semmi baj. A gyakori kontextusváltás jelezheti az operációs rendszer problémáját, de általában folyamatos, és nem jelez semmi különöset.

Ilyen hosszú történetre van szükség ahhoz, hogy megmagyarázzunk egy tényt: minél több processzorerőforrást próbál felhasználni egy folyamat egy őszinte Linux ütemezőben, annál gyorsabban leállítják, hogy más folyamatok is működhessenek. Hogy ez helyes-e vagy sem, az egy összetett kérdés, amely különböző terhelések mellett másként is megoldható. A Windows rendszerben egészen a közelmúltig az ütemező az asztali alkalmazások elsőbbségi feldolgozására összpontosított, ami a háttérfolyamatok lefagyását okozhatja. A Sun Solarisnak öt különböző ütemező osztálya volt. Amikor elindítottuk a virtualizációt, hozzáadtunk egy hatodik, Fair share ütemező, mert az előző öt nem működött megfelelően a Solaris Zones virtualizációval. Azt javaslom, hogy kezdje el a probléma részletes tanulmányozását olyan könyvekkel, mint a Solaris belső elemek: Solaris 10 és OpenSolaris Kernel Architecture vagy A Linux kernel megértése.

2.4. Hogyan lehet nyomon követni a lopást?

A virtuális gépeken belüli lopások megfigyelése, mint bármely más processzormutató, egyszerű: bármilyen processzormérő eszközt használhat. A lényeg az, hogy a virtuális gép Linuxon legyen. A Windows valamilyen oknál fogva nem adja meg ezt az információt felhasználóinak. 🙁

Lop: ki lopja a CPU-időt a virtuális gépekről
A felső parancs kimenete: a processzor terhelésének részletei, a jobb szélső oszlopban - lopni

A nehézség akkor merül fel, amikor megpróbáljuk megszerezni ezeket az információkat a hipervizortól. Megpróbálhatja megjósolni a lopást a gazdagépen, például a Load Average (LA) paraméterrel – a végrehajtási sorban várakozó folyamatok számának átlagos értékével. Ennek a paraméternek a kiszámításának módja nem egyszerű, de általában, ha a processzorszálak számával normalizált LA nagyobb, mint 1, ez azt jelzi, hogy a Linux szerver túl van terhelve valamivel.

Mire várnak ezek a folyamatok? A kézenfekvő válasz a processzor. De a válasz nem teljesen helyes, mert néha a processzor ingyenes, de az LA kilép a skála alól. Emlékezik hogyan esik le az NFS és hogyan nő az LA. Ugyanez történhet lemezzel és más bemeneti/kimeneti eszközökkel. Valójában azonban a folyamatok bármilyen zárolás végére várhatnak, legyen az I/O eszközhöz kapcsolódó fizikai vagy logikai, például mutex. Ez magában foglalja a hardver szintű zárolást (ugyanaz a válasz a lemezről) vagy a logikát (az úgynevezett zárolási primitívek, amelyek egy csomó entitást tartalmaznak, mutex adaptív és spin, szemaforok, feltétel változók, rw zárak, ipc zárak ...).

Az LA másik jellemzője, hogy az operációs rendszer átlagának számít. Például 100 folyamat verseng egy fájlért, majd LA=50. Egy ilyen nagy érték azt jelzi, hogy az operációs rendszer rossz. De más ferdén megírt kódnál ez normális állapot lehet, annak ellenére, hogy csak ez rossz, és az operációs rendszer többi folyamata nem szenved.

Az átlagolás miatt (és nem kevesebb, mint egy perc alatt) az LA mutató alapján bármit is meghatározni nem a legkifizetődőbb feladat, konkrét esetekben nagyon bizonytalan eredményeket ad. Ha megpróbálja kitalálni, azt fogja tapasztalni, hogy a Wikipédián és más elérhető forrásokban található cikkek csak a legegyszerűbb eseteket írják le, a folyamat mélyreható magyarázata nélkül. Ismételten küldöm mindenkinek, akit érdekel, ide Brendan Greggnek  - kövesse az alábbi linkeket. Ki lusta angolul beszélni? LA-ról szóló népszerű cikkének fordítása.

3. Speciális effektusok

Most pedig nézzük meg a főbb lopási eseteket, amelyekkel találkoztunk. Elmondom, hogyan következnek ezek a fentiekből, és hogyan viszonyulnak a hypervisor mutatóihoz.

Újrafeldolgozás. A legegyszerűbb és leggyakoribb: a hipervizort újra felhasználták. Valóban sok futó virtuális gép van, magas processzorfogyasztás bennük, nagy a verseny, az LA kihasználtsága több mint 1 (processzorszálakkal normalizálva). Az összes virtuális gépen belül minden lelassul. A hipervizorból átvitt lopás is növekszik, újra kell osztani a terhelést vagy ki kell kapcsolni valakit. Általában minden logikus és érthető.

Paravirtualizáció vs. egyedi példányok. Csak egy virtuális gép van a hypervisoron, ennek egy kis részét fogyasztja, de nagy I/O terhelést produkál, például a lemezen. És valahonnan egy kis lopás jelenik meg benne, akár 10% (amint azt több kísérlet is mutatja).

Érdekes az eset. A Steal itt éppen a paravirtualizált meghajtók szintjén történő blokkolás miatt jelenik meg. A virtuális gépen belül létrejön egy megszakítás, amelyet az illesztőprogram feldolgoz, és elküld a hypervisornak. A hypervisoron a megszakításkezelés miatt a virtuális gép számára elküldött kérésnek tűnik, készen áll a végrehajtásra és várja a processzort, de nem kap processzoridőt. A virtuális lány azt hiszi, hogy ezt az időt ellopták.

Ez a puffer elküldésének pillanatában történik, bekerül a hypervisor kernelterébe, és elkezdünk rá várni. Bár a virtuális gép szempontjából azonnal vissza kellene térnie. Ezért a lopási számítási algoritmus szerint ez az idő ellopottnak minősül. Valószínűleg ebben a helyzetben más mechanizmusok is létezhetnek (például néhány más rendszerhívás feldolgozása), de ezek nem különbözhetnek egymástól.

Ütemező a nagy terhelésű virtuális gépekkel szemben. Ha egy virtuális gép többet szenved a lopástól, mint mások, ez az ütemezőnek köszönhető. Minél jobban terheli egy folyamat a processzort, az ütemező annál hamarabb kirúgja, hogy a többiek is működhessenek. Ha a virtuális gép keveset fogyaszt, alig lát lopást: a folyamata őszintén ült és várt, több időt kell adnunk neki. Ha egy virtuális gép a maximális terhelést produkálja minden magjára, akkor gyakran kirúgják a processzorból, és igyekeznek nem sok időt adni neki.

Még rosszabb, ha a virtuális gépen belüli folyamatok megpróbálnak több processzort szerezni, mert nem tudnak megbirkózni az adatfeldolgozással. Ekkor a hypervisor operációs rendszere az őszinte optimalizálás miatt egyre kevesebb processzoridőt biztosít. Ez a folyamat lavinaszerűen megy végbe, és a lopás az egekbe ugrik, bár más virtuális gépek ezt aligha veszik észre. És minél több mag, annál rosszabb az érintett gép. Röviden, a nagy terhelésű, sok maggal rendelkező virtuális gépek szenvednek a leginkább.

Alacsony LA, de van lopás. Ha az LA körülbelül 0,7 (azaz úgy tűnik, hogy a hipervizor alul van terhelve), de az egyes virtuális gépeken belül lopást figyeltek meg:

  • A fentebb már ismertetett paravirtualizációs lehetőség. A virtuális gép képes fogadni a lopást jelző mutatókat, bár a hypervisor rendben van. Kísérleteink eredményei szerint ez a lopási lehetőség nem haladja meg a 10%-ot, és nem lehet jelentős hatással a virtuális gépen belüli alkalmazások teljesítményére.
  • Az LA paraméter kiszámítása hibás. Pontosabban, minden adott pillanatban helyesen számítják ki, de egy percre átlagolva alulbecsültnek bizonyul. Például, ha a hypervisor harmadánként egy virtuális gép pontosan fél percig fogyasztja az összes processzorát, akkor a hypervisor percenkénti LA értéke 0,15 lesz; négy ilyen virtuális gép egyidejű működése 0,6-ot ad. Az pedig, hogy mindegyiken fél percig volt vad lopás az LA mutató szerint 25%-nál, már nem lehet kihúzni.
  • Ismét az ütemező miatt, aki úgy döntött, hogy valaki túl sokat eszik, és hagyta, hogy valaki várjon. Addig is átállítom a kontextust, kezelem a megszakításokat és más fontos rendszerdolgokat. Ennek eredményeként egyes virtuális gépek nem látnak problémát, míg mások komoly teljesítménycsökkenést tapasztalnak.

4. Egyéb torzítások

Millió további oka van annak, hogy egy virtuális gépen torzítsák a processzoridő méltányos megtérülését. Például a hyperthreading és a NUMA nehézségeket okoz a számításokban. Teljesen összekeverik a kernel kiválasztását a folyamat végrehajtásához, mivel az ütemező együtthatókat - súlyokat - használ, amelyek még megnehezítik a számítást a kontextus váltásakor.

Olyan technológiák miatt vannak torzítások, mint a turbónövelés, vagy fordítva, az energiatakarékos mód, amelyek a kihasználtság kiszámításakor mesterségesen növelhetik vagy csökkenthetik a frekvenciát vagy akár az időszeletet a szerveren. A turbo boost engedélyezése csökkenti az egyik processzorszál teljesítményét a másik teljesítményének növekedése miatt. Ebben a pillanatban a processzor aktuális frekvenciájára vonatkozó információkat nem továbbítják a virtuális gépnek, és azt hiszi, hogy valaki ellopja az idejét (például 2 GHz-et kért, de ennek felét kapta).

Általában sok oka lehet a torzításnak. Egy adott rendszeren találhat mást is. Jobb azokkal a könyvekkel kezdeni, amelyekhez fentebb hivatkozásokat adtam, és a statisztikákat lekérni a hypervisorból olyan segédprogramok segítségével, mint a perf, sysdig, systemtap, amelyek közül Több tucat.

5. Konklúziók

  1. A paravirtualizáció miatt előfordulhat némi lopás, és ez normálisnak tekinthető. Azt írják az interneten, hogy ez az érték 5-10% is lehet. A virtuális gépen belüli alkalmazásoktól és a fizikai eszközök terhelésétől függ. Itt fontos figyelni arra, hogy az alkalmazások hogyan érzik magukat a virtuális gépeken belül.
  2. A hypervisor terhelése és a virtuális gépen belüli lopás aránya nem mindig van egyértelműen összefüggésben egymással; a lopásra vonatkozó mindkét becslés hibás lehet bizonyos helyzetekben, különböző terhelések mellett.
  3. Az ütemező rosszul viszonyul a sokat kérdező folyamatokhoz. Igyekszik kevesebbet adni annak, aki többet kér. A nagy virtuális gépek gonoszak.
  4. Egy kis lopás még paravirtualizálás nélkül is jellemző lehet (figyelembe véve a virtuális gépen belüli terhelést, a szomszédok terhelésének jellemzőit, a szálak közötti terheléseloszlást és egyéb tényezőket).
  5. Ha ki akarja deríteni a lopást egy adott rendszerben, fel kell fedeznie a különféle lehetőségeket, össze kell gyűjtenie a mutatókat, gondosan elemeznie kell azokat, és át kell gondolnia a terhelés egyenletes elosztását. Bármilyen esettől el lehet térni, amit kísérletileg meg kell erősíteni, vagy meg kell nézni a kernel hibakeresőjében.

Forrás: will.com

Hozzászólás