Steal: hvem stjæler CPU-tid fra virtualiseringer

Steal: hvem stjæler CPU-tid fra virtualiseringer

Hej! Jeg vil gerne forklare på en enkel måde, hvordan steal opstår inden for virtuelle maskiner, samt nogle uventede artefakter, vi er stødt på under vores undersøgelse, som jeg har dykket ned i som teknisk direktør for cloud-platformen. Mail.ru Cloud Solutions. Platformen kører på KVM.

CPU steal time — er den tid, hvor den virtuelle maskine ikke modtager CPU-ressourcer til sin udførelse. Denne tid tælles kun i gæsteoperativsystemer i virtualiseringsmiljøer. Årsagerne til, hvor disse tildelte ressourcer går hen, er desværre temmelig uklare. Vi besluttede os for at undersøge dette nærmere og gennemførte en række eksperimenter. Selvom vi ikke ved alt om steal nu, har vi nogle interessante indsigter at dele.

1. Hvad er steal

Så, steal — er en metrisk måling, der indikerer mangel på CPU-tid til processerne inden for den virtuelle maskine. Som beskrevet i KVM-kernelpatchen, er steal den tid, hvor hypervisoren kører andre processer på værtsoperativsystemet, selvom den har placeret den virtuelle maskines proces i kø til udførelse. Det vil sige, steal beregnes som forskellen mellem den tid, hvor processen er klar til at blive udført, og den tid, hvor processen får tildelt CPU-tid.

Den virtuelle maskine modtager steal-metrikken fra hypervisoren. Hypervisoren specificerer ikke, hvilke andre processer den udfører, men siger blot "jeg er optaget, så jeg kan ikke give dig tid lige nu". I KVM er støtten til beregning af steal tilføjet i patchene.Der er to hovedpunkter her:

  • Den virtuelle maskine bliver informeret om steal af hypervisoren. Det vil sige, at set fra tabernes perspektiv, er det for processerne på selve virtualiseringerne en indirekte måling, som kan være udsat for forskellige forvrængninger.
  • Hypervisoren deler ikke med virtualiseringen, hvad den er optaget med — det vigtigste er, at den ikke giver tid til den. Af denne grund kan selve virtualiseringen ikke identificere forvrængninger i steal-metrikken, som kunne vurderes ud fra karakteren af de konkurrerende processer.

2. Hvad påvirker steal

2.1. Beregning af steal

I bundet betragtes steal stort set ligesom den normale CPU-udnyttelse. Der er ikke meget information om, hvordan udnyttelsen beregnes. Måske fordi de fleste anser dette spørgsmål for at være åbenlyst. Men der kan også være faldgruber her. For at blive bekendt med denne proces kan du læse artiklen af Brendann Gregg: du vil lære om en række nuanceforskelle ved beregningen af udnyttelse og om situationer, hvor denne beregning vil være fejlagtig af følgende grunde:

  • Overophedning af CPU'en, hvor der springes cykler over.
  • Tænd/sluk for turbo boost, hvilket ændrer CPU'ens klokfrekvens.
  • Ændring af tidskvantitet, der sker ved brug af CPU-energibesparende teknologier, som f.eks. SpeedStep.
  • Problemet med at beregne gennemsnittet: en vurdering af udnyttelsen på 80 % over et minut kan skjule et kortvarigt burst på 100 %.
  • Cyclic lock (spin lock) resulterer i, at CPU'en er udnyttet, men brugerprocessen ser ikke fremgang i sin udførelse. Som resultat vil den beregnede udnyttelse af CPU'en for processen være 100 %, selvom CPU-tid ikke fysisk bliver forbrugt.

Jeg fandt ikke artikler, der beskriver en lignende beregning for steal (hvis du ved det — del venligst i kommentarerne). Men ifølge kildekoden er beregningsmekanismen den samme som for udnyttelse. Bare i kernen tilføjes der endnu en tæller, specifikt for KVM-processen (virtuelle maskine-proces), der registrerer varigheden af KVM-processens ventetid på CPU-tid. Tælleren henter oplysninger om CPU'en fra dens specifikation og undersøger, om alle dens tikker er udnyttet af virtualmaskineprocessen. Hvis de er, så antager vi, at CPU'en kun har været involveret i den virtuelle maskine. I modsætning hertil informerer vi om, at CPU'en har været involveret i noget andet og at steal er opstået.

Processen til at beregne steal er udsat for de samme problemer som almindelig udnyttelsesevaluering. Man kan ikke sige, at sådanne problemer opstår ofte, men de virker nedslående.

2.2. Typer af virtualisering på KVM

Generelt er der tre typer virtualisering, og alle understøttes af KVM. Den type virtualisering, der anvendes, kan påvirke mekanismen for opståen af steal.

OversættelseI dette tilfælde arbejder operativsystemet for den virtuelle maskine med hypervisorens fysiske enheder omtrent sådan her:

  1. Gæsteoperativsystemet sender en kommando til sin gæsteenhed.
  2. Driveren for gæsteenheden modtager kommandoen, danner en forespørgsel til enhedens BIOS og sender den til hypervisoren.
  3. Hypervisorens proces oversætter kommandoen til en kommando for den fysiske enhed og gør den blandt andet mere sikker.
  4. Driveren for den fysiske enhed modtager den modificerede kommando og sender den videre til den fysiske enhed.
  5. Resultaterne af kommandoens udførelse går tilbage ad den samme vej.

Fordelen ved oversættelsen er, at den muliggør emulering af enhver enhed og ikke kræver særlig forberedelse af operativsystemets kerne. Men prisen betales først og fremmest i form af hastighed.

HardwarevirtualiseringI dette tilfælde forstår enheden på hardware-niveau kommandoer fra operativsystemet. Dette er den hurtigste og bedste metode. Men desværre understøttes den ikke af alle fysiske enheder, hypervisorer og gæsteoperativsystemer. På nuværende tidspunkt er de primære enheder, der understøtter hardwarevirtualisering, processorer.

Paravirtualisering (paravirtualization)Dette er den mest udbredte form for enhedsvirtualisering på KVM og generelt den mest udbredte tilstand for gæsteoperativsystemer. Dets særligt ved er, at arbejdet med nogle af hypervisorens underliggende systemer (som netværks- eller diskstakken) eller tildeling af hukommelsessider sker ved hjælp af hypervisorens API, uden oversættelse af lavniveau kommandoer. Ulempen ved denne virtualiseringsmetode er behovet for at modificere gæsteoperativsystemets kerne, så den kan interagere med hypervisoren via dette API. Men dette løses normalt ved at installere særlige drivere på gæsteoperativsystemet. I KVM kaldes dette API virtio API.

Ved paravirtualisering, i forhold til translation, forkortes vejen til det fysiske apparat betydeligt ved at sende kommandoer direkte fra den virtuelle maskine til hypervisorens proces på værten. Dette muliggør en hurtigere udførelse af alle instruktioner inde i den virtuelle maskine. I KVM håndteres dette af virtio API, som kun fungerer for visse enheder, såsom netværks- eller diskadaptere. Derfor installeres virtio-drivere inde i de virtuelle maskiner.

Den bagside af denne acceleration er, at ikke alle processer, der udføres inde i virtuellen, forbliver inde i den. Dette skaber nogle specielle effekter, der kan føre til problemer med steal. Et grundigt studie af dette emne anbefales at starte med En API til virtuel I/O: virtio.

2.3. "Retfærdig" planlægning

Den virtuelle maskine på hypervisoren er i realiteten en almindelig proces, som underkastes reglerne for planlægning (ressourcefordeling mellem processer) i Linux-kernen, så vi ser nærmere på det.

I Linux anvendes den såkaldte CFS, Completely Fair Scheduler, som fra kernel 2.6.23 blev standardplanlæggeren. For at forstå denne algoritme kan man læse Linux Kernel Architecture eller kildekoden. Essensen af CFS ligger i fordelingen af CPU-tid mellem processer afhængigt af varigheden af deres udførelse. Jo mere CPU-tid en proces kræver, desto mindre tid får den. Dette sikrer en "retfærdig" udførelse af alle processer — så én proces ikke konstant optager alle CPU'er, og de andre processer også kan køre.

Nogle gange fører denne paradigme til interessante artefakter. Langvarige brugere af Linux husker sikkert, at den almindelige teksteditor på skrivebordet fryser under opstarten af ressourcekrævende applikationer som kompilatorer. Dette skete, fordi ikke-ressourcekrævende opgaver fra skrivebordsapplikationer konkurrerede med opgaver, der aktivt krævede ressourcer, som kompilatoren. CFS anser, at dette er uretfærdigt, så den stopper periodisk teksteditoren og giver CPU'en tid til at behandle kompilatorens opgaver. Dette blev rettet ved hjælp af mekanismen sched_autogroup, men der er stadig mange andre funktioner ved fordeling af processorens tid mellem opgaver. Egentlig handler denne fortælling ikke om, hvor dårligt det er i CFS, men om at påpege, at en "fair" fordeling af processorens tid ikke er en triviel opgave.

En anden vigtig faktor i scheduler er preemption. Dette er nødvendigt for at tvinge en overbelastet proces væk fra processoren og give andre mulighed for at arbejde. Procesudvisningen kaldes context switching, som er skiftet af processorens kontekst. Her gemmes hele opgavekonteksten: stackens tilstand, registre og andet, hvorefter processen venter, mens en anden træder ind. Dette er en dyr operation for OS, og den bruges sjældent, men der er i bund og grund ikke noget dårligt i den. Hyppig kontekstskift kan indikere et problem i OS, men normalt går det kontinuerligt og angiver ikke noget særligt.

Denne lange fortælling er nødvendig for at forklare en kendsgerning: jo flere ressourcer processorens opgave forsøger at forbruge i den ærlige scheduler i Linux, jo hurtigere vil den blive stoppet, så andre processer også kan arbejde. Om dette er korrekt eller ej er et komplekst spørgsmål, der varierer afhængigt af belastningen. I Windows var scheduler indtil for nylig fokuseret på prioriteret behandling af desktop-applikationer, hvilket kunne forårsage, at baggrundsprocesser hang. I Sun Solaris var der fem forskellige klasser af schedulere. Da virtualisering blev lanceret, blev der tilføjet en sjette. Fair share scheduler, fordi de tidligere fem arbejdede utilstrækkeligt med Solaris Zones virtualisering. Jeg anbefaler at starte en detaljeret undersøgelse af dette emne med bøger som Solaris Internals: Solaris 10 og OpenSolaris Kernel Architecture eller Understanding the Linux Kernel.

2.4. Hvordan overvåge steal?

At overvåge steal inde i en virtuel maskine, ligesom enhver anden processor-metrik, er enkelt: man kan bruge ethvert værktøj til at måle processor-metrikker. Det vigtigste er, at virtualmaskinen kører på Linux. Windows giver åbenbart ikke sådan information til sine brugere. 🙁

Steal: hvem stjæler CPU-tid fra virtualiseringer
Output fra kommandoen top: detaljering af belastningen på processoren, helt til højre kolonne - steal

Det opstår vanskeligheder, når man forsøger at hente disse oplysninger fra hypervisoren. Man kan måske forudsige steal på værtmaskinen, for eksempel ved at se på Load Average (LA) — det gennemsnitlige antal processer, der venter i kø på at blive udført. Metoden til at beregne denne parameter er kompliceret, men generelt, hvis den normaliserede LA pr. antal CPU-tråde er over 1, indikerer det, at serveren med Linux er belastet.

Hvad venter alle disse processer på? Det åbenlyse svar er CPU'en. Men svaret er ikke helt korrekt, fordi CPU'en nogle gange er ledig, mens LA skyder i vejret. Husk, hvordan NFS falder ud, og hvordan LA stiger. På samme måde kan det være med disken og andre input/output-enheder. Men faktisk kan processerne vente på afslutningen af enhver form for blokering, både fysisk relateret til input/output-enheder og logisk, som for eksempel en mutex. Det inkluderer også blokeringer på hardware-niveau (som svaret fra disken) eller logik (de såkaldte blokingsprimitiver, der omfatter mange enheder, mutex adaptive og spin, semaforer, betingede variable, rw locks, ipc locks…).

En anden egenskab ved LA er, at det beregnes som et gennemsnit for operativsystemet. For eksempel, hvis 100 processer konkurrerer om en fil, er LA=50. Et så højt tal tyder umiddelbart på, at operativsystemet har det skidt. Men for noget dårligt skrevet kode kan dette være en normal tilstand, mens kun den specifikke proces er påvirket, mens andre processer i operativsystemet ikke lider.

På grund af denne gennemsnitsberegning (som strækker sig over mindst et minut) er det at forsøge at bestemme noget ud fra LA-værdien ikke en lunefuld opgave, med ret usikre resultater i konkrete tilfælde. Hvis du prøver at finde ud af det, vil du opdage, at artiklerne på Wikipedia og andre tilgængelige ressourcer kun beskriver de mest grundlæggende tilfælde uden dybdegående forklaring af processen. Til alle interesserede sender jeg igen, herhen til Brendann Gregg  — videre via links. For dem, der ikke orker engelsk — oversættelsen af hans populære artikel om LA.

3. Specialeffekter

Lad os nu fokusere på de vigtigste tilfælde af steal, som vi har stødt på. Jeg vil forklare, hvordan de fremgår af det ovenstående og hvordan de forholder sig til indikationerne på hypervisoren.

Overudnyttelse. Det mest almindelige og hyppigste: hypervisoren er blevet genbrugt. Faktisk kører der mange virtuelle maskiner, med stort CPU-forbrug inden i dem, stor konkurrence, og udnyttelsen er over 1 (i normalisering efter CPU-tråde). Inden i alle VM'er er der alt for meget lag. Steal, der overføres fra hypervisoren, vokser også, og der skal redistribueres belastning eller slukkes for nogle. Generelt er det alt sammen logisk og forståeligt.

Paravirtualisering mod ensomme instanser. På hypervisoren kører der kun én enkelt virtuel maskine, som forbruger en lille del af den, men den giver en stor belastning på input/output, for eksempel vedrørende disk. Og der dukker et lille steal op i den, op til 10 % (som flere gennemførte eksperimenter viser).

En interessant case. Steal optræder her netop på grund af de blokeringer, der er på niveauet af paravirtualiserede drivere. Inden i VM'en oprettes en afbrydelse, behandles af driveren og går til hypervisoren. På grund af behandlingen af afbrydelsen på hypervisoren ser VM'en det som en sendt anmodning, den er klar til udførelse og venter på processoren, men får ikke processtid. VM'en tror, at denne tid er stjålet.

Dette sker i det øjeblik, hvor bufferen sendes, den går ind i kernel space af hypervisoren, og vi begynder at vente på det. Selvom, set fra VM'ens synspunkt, burde det straks vende tilbage. Følgelig betragtes denne tid som stjålet ifølge algoritmen for beregning af steal. Sandsynligvis kan der være andre mekanismer i denne situation (for eksempel behandling af andre sys calls), men de bør ikke adskille sig meget.

Scheduler mod højtydende VM'er. Når en VM lider mere af steal end de andre, hænger det netop sammen med scheduler'en. Jo mere en proces belaster processoren, jo hurtigere vil scheduler'en skubbe den ud, så de andre også kan få tid til at arbejde. Hvis VM'en forbruger lidt, ser den næsten ikke steal: dens proces har været stille og ventet, den skal have mere tid. Hvis VM'en genererer maksimal belastning på alle sine kerner, bliver den oftere skubbet ud af processoren og får ikke meget tid.

Endnu værre er det, når processer inden i en virtuel maskine prøver at få mere processorkraft, fordi de ikke kan håndtere databehandlingen. Så vil operativsystemet på hypervisoren, ved hjælp af ærlig optimering, give mindre og mindre processortid. Denne proces sker lavineagtigt, og steal-parameteren stiger til himmels, selvom de andre virtuelle maskiner knap bemærker det. Jo flere kerner, jo værre for den maskine, der rammes. Kort sagt, de mest belastede virtuelle maskiner med mange kerner lider mest.

Lav LA, men der er steal. Hvis LA er cirka 0,7 (dvs. hypervisoren virker underbelastet), men der observeres steal i enkelte virtuelle maskiner:

  • Den tidligere beskrevne situation med para-virtualisering. Den virtuelle maskine kan modtage metrikker, der indikerer steal, selvom alt ser fint ud på hypervisoren. Ifølge vores eksperimenter overstiger sådan steal ikke 10 % og bør ikke have væsentlig indflydelse på ydeevnen for applikationerne inden i den virtuelle maskine.
  • Parameteren LA betragtes forkert. Mere præcist, den betragtes korrekt på ethvert givet tidspunkt, men når den gennemsnitlige for en minut beregnes, bliver den undervurderet. For eksempel, hvis en virtuel maskine i en tredjedel af hypervisoren bruger alle sine processorer i præcis et halvt minut, vil LA for hypervisoren i løbet af et minut være 0,15; fire sådanne virtuelle maskiner, der arbejder samtidig, giver 0,6. Og det faktum, at der var et voldsomt steal på hver af dem på 25 % i et halvt minut, vil ikke kunne hentes.
  • Igen på grund af schedulerens beslutning om, at nogen spiser for meget, og at denne person skal vente. Imens vil jeg skifte kontekst, behandle interrupts og tage mig af andre vigtige systemopgaver. Som resultat ser nogle virtuelle maskiner ingen problemer, mens andre oplever alvorlig nedgang i ydeevnen.

4. Andre forvrængninger

Der er også en million andre årsager til forvrængninger i den ærlige givelse af processortid på en virtuel maskine. For eksempel skaber hyper-threading og NUMA komplikationer i beregningerne. De forvirrer valget af kerne til udførelse af processen, fordi scheduleren bruger koefficienter - vægte, der gør beregningen endnu vanskeligere ved kontekstskift.

Der er forvrængninger på grund af teknologier som turbo boost eller omvendt, energibesparende tilstande, som ved beregningen af udnyttelse kunstigt kan hæve eller sænke frekvensen eller endda tidskvanten på serveren. Aktivering af turbo boost reducerer ydelsen af en CPU-tråd på grund af øget ydelse fra en anden. På dette tidspunkt transmitteres oplysninger om den aktuelle processorfremsening ikke til den virtuelle maskine, og den tror, at dens tid bliver stjålet (for eksempel, hvis den bad om 2 GHz, men fik halvdelen).

Generelt kan der være mange årsager til forvrængninger. I et specifikt system kan du opdage noget andet. Det er bedst at starte med de bøger, som jeg har givet links til ovenfor, og at tage statistikker fra hypervisoren ved hjælp af værktøjer som perf, sysdig, systemtap, af hvilke der er snesevis.

5. Konklusioner

  1. En vis mængde steal kan opstå på grund af paravirtualisering, og det kan betragtes som normalt. På internettet siger de, at denne værdi kan være mellem 5-10 %. Det afhænger af de applikationer, der kører i den virtuelle maskine, og hvilken belastning de giver til deres fysiske enheder. Her er det vigtigt at være opmærksom på, hvordan applikationerne klarer sig inden i de virtuelle maskiner.
  2. Forholdet mellem belastningen på hypervisoren og steal inde i den virtuelle maskine er ikke altid entydigt sammenhængende, og begge vurderinger af steal kan være forkerte i specifikke situationer under forskellige belastninger.
  3. Planlæggeren er ikke venlig overfor processer, der beder meget. Den prøver at give mindre til dem, der beder om mere. Store virtuelle maskiner er en plage.
  4. En lille mængde steal kan være normalt og uden paravirtualisering (under hensyntagen til belastningen inden i den virtuelle maskine, naboernes belastningskarakteristika, fordeling af belastningen over tråde og andre faktorer).
  5. Hvis du vil finde ud af steal i et specifikt system, er du nødt til at undersøge forskellige muligheder, indsamle målinger, grundigt analysere dem og tænke over, hvordan man jævnt fordeler belastningen. Der kan være afvigelser fra alle tilfælde, som skal bekræftes eksperimentelt eller undersøges i kernen debugger.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster