Stjel: hvem som stjeler CPU-tid fra virtuelle maskiner

Stjel: hvem som stjeler CPU-tid fra virtuelle maskiner

Hallo! Jeg vil fortelle deg på en enkel måte om mekanikken ved å stjele inne i virtuelle maskiner og om noen ikke-åpenbare artefakter som vi klarte å finne ut under forskningen, som jeg måtte dykke ned i som teknisk direktør for en skyplattform Mail.ru skyløsninger. Plattformen kjører på KVM.

CPU-tyveri er tiden hvor den virtuelle maskinen ikke mottar prosessorressurser for utførelse. Denne tiden telles kun i gjesteoperativsystemer i virtualiseringsmiljøer. Årsakene til hvor disse mest tildelte ressursene går, som i livet, er svært vage. Men vi bestemte oss for å finne ut av det, og gjennomførte til og med en rekke eksperimenter. Det er ikke det at vi nå vet alt om å stjele, men vi skal fortelle deg noe interessant nå.

1. Hva er stjele

Så stjele er en beregning som indikerer mangel på prosessortid for prosesser inne i en virtuell maskin. Som beskrevet i KVM-kjerneoppdateringenStealth er tiden hvor hypervisoren utfører andre prosesser på verts-OSet selv om den har satt den virtuelle maskinprosessen i kø for utførelse. Det vil si at tyveri beregnes som differansen mellom tidspunktet da prosessen er klar til å utføres og tiden da prosessen er tildelt prosessortid.

Den virtuelle maskinkjernen mottar stjelemetrikken fra hypervisoren. Samtidig spesifiserer ikke hypervisoren nøyaktig hvilke andre prosesser den kjører, den sier bare "mens jeg er opptatt, kan jeg ikke gi deg tid." På KVM er støtte for stjeleberegning lagt til lapper. Det er to hovedpunkter her:

  • Den virtuelle maskinen lærer om å stjele fra hypervisoren. Det vil si, fra et tapssynspunkt, for prosesser på selve den virtuelle maskinen er dette en indirekte måling som kan være gjenstand for ulike forvrengninger.
  • Hypervisoren deler ikke informasjon med den virtuelle maskinen om hva annet den gjør - hovedsaken er at den ikke bruker tid på det. På grunn av dette kan ikke den virtuelle maskinen i seg selv oppdage forvrengninger i stjeleindikatoren, noe som kan vurderes ut fra arten av konkurrerende prosesser.

2. Hva påvirker stjele

2.1. Stjele beregning

I hovedsak beregnes tyveri omtrent det samme som normal CPU-brukstid. Det er ikke mye informasjon om hvordan resirkulering vurderes. Sannsynligvis fordi de fleste anser dette spørsmålet som åpenbart. Men det er også fallgruver her. For å gjøre deg kjent med denne prosessen kan du lese artikkel av Brendan Gregg: du vil lære om mange nyanser når du beregner utnyttelse og om situasjoner når denne beregningen vil være feil av følgende grunner:

  • Prosessoren overopphetes, noe som får sykluser til å hoppe over.
  • Aktiver/deaktiver turboboost, som endrer prosessorens klokkehastighet.
  • En endring i lengden på tidsstykket som oppstår ved bruk av prosessorstrømsparende teknologier som SpeedStep.
  • Problemet med å beregne gjennomsnittet: å estimere ett minutts utnyttelse til 80 % kan skjule en kortsiktig utbrudd på 100 %.
  • En spinnlås fører til at prosessoren blir gjenvunnet, men brukerprosessen ser ingen fremgang i utførelsen. Som et resultat vil den beregnede prosessorutnyttelsen av prosessen være hundre prosent, selv om prosessen ikke fysisk vil forbruke prosessortid.

Jeg har ikke funnet en artikkel som beskriver en lignende beregning for stjele (hvis du vet, del den i kommentarene). Men etter kildekoden å dømme er beregningsmekanismen den samme som for resirkulering. Enda en teller legges til i kjernen, direkte for KVM-prosessen (virtuell maskinprosess), som teller varigheten av KVM-prosessen som venter på CPU-tid. Telleren henter informasjon om prosessoren fra spesifikasjonen og sjekker om alle dens tikker blir brukt av den virtuelle maskinprosessen. Hvis det er alt, antar vi at prosessoren bare var opptatt med den virtuelle maskinprosessen. Ellers informerer vi om at prosessoren gjorde noe annet, stjele dukket opp.

Prosessen med tyvetelling er gjenstand for de samme problemene som vanlig gjenvinningstelling. For ikke å si at slike problemer dukker opp ofte, men de ser nedslående ut.

2.2. Typer virtualisering på KVM

Grovt sett er det tre typer virtualisering, som alle støttes av KVM. Mekanismen for tyveri kan avhenge av typen virtualisering.

oversettelse. I dette tilfellet skjer driften av det virtuelle maskinoperativsystemet med fysiske hypervisorenheter omtrent slik:

  1. Gjesteoperativsystemet sender en kommando til gjesteenheten.
  2. Gjesteenhetsdriveren mottar kommandoen, genererer en forespørsel om enhetens BIOS og sender den til hypervisoren.
  3. Hypervisor-prosessen oversetter kommando til kommando for den fysiske enheten, noe som gjør den blant annet sikrere.
  4. Den fysiske enhetsdriveren godtar den endrede kommandoen og sender den til selve den fysiske enheten.
  5. Resultatene av å utføre kommandoer går tilbake langs samme vei.

Fordelen med oversettelse er at den lar deg emulere hvilken som helst enhet og ikke krever spesiell forberedelse av operativsystemkjernen. Men du må betale for dette, først og fremst i fart.

Maskinvarevirtualisering. I dette tilfellet forstår enheten på maskinvarenivå kommandoer fra operativsystemet. Dette er den raskeste og beste måten. Men dessverre støttes det ikke av alle fysiske enheter, hypervisorer og gjesteoperativsystemer. For øyeblikket er de viktigste enhetene som støtter maskinvarevirtualisering prosessorer.

Paravirtualisering. Det vanligste alternativet for enhetsvirtualisering på KVM og generelt den vanligste virtualiseringsmodusen for gjesteoperativsystemer. Dets særegenhet er at arbeid med noen hypervisor-undersystemer (for eksempel med nettverket eller diskstabelen) eller tildeling av minnesider skjer ved bruk av hypervisor-API, uten å oversette kommandoer på lavt nivå. Ulempen med denne virtualiseringsmetoden er at kjernen for gjesteoperativsystemet må endres slik at den kan kommunisere med hypervisoren ved hjelp av denne APIen. Men dette løses vanligvis ved å installere spesielle drivere på gjesteoperativsystemet. I KVM kalles dette API virtio API.

Med paravirtualisering, sammenlignet med kringkasting, reduseres banen til den fysiske enheten betydelig ved å sende kommandoer direkte fra den virtuelle maskinen til hypervisorprosessen på verten. Dette lar deg fremskynde utførelsen av alle instruksjoner inne i den virtuelle maskinen. I KVM gjøres dette av virtio API, som bare fungerer for visse enheter, for eksempel et nettverk eller en diskadapter. Dette er grunnen til at virtio-drivere er installert inne i virtuelle maskiner.

Ulempen med denne akselerasjonen er at ikke alle prosesser som kjører inne i den virtuelle maskinen forblir inne i den. Dette skaper noen spesialeffekter som kan resultere i gyting ved stjeling. Jeg anbefaler å starte en detaljert studie av dette problemet med Et API for virtuell I/O: virtio.

2.3. "Fair" planlegging

En virtuell maskin på en hypervisor er faktisk en vanlig prosess som følger lovene for planlegging (ressursfordeling mellom prosesser) i Linux-kjernen, så la oss se nærmere på det.

Linux bruker den såkalte CFS, Completely Fair Scheduler, som har blitt standardplanleggeren siden kjernen 2.6.23. For å forstå denne algoritmen kan du lese Linux Kernel Architecture eller kildekoden. Essensen av CFS er å fordele prosessortid mellom prosesser avhengig av varigheten av deres utførelse. Jo mer CPU-tid en prosess krever, jo mindre CPU-tid mottar den. Dette sikrer at alle prosesser utføres "rettferdig" - slik at en prosess ikke hele tiden opptar alle prosessorer, og andre prosesser kan også kjøres.

Noen ganger fører dette paradigmet til interessante artefakter. Langvarige Linux-brukere husker sannsynligvis frysingen av en vanlig tekstredigerer på et skrivebord mens de kjører ressurskrevende applikasjoner som en kompilator. Dette skjedde fordi ikke-ressursintensive oppgaver i skrivebordsapplikasjoner konkurrerte med ressurskrevende oppgaver, for eksempel kompilatoren. CFS synes dette er urettferdig, så det stopper med jevne mellomrom tekstredigereren og lar prosessoren håndtere kompilatorens oppgaver. Dette ble korrigert ved hjelp av en mekanisme sched_autogroup, men mange andre funksjoner ved fordelingen av prosessortid mellom oppgavene gjensto. Egentlig er dette ikke en historie om hvor ille alt er i CFS, men et forsøk på å trekke oppmerksomhet til det faktum at "rettferdig" fordeling av prosessortid ikke er den mest trivielle oppgaven.

Et annet viktig punkt i planleggeren er forkjøpsrett. Dette er nødvendig for å sparke ut snikprosessen fra prosessoren og la andre jobbe. Utkastingsprosessen kalles kontekstbytte. I dette tilfellet er hele konteksten til oppgaven bevart: tilstanden til stabelen, registre, etc., hvoretter prosessen sendes til å vente, og en annen tar sin plass. Dette er en kostbar operasjon for operativsystemet og brukes sjelden, men det er ingenting iboende galt med det. Hyppig kontekstbytte kan indikere et problem i operativsystemet, men vanligvis er det kontinuerlig og indikerer ikke noe spesielt.

En så lang historie er nødvendig for å forklare ett faktum: jo mer prosessorressurser en prosess prøver å forbruke i en ærlig Linux-planlegger, jo raskere vil den bli stoppet slik at andre prosesser også kan fungere. Om dette er riktig eller ikke er et komplekst spørsmål som kan løses ulikt under ulike belastninger. I Windows, inntil nylig, var planleggeren fokusert på prioritert behandling av skrivebordsapplikasjoner, noe som kan føre til at bakgrunnsprosesser fryser. Sun Solaris hadde fem forskjellige klasser med planleggere. Da vi lanserte virtualisering, la vi til en sjette, Planlegger for rettferdig andel, fordi de forrige fem ikke fungerte tilstrekkelig med Solaris Zones-virtualisering. Jeg anbefaler å starte en detaljert studie av dette problemet med bøker som Solaris Internals: Solaris 10 og OpenSolaris Kernel Architecture eller Forstå Linux-kjernen.

2.4. Hvordan overvåke tyveri?

Det er enkelt å overvåke tyveri inne i en virtuell maskin, som enhver annen prosessorberegning: du kan bruke et hvilket som helst verktøy for prosessorberegninger. Hovedsaken er at den virtuelle maskinen er på Linux. Av en eller annen grunn gir ikke Windows denne informasjonen til brukerne. 🙁

Stjel: hvem som stjeler CPU-tid fra virtuelle maskiner
Utgang av toppkommandoen: detaljer om prosessorbelastningen, i kolonnen lengst til høyre - stjel

Vanskeligheten oppstår når man prøver å få denne informasjonen fra hypervisoren. Du kan prøve å forutsi tyveri på vertsmaskinen, for eksempel ved å bruke parameteren Load Average (LA) - gjennomsnittsverdien av antall prosesser som venter i utførelseskøen. Metoden for å beregne denne parameteren er ikke enkel, men generelt, hvis LA normalisert med antall prosessortråder er mer enn 1, indikerer dette at Linux-serveren er overbelastet med noe.

Hva venter alle disse prosessene på? Det åpenbare svaret er prosessoren. Men svaret er ikke helt riktig, for noen ganger er prosessoren gratis, men LA går av skala. Huske hvordan NFS faller av og hvordan LA vokser. Det samme kan skje med en disk og andre inn-/utgangsenheter. Men faktisk kan prosesser vente på slutten av enhver lås, enten fysisk, assosiert med en I/O-enhet, eller logisk, for eksempel en mutex. Dette inkluderer også låsing på maskinvarenivå (samme respons fra disken), eller logikk (de såkalte låseprimitivene, som inkluderer en haug med enheter, mutex adaptive og spinn, semaforer, tilstandsvariabler, rw-låser, ipc-låser ...).

En annen funksjon ved LA er at det regnes som et operativsystemgjennomsnitt. For eksempel konkurrerer 100 prosesser om én fil, og deretter LA=50. En så stor verdi ser ut til å indikere at operativsystemet er dårlig. Men for annen skjevt skrevet kode kan dette være en normal tilstand, til tross for at bare den er dårlig, og andre prosesser i operativsystemet ikke lider.

På grunn av dette gjennomsnittet (og på ikke mindre enn et minutt), er det ikke den mest givende oppgaven å bestemme noe ved hjelp av LA-indikatoren, med svært usikre resultater i spesifikke tilfeller. Hvis du prøver å finne ut av det, vil du finne at artikler på Wikipedia og andre tilgjengelige ressurser kun beskriver de enkleste tilfellene, uten en dyp forklaring av prosessen. Jeg sender alle som er interessert, igjen, her til Brendan Gregg  - følg lenkene nedenfor. Hvem er for lat til å snakke engelsk - oversettelse av hans populære artikkel om LA.

3. Spesialeffekter

La oss nå se på de viktigste tilfellene av tyveri som vi møtte. Jeg vil fortelle deg hvordan de følger av alt det ovennevnte og hvordan de forholder seg til indikatorene på hypervisoren.

Resirkulering. Det enkleste og mest vanlige: hypervisoren har blitt gjenbrukt. Faktisk er det mange virtuelle maskiner som kjører, høyt prosessorforbruk inne i dem, mye konkurranse, LA-bruken er mer enn 1 (normalisert av prosessortråder). Alt inne i alle virtuelle maskiner bremser ned. Steal overført fra hypervisoren vokser også, det er nødvendig å omfordele lasten eller slå av noen. Generelt er alt logisk og forståelig.

Paravirtualisering vs. enkeltforekomster. Det er bare én virtuell maskin på hypervisoren; den bruker en liten del av den, men produserer en stor I/O-belastning, for eksempel på disk. Og fra et sted dukker det opp en liten stjålning i den, opptil 10% (som vist av flere eksperimenter).

Saken er interessant. Stjel dukker opp her nettopp på grunn av blokkering på nivå med paravirtualiserte drivere. Et avbrudd opprettes inne i den virtuelle maskinen, behandles av driveren og sendes til hypervisoren. På grunn av avbruddshåndteringen på hypervisoren ser det for den virtuelle maskinen ut som en sendt forespørsel, den er klar for utførelse og venter på prosessoren, men den får ikke prosessortid. Den virtuelle jenta tror at denne gangen er stjålet.

Dette skjer i det øyeblikket bufferen sendes, den går inn i kjernerommet til hypervisoren, og vi begynner å vente på det. Selv om han fra den virtuelle maskinens synspunkt bør returnere umiddelbart. Derfor, i henhold til stjeleberegningsalgoritmen, regnes denne tiden som stjålet. Mest sannsynlig kan det i denne situasjonen være andre mekanismer (for eksempel å behandle noen andre sys-anrop), men de bør ikke være mye annerledes.

Planlegger versus høyt belastede virtuelle maskiner. Når en virtuell maskin lider av å stjele mer enn andre, er dette på grunn av planleggeren. Jo mer en prosess laster prosessoren, jo raskere vil planleggeren sparke den ut slik at de andre også kan fungere. Hvis den virtuelle maskinen bruker lite, vil den neppe se stjele: prosessen satt ærlig og ventet, vi må gi den mer tid. Hvis en virtuell maskin produserer maksimal belastning på alle kjernene, blir den ofte kastet ut av prosessoren og de prøver å ikke gi den mye tid.

Det er enda verre når prosesser inne i den virtuelle maskinen prøver å få mer prosessor fordi de ikke kan takle databehandling. Da vil operativsystemet på hypervisoren, på grunn av ærlig optimalisering, gi mindre og mindre prosessortid. Denne prosessen skjer som et snøskred, og stjele hopper til himmelen, selv om andre virtuelle maskiner kanskje knapt legger merke til det. Og jo flere kjerner, jo verre er den berørte maskinen. Kort sagt, høyt belastede virtuelle maskiner med mange kjerner lider mest.

Lavt LA, men det er tyveri. Hvis LA er omtrent 0,7 (det vil si hypervisoren ser ut til å være underbelastet), men tyveri observeres inne i individuelle virtuelle maskiner:

  • Alternativet med paravirtualisering er allerede beskrevet ovenfor. Den virtuelle maskinen kan motta beregninger som indikerer tyveri, selv om hypervisoren er fin. I følge resultatene av eksperimentene våre overstiger ikke dette stjelealternativet 10 % og bør ikke ha en betydelig innvirkning på ytelsen til applikasjoner inne i den virtuelle maskinen.
  • LA-parameteren er beregnet feil. Mer presist, i hvert spesifikke øyeblikk beregnes det riktig, men når gjennomsnittet over ett minutt viser seg å være undervurdert. For eksempel, hvis én virtuell maskin per tredjedel av hypervisoren bruker alle prosessorene i nøyaktig et halvt minutt, vil LA per minutt på hypervisoren være 0,15; fire slike virtuelle maskiner som jobber samtidig vil gi 0,6. Og det faktum at det i et halvt minutt på hver av dem var en vill stjele på 25 % ifølge LA-indikatoren kan ikke lenger trekkes ut.
  • Igjen, på grunn av planleggeren som bestemte at noen spiste for mye og lot vedkommende vente. I mellomtiden vil jeg bytte kontekst, håndtere avbrudd og ta meg av andre viktige systemting. Som et resultat ser noen virtuelle maskiner ingen problemer, mens andre opplever alvorlig ytelsesforringelse.

4. Andre forvrengninger

Det er en million flere grunner til å forvrenge rettferdig avkastning av prosessortid på en virtuell maskin. For eksempel introduserer hyperthreading og NUMA vanskeligheter i beregninger. De forvirrer fullstendig valget av kjerne for å utføre prosessen, fordi planleggeren bruker koeffisienter - vekter, som gjør beregningen enda vanskeligere når du bytter kontekst.

Det er forvrengninger på grunn av teknologier som turbo boost eller omvendt energisparemodus, som ved beregning av utnyttelse kunstig kan øke eller redusere frekvensen eller til og med tidsdelen på serveren. Aktivering av turbo-boost reduserer ytelsen til én prosessortråd på grunn av en økning i ytelsen til en annen. For øyeblikket overføres ikke informasjon om gjeldende prosessorfrekvens til den virtuelle maskinen, og den tror at noen stjeler tiden sin (for eksempel ba den om 2 GHz, men mottok halvparten).

Generelt kan det være mange årsaker til forvrengning. Du kan finne noe annet på et bestemt system. Det er bedre å starte med bøkene som jeg ga lenker til ovenfor, og hente statistikk fra hypervisoren ved å bruke verktøy som perf, sysdig, systemtap, hvorav dusinvis.

5. Konklusjoner

  1. En viss mengde stjeling kan forekomme på grunn av paravirtualisering, og det kan betraktes som normalt. De skriver på Internett at denne verdien kan være 5-10%. Avhenger av applikasjonene inne i den virtuelle maskinen og belastningen den legger på sine fysiske enheter. Her er det viktig å være oppmerksom på hvordan applikasjoner føles inne i virtuelle maskiner.
  2. Forholdet mellom belastningen på hypervisoren og tyveriet inne i den virtuelle maskinen er ikke alltid tydelig relatert; begge estimatene for tyveri kan være feilaktige i spesifikke situasjoner under forskjellige belastninger.
  3. Planleggeren har en dårlig holdning til prosesser som spør mye. Han prøver å gi mindre til de som ber om mer. Store virtuelle maskiner er onde.
  4. Litt tyveri kan være normen selv uten paravirtualisering (som tar hensyn til belastningen inne i den virtuelle maskinen, egenskapene til belastningen til naboer, lastfordeling på tvers av tråder og andre faktorer).
  5. Hvis du vil finne ut å stjele i et spesifikt system, må du utforske ulike alternativer, samle beregninger, analysere dem nøye og tenke på hvordan du kan fordele belastningen jevnt. Avvik fra alle tilfeller er mulig, som må bekreftes eksperimentelt eller ses på i kjernefeilsøkeren.

Kilde: www.habr.com

Legg til en kommentar