Stjæl: hvem stjæler CPU-tid fra virtuelle maskiner

Stjæl: hvem stjæler CPU-tid fra virtuelle maskiner

Hej! Jeg vil i enkle vendinger fortælle dig om mekanikken ved at stjæle inde i virtuelle maskiner og om nogle ikke-oplagte artefakter, som vi formåede at finde ud af under forskningen, som jeg var nødt til at dykke ned i som teknisk direktør for en cloud-platform Mail.ru Cloud-løsninger. Platformen kører på KVM.

CPU-tyvningstid er den tid, hvor den virtuelle maskine ikke modtager processorressourcer til sin eksekvering. Denne tid tælles kun i gæsteoperativsystemer i virtualiseringsmiljøer. Årsagerne til, hvor disse mest allokerede ressourcer går hen, som i livet, er meget vage. Men vi besluttede at finde ud af det og udførte endda en række eksperimenter. Det er ikke sådan, at vi nu ved alt om at stjæle, men vi vil fortælle dig noget interessant nu.

1. Hvad er stjæle

Så stjæle er en metrik, der indikerer mangel på processortid for processer inde i en virtuel maskine. Som beskrevet i KVM-kernepatchenStealth er den tid, hvor hypervisoren udfører andre processer på værts-OS, selvom den har sat den virtuelle maskinproces i kø til eksekvering. Det vil sige, at stjæle beregnes som forskellen mellem det tidspunkt, hvor processen er klar til at udføres, og det tidspunkt, hvor processen er tildelt processortid.

Den virtuelle maskine-kerne modtager stjæle-metrikken fra hypervisoren. Samtidig specificerer hypervisoren ikke præcis, hvilke andre processer den kører, den siger blot "mens jeg har travlt, kan jeg ikke give dig tid." På KVM er der tilføjet understøttelse af tyveriberegning plastre. Der er to hovedpunkter her:

  • Den virtuelle maskine lærer om tyveri fra hypervisoren. Det vil sige, ud fra et tabssynspunkt, for processer på selve den virtuelle maskine er dette en indirekte måling, der kan være udsat for forskellige forvrængninger.
  • Hypervisoren deler ikke information med den virtuelle maskine om, hvad den ellers laver - det vigtigste er, at den ikke afsætter tid til det. På grund af dette kan den virtuelle maskine ikke selv registrere forvrængninger i stjæleindikatoren, hvilket kunne vurderes ud fra arten af ​​konkurrerende processer.

2. Hvad påvirker stjæle

2.1. Stjæleberegning

I det væsentlige beregnes tyveri omtrent det samme som den normale CPU-udnyttelsestid. Der er ikke meget information om, hvordan genbrug opfattes. Sandsynligvis fordi de fleste mennesker anser dette spørgsmål for indlysende. Men der er også faldgruber her. For at sætte dig ind i denne proces, kan du læse artikel af Brendan Gregg: du vil lære om en masse nuancer ved beregning af udnyttelse og om situationer, hvor denne beregning vil være fejlagtig af følgende årsager:

  • Processoren overophedes, hvilket får cyklusser til at springe over.
  • Aktiver/deaktiver turbo boost, som ændrer processorens clockhastighed.
  • En ændring i længden af ​​det tidsudsnit, der opstår ved brug af strømbesparende processorteknologier såsom SpeedStep.
  • Problemet med at beregne gennemsnittet: at estimere et minuts udnyttelse til 80 % kan skjule et kortsigtet udbrud på 100 %.
  • En spin-lås får processoren til at blive genvundet, men brugerprocessen kan ikke se nogen fremskridt i dens eksekvering. Som et resultat vil den beregnede processorudnyttelse af processen være hundrede procent, selvom processen ikke fysisk vil forbruge processortid.

Jeg har ikke fundet en artikel, der beskriver en lignende beregning for stjæle (hvis du ved, del den i kommentarerne). Men ud fra kildekoden at dømme er beregningsmekanismen den samme som for genbrug. Simpelthen tilføjes en anden tæller i kernen, direkte til KVM-processen (virtuel maskinproces), som tæller varigheden af ​​KVM-processen, der venter på CPU-tid. Tælleren tager information om processoren fra dens specifikation og kontrollerer, om alle dens ticks udnyttes af den virtuelle maskinproces. Hvis det er alt, så antager vi, at processoren kun var optaget af den virtuelle maskinproces. Ellers informerer vi om, at processoren lavede noget andet, stjæle dukkede op.

Stjæleoptællingsprocessen er underlagt de samme problemer som almindelig genbrugsoptælling. For ikke at sige, at sådanne problemer opstår ofte, men de ser nedslående ud.

2.2. Typer af virtualisering på KVM

Overordnet set er der tre typer virtualisering, som alle understøttes af KVM. Mekanismen for tyveri kan afhænge af typen af ​​virtualisering.

oversættelse. I dette tilfælde sker driften af ​​det virtuelle maskine-operativsystem med fysiske hypervisor-enheder noget som dette:

  1. Gæsteoperativsystemet sender en kommando til sin gæsteenhed.
  2. Gæsteenhedsdriveren modtager kommandoen, genererer en anmodning til enhedens BIOS og sender den til hypervisoren.
  3. Hypervisor-processen oversætter kommando til kommando for den fysiske enhed, hvilket gør den blandt andet mere sikker.
  4. Den fysiske enhedsdriver accepterer den ændrede kommando og sender den til selve den fysiske enhed.
  5. Resultaterne af udførelse af kommandoer går tilbage ad samme vej.

Fordelen ved oversættelse er, at det giver dig mulighed for at emulere enhver enhed og ikke kræver særlig forberedelse af operativsystemets kerne. Men du skal først og fremmest betale for dette i hastighed.

Hardware virtualisering. I dette tilfælde forstår enheden på hardwareniveau kommandoer fra operativsystemet. Dette er den hurtigste og bedste måde. Men desværre understøttes det ikke af alle fysiske enheder, hypervisorer og gæsteoperativsystemer. I øjeblikket er de vigtigste enheder, der understøtter hardwarevirtualisering, processorer.

Paravirtualisering. Den mest almindelige mulighed for enhedsvirtualisering på KVM og generelt den mest almindelige virtualiseringstilstand for gæsteoperativsystemer. Dets særegenhed er, at arbejde med nogle hypervisor-undersystemer (for eksempel med netværket eller diskstakken) eller tildeling af hukommelsessider sker ved hjælp af hypervisor-API'en uden at oversætte kommandoer på lavt niveau. Ulempen ved denne virtualiseringsmetode er, at gæsteoperativsystemkernen skal modificeres, så den kan kommunikere med hypervisoren ved hjælp af denne API. Men dette løses normalt ved at installere specielle drivere på gæsteoperativsystemet. I KVM kaldes denne API virtio API.

Med paravirtualisering, sammenlignet med broadcasting, reduceres stien til den fysiske enhed betydeligt ved at sende kommandoer direkte fra den virtuelle maskine til hypervisorprocessen på værten. Dette giver dig mulighed for at fremskynde udførelsen af ​​alle instruktioner inde i den virtuelle maskine. I KVM gøres dette af virtio API, som kun virker for visse enheder, såsom et netværk eller en diskadapter. Dette er grunden til, at virtio-drivere er installeret inde i virtuelle maskiner.

Ulempen ved denne acceleration er, at ikke alle processer, der kører inde i den virtuelle maskine, forbliver inde i den. Dette skaber nogle specielle effekter, der kan resultere i spawning ved tyveri. Jeg anbefaler at starte en detaljeret undersøgelse af dette problem med En API til virtuel I/O: virtio.

2.3. "Fair" planlægning

En virtuel maskine på en hypervisor er i virkeligheden en almindelig proces, der adlyder lovene for planlægning (ressourcefordeling mellem processer) i Linux-kernen, så lad os se nærmere på det.

Linux bruger den såkaldte CFS, Completely Fair Scheduler, som er blevet standardplanlæggeren siden kerne 2.6.23. For at forstå denne algoritme kan du læse Linux Kernel Architecture eller kildekoden. Essensen af ​​CFS er at fordele processortid mellem processer afhængigt af varigheden af ​​deres eksekvering. Jo mere CPU-tid en proces kræver, jo mindre CPU-tid modtager den. Dette sikrer, at alle processer bliver eksekveret "retfærdigt" - så én proces ikke konstant optager alle processorer, og andre processer kan også eksekvere.

Nogle gange fører dette paradigme til interessante artefakter. Længerevarende Linux-brugere husker sikkert frysningen af ​​en almindelig teksteditor på et skrivebord, mens de kører ressourcekrævende applikationer såsom en compiler. Dette skete, fordi ikke-ressourcekrævende opgaver i desktopapplikationer konkurrerede med ressourcekrævende opgaver, såsom compileren. CFS mener, at dette er uretfærdigt, så det stopper med jævne mellemrum teksteditoren og lader processoren håndtere compilerens opgaver. Dette blev rettet ved hjælp af en mekanisme sched_autogroup, men mange andre funktioner i fordelingen af ​​processortid mellem opgaver forblev. Faktisk er dette ikke en historie om, hvor dårligt alt er i CFS, men et forsøg på at gøre opmærksom på, at "fair" fordeling af processortid ikke er den mest trivielle opgave.

Et andet vigtigt punkt i skemalæggeren er præemption. Dette er nødvendigt for at sparke grineprocessen ud af processoren og lade andre arbejde. Udstødningsprocessen kaldes kontekstskifte. I dette tilfælde bevares hele konteksten af ​​opgaven: stakkens tilstand, registre osv., hvorefter processen sendes til at vente, og en anden tager dens plads. Dette er en dyr operation for operativsystemet og bruges sjældent, men der er ikke noget iboende galt med det. Hyppig kontekstskift kan indikere et problem i operativsystemet, men normalt er det kontinuerligt og indikerer ikke noget særligt.

En så lang historie er nødvendig for at forklare én kendsgerning: Jo flere processorressourcer en proces forsøger at forbruge i en ærlig Linux-planlægger, jo hurtigere vil den blive stoppet, så andre processer også kan fungere. Hvorvidt dette er korrekt eller ej, er et komplekst spørgsmål, som kan løses forskelligt under forskellige belastninger. I Windows var planlæggeren indtil for nylig fokuseret på prioriteret behandling af desktop-applikationer, hvilket kunne få baggrundsprocesser til at fryse. Sun Solaris havde fem forskellige klasser af skemalæggere. Da vi lancerede virtualisering, tilføjede vi en sjette, Fair share planlægger, fordi de foregående fem ikke fungerede tilstrækkeligt med Solaris Zones-virtualisering. Jeg anbefaler at starte en detaljeret undersøgelse af dette problem med bøger som Solaris Internals: Solaris 10 og OpenSolaris Kernel Architecture eller Forstå Linux-kernen.

2.4. Hvordan overvåger man stjæle?

Overvågning af stjæle inde i en virtuel maskine, som enhver anden processormetrik, er enkel: du kan bruge ethvert processormetrikværktøj. Det vigtigste er, at den virtuelle maskine er på Linux. Af en eller anden grund giver Windows ikke disse oplysninger til sine brugere. 🙁

Stjæl: hvem stjæler CPU-tid fra virtuelle maskiner
Output af den øverste kommando: detaljer om processorbelastningen, i kolonnen længst til højre - stjæle

Vanskeligheden opstår, når man forsøger at få denne information fra hypervisoren. Du kan prøve at forudsige tyveri på værtsmaskinen, for eksempel ved at bruge parameteren Load Average (LA) - gennemsnitsværdien af ​​antallet af processer, der venter i eksekveringskøen. Metoden til at beregne denne parameter er ikke enkel, men generelt, hvis LA normaliseret med antallet af processortråde er mere end 1, indikerer dette, at Linux-serveren er overbelastet med noget.

Hvad venter alle disse processer på? Det åbenlyse svar er processoren. Men svaret er ikke helt korrekt, for nogle gange er processoren gratis, men LA går ud af skalaen. Husk hvordan NFS falder af, og hvordan LA vokser. Det samme kan ske med en disk og andre input/output-enheder. Men faktisk kan processer vente på slutningen af ​​enhver lås, enten fysisk, forbundet med en I/O-enhed eller logisk, såsom en mutex. Dette inkluderer også låsning på hardwareniveau (det samme svar fra disken) eller logik (de såkaldte låseprimitiver, som inkluderer en masse entiteter, mutex adaptive og spin, semaforer, tilstandsvariable, rw-låse, ipc-låse ...).

Et andet træk ved LA er, at det betragtes som et operativsystemgennemsnit. For eksempel konkurrerer 100 processer om en fil, og derefter LA=50. Så stor en værdi tyder på, at operativsystemet er dårligt. Men for anden skævt skrevet kode kan dette være en normal tilstand, på trods af at kun den er dårlig, og andre processer i operativsystemet ikke lider.

På grund af dette gennemsnit (og på ikke mindre end et minut), er det ikke den mest givende opgave at bestemme noget ved LA-indikatoren, med meget usikre resultater i specifikke tilfælde. Hvis du forsøger at finde ud af det, vil du opdage, at artikler på Wikipedia og andre tilgængelige ressourcer kun beskriver de enkleste tilfælde, uden en dyb forklaring af processen. Jeg sender igen alle interesserede, her til Brendan Gregg  - følg nedenstående links. Hvem er for doven til at tale engelsk - oversættelse af hans populære artikel om LA.

3. Specialeffekter

Lad os nu se på de vigtigste tilfælde af tyveri, som vi stødte på. Jeg vil fortælle dig, hvordan de følger af alt ovenstående, og hvordan de relaterer til indikatorerne på hypervisoren.

Genbrug. Det enkleste og mest almindelige: hypervisoren er blevet genbrugt. Faktisk er der en masse kørende virtuelle maskiner, højt processorforbrug inde i dem, en masse konkurrence, LA-udnyttelsen er mere end 1 (normaliseret af processortråde). Alt inde i alle virtuelle maskiner bliver langsommere. Stjæle, der overføres fra hypervisoren, vokser også, det er nødvendigt at omfordele belastningen eller slukke for nogen. Generelt er alt logisk og forståeligt.

Paravirtualisering vs. enkelte tilfælde. Der er kun én virtuel maskine på hypervisoren, den bruger en lille del af den, men producerer en stor I/O-belastning, for eksempel på disk. Og fra et eller andet sted dukker der et lille stjæle op i det, op til 10% (som vist af flere eksperimenter).

Sagen er interessant. Stjæl optræder her netop på grund af blokering på niveau med paravirtualiserede drivere. En interrupt oprettes inde i den virtuelle maskine, behandles af driveren og sendes til hypervisoren. På grund af afbrydelseshåndteringen på hypervisoren ligner den for den virtuelle maskine en sendt anmodning, den er klar til udførelse og venter på processoren, men den får ikke processortid. Den virtuelle pige tror, ​​at denne gang er blevet stjålet.

Dette sker i det øjeblik, bufferen sendes, den går ind i hypervisorens kernerum, og vi begynder at vente på det. Selvom han fra den virtuelle maskines synspunkt bør vende tilbage med det samme. Derfor anses denne tid i henhold til steal-beregningsalgoritmen for at være stjålet. Mest sandsynligt kan der i denne situation være andre mekanismer (for eksempel behandling af nogle andre sys-kald), men de burde ikke være meget anderledes.

Planlægger versus højt belastede virtuelle maskiner. Når en virtuel maskine lider mere af stjæle end andre, skyldes det skemalæggeren. Jo mere en proces indlæser processoren, jo hurtigere vil planlæggeren sparke den ud, så de andre også kan arbejde. Hvis den virtuelle maskine bruger lidt, vil den næppe se stjæle: dens proces sad ærligt og ventede, vi er nødt til at give den mere tid. Hvis en virtuel maskine producerer den maksimale belastning på alle dens kerner, bliver den ofte smidt ud af processoren, og de forsøger ikke at give den en masse tid.

Det er endnu værre, når processer inde i den virtuelle maskine forsøger at få mere processor, fordi de ikke kan klare databehandling. Så vil styresystemet på hypervisoren, grundet ærlig optimering, give mindre og mindre processortid. Denne proces opstår som en lavine, og stjæle springer til himlen, selvom andre virtuelle maskiner næsten ikke bemærker det. Og jo flere kerner, jo værre er den berørte maskine. Kort sagt lider højt belastede virtuelle maskiner med mange kerner mest.

Lavt LA, men der er stjålet. Hvis LA er ca. 0,7 (det vil sige hypervisoren ser ud til at være underbelastet), men der observeres tyveri inde i individuelle virtuelle maskiner:

  • Muligheden med paravirtualisering allerede beskrevet ovenfor. Den virtuelle maskine kan modtage metrics, der indikerer tyveri, selvom hypervisoren er fin. Ifølge resultaterne af vores eksperimenter overstiger denne stjælemulighed ikke 10% og bør ikke have en væsentlig indflydelse på ydeevnen af ​​applikationer inde i den virtuelle maskine.
  • LA-parameteren er beregnet forkert. Mere præcist, i hvert specifikt øjeblik beregnes det korrekt, men når gennemsnittet over et minut viser sig at være undervurderet. For eksempel, hvis en virtuel maskine pr. tredjedel af hypervisoren bruger alle sine processorer i præcis et halvt minut, så vil LA pr. minut på hypervisoren være 0,15; fire sådanne virtuelle maskiner, der arbejder samtidigt, vil give 0,6. Og det faktum, at der i et halvt minut på hver af dem var et vildt stjæle på 25% ifølge LA-indikatoren, kan ikke længere trækkes ud.
  • Igen, på grund af planlæggeren, der besluttede, at nogen spiste for meget og lod vedkommende vente. I mellemtiden skifter jeg kontekst, håndterer afbrydelser og tager mig af andre vigtige systemting. Som følge heraf ser nogle virtuelle maskiner ingen problemer, mens andre oplever en alvorlig forringelse af ydeevnen.

4. Andre forvrængninger

Der er en million flere grunde til at forvrænge det rimelige afkast af processortid på en virtuel maskine. For eksempel introducerer hyperthreading og NUMA vanskeligheder i beregninger. De forvirrer fuldstændig valget af kerne til at udføre processen, fordi skemalæggeren bruger koefficienter - vægte, som gør beregningen endnu vanskeligere, når der skiftes kontekst.

Der er forvrængninger på grund af teknologier som turbo boost eller omvendt energisparetilstand, som ved beregning af udnyttelse kunstigt kan øge eller mindske frekvensen eller endda tidsudsnittet på serveren. Aktivering af turbo-boost reducerer ydeevnen af ​​én processortråd på grund af en stigning i ydeevnen af ​​en anden. I øjeblikket sendes information om den aktuelle processorfrekvens ikke til den virtuelle maskine, og den mener, at nogen stjæler dens tid (for eksempel anmodede den om 2 GHz, men modtog halvdelen af ​​det).

Generelt kan der være mange årsager til forvrængning. Du kan finde noget andet på et bestemt system. Det er bedre at starte med bøgerne, som jeg gav links til ovenfor, og hente statistik fra hypervisoren ved hjælp af værktøjer som perf, sysdig, systemtap, hvoraf snesevis af.

5 konklusioner

  1. En vis mængde stjæle kan forekomme på grund af paravirtualisering, og det kan betragtes som normalt. De skriver på internettet, at denne værdi kan være 5-10%. Afhænger af applikationerne inde i den virtuelle maskine og af den belastning, den påfører sine fysiske enheder. Her er det vigtigt at være opmærksom på, hvordan applikationer føles inde i virtuelle maskiner.
  2. Forholdet mellem belastningen på hypervisoren og tyveri inde i den virtuelle maskine er ikke altid tydeligt forbundne; begge estimater af tyveri kan være fejlagtige i specifikke situationer under forskellige belastninger.
  3. Planlæggeren har en dårlig holdning til processer, der spørger meget. Han forsøger at give mindre til dem, der beder om mere. Store virtuelle maskiner er onde.
  4. Lidt stjæle kan være normen selv uden paravirtualisering (under hensyntagen til belastningen inde i den virtuelle maskine, karakteristikaene for belastningen af ​​naboer, belastningsfordeling på tværs af tråde og andre faktorer).
  5. Hvis du vil finde ud af at stjæle i et specifikt system, skal du udforske forskellige muligheder, indsamle metrics, analysere dem omhyggeligt og tænke over, hvordan du kan fordele belastningen jævnt. Afvigelser fra alle tilfælde er mulige, hvilket skal bekræftes eksperimentelt eller ses på i kernel debuggeren.

Kilde: www.habr.com

Tilføj en kommentar