Wer stiehlt die virtuelle CPU-Zeit?



Hallo! In diesem Artikel möchte ich Laien erklären, wie Steal in VMs auftritt, und Ihnen einige der weniger offensichtlichen Artefakte erläutern, die wir bei der Recherche zu dem Thema gefunden haben, an dem ich als CTO der Mail beteiligt war. com Cloud Solutions- Plattform. Auf der Plattform wird KVM ausgeführt.

Die CPU-Diebstahlzeit ist die Zeit, in der eine VM nicht die für den Betrieb erforderlichen Ressourcen erhält. Diese Zeit kann nur in einem Gastbetriebssystem in Virtualisierungsumgebungen berechnet werden. Es ist äußerst unklar, wo die zugewiesenen Ressourcen verloren gehen, genau wie in realen Situationen. Wir haben uns jedoch entschlossen, es herauszufinden, und wir haben sogar eine Reihe von Tests durchgeführt, um dies zu tun. Das heißt nicht, dass wir alles über Stehlen wissen , aber es gibt einige faszinierende Dinge, die wir gerne mit Ihnen teilen möchten.

1. Was ist stehlen ?


Steal ist eine Metrik, die auf einen Mangel an CPU-Zeit für VM-Prozesse hinweist. Wie im KVM-Kernel-Patch beschrieben , ist Steal die Zeit, die ein Hypervisor damit verbringt, andere Prozesse in einem Host-Betriebssystem auszuführen, während sich der VM-Prozess in einer Ausführungswarteschlange befindet. Mit anderen Worten, stehlen wird als Differenz zwischen dem Moment, in dem ein Prozess zur Ausführung bereit ist, und dem Moment, in dem dem Prozess CPU-Zeit zugewiesen wird, berechnet.

Der VM-Kernel erhält die Steal- Metrik vom Hypervisor. Der Hypervisor gibt nicht an, welche Prozesse ausgeführt werden. Es heißt nur: "Ich bin beschäftigt und kann Ihnen keine Zeit zuweisen." In einer KVM wird die Diebstahlberechnung in Patches unterstützt . Hierzu gibt es zwei Hauptpunkte:

  • Eine VM lernt vom Hypervisor, wie man stiehlt . Dies bedeutet, dass Steal in Bezug auf Verluste eine indirekte Messung ist, die auf verschiedene Weise verzerrt werden kann.
  • Der Hypervisor teilt den VM-Informationen nicht mit, womit er beschäftigt ist. Der wichtigste Punkt ist, dass ihm keine Zeit zugewiesen wird. Die VM selbst kann daher keine Verzerrungen in der Steal- Metrik erkennen , die durch die Art der konkurrierenden Prozesse geschätzt werden könnten.

2. Was beeinflusst stehlen ?


2.1. Steal berechnen


Im Wesentlichen wird Steal mehr oder weniger auf die gleiche Weise berechnet wie die CPU-Auslastungszeit. Es gibt nicht viele Informationen darüber, wie die Auslastung berechnet wird. Das liegt wahrscheinlich daran, dass die meisten Profis denken, dass es offensichtlich ist. Es gibt jedoch einige Fallstricke. Der Prozess wird in einem Artikel von Brendann Gregg beschrieben . Er diskutiert eine ganze Reihe von Nuancen in Bezug auf die Berechnung der Auslastung und Szenarien, in denen die Berechnung falsch sein wird:

  • CPU überhitzt und drosselt.
  • Ein- und Ausschalten des Turbo Boost führt zu einer Änderung der CPU-Taktrate.
  • Die Zeitscheibenänderung, die auftritt, wenn CPU-Energiespartechnologien, z. B. SpeedStep, verwendet werden.
  • Probleme bei der Berechnung von Durchschnittswerten: Die Messung der Auslastung für eine Minute bei 80% Leistung könnte einen kurzfristigen Anstieg um 100% verbergen.
  • Ein Spinlock, der zu einem Szenario führt, in dem der Prozessor verwendet wird, der Benutzerprozess jedoch nicht fortschreitet. Infolgedessen beträgt die berechnete CPU-Auslastung 100%, der Prozess verbraucht jedoch keine CPU-Zeit.

Ich habe keine Artikel gefunden, die solche Berechnungen von Diebstahl beschreiben (wenn Sie welche kennen, teilen Sie sie bitte im Kommentarbereich mit). Wie Sie dem Quellcode entnehmen können, ist der Berechnungsmechanismus der gleiche wie für die Verwendung. Der einzige Unterschied besteht darin, dass ein weiterer Zähler speziell für den KVM-Prozess (VM-Prozess) hinzugefügt wird, der berechnet, wie lange der KVM-Prozess auf die CPU-Zeit gewartet hat. Der Zähler entnimmt Daten zur CPU aus seiner Spezifikation und prüft, ob alle seine Ticks vom VM-Prozess verwendet werden. Wenn alle Ticks verwendet werden, war die CPU nur mit dem VM-Prozess beschäftigt. Ansonsten wissen wir, dass die CPU etwas anderes getan hat und stehlen erscheint.

Der Prozess, mit dem der Diebstahl berechnet wird, unterliegt denselben Problemen wie die reguläre Berechnung der Auslastung. Diese Probleme sind nicht so häufig, aber sie können ziemlich verwirrend erscheinen.

2.2. Arten der KVM-Virtualisierung


Im Allgemeinen gibt es drei Arten der Virtualisierung, die alle von einer KVM unterstützt werden. Der Mechanismus, mit dem gestohlen wird, kann von der Art der Virtualisierung abhängen.

Übersetzung In diesem Fall funktioniert das VM-Betriebssystem auf folgende Weise mit physischen Hypervisor-Geräten:

  1. Das Gastbetriebssystem sendet einen Befehl an sein Gastgerät.
  2. Der Gastgerätetreiber akzeptiert den Befehl, erstellt eine BIOS-Geräteanforderung und sendet den Befehl an den Hypervisor.
  3. Der Hypervisor-Prozess übersetzt den Befehl in einen Befehl für ein physisches Gerät, wodurch er unter anderem sicherer wird.
  4. Der physische Gerätetreiber akzeptiert den geänderten Befehl und leitet ihn an das physische Gerät selbst weiter.
  5. Die Ausführungsergebnisse des Befehls kehren auf demselben Pfad zurück.

Der Vorteil der Übersetzung besteht darin, dass wir jedes Gerät emulieren können und keine spezielle Vorbereitung des Betriebssystemkerns erforderlich ist. Dies geht jedoch zu Lasten der Leistung.

Hardware-Virtualisierung. In diesem Fall empfängt ein Gerät Befehle vom Betriebssystem auf Hardwareebene. Dies ist die schnellste und insgesamt beste Methode. Leider unterstützen dies nicht alle physischen Geräte, Hypervisoren und Gastbetriebssysteme. Derzeit sind die Hauptgeräte, die die Hardwarevirtualisierung unterstützen, CPUs.

Paravirtualisierung. Die häufigste Option für die Gerätevirtualisierung auf einer KVM und die am weitesten verbreitete Art der Virtualisierung für Gastbetriebssysteme. Das Hauptmerkmal besteht darin, dass es mit einigen Hypervisor-Subsystemen (z. B. Netzwerk- oder Laufwerksstapel) funktioniert und Speicherseiten mithilfe einer Hypervisor-API zuweist, ohne Befehle auf niedriger Ebene zu übersetzen. Der Nachteil dieser Virtualisierungsmethode ist die Notwendigkeit, den Kernel des Gastbetriebssystems zu ändern, um die Interaktion mit dem Hypervisor unter Verwendung derselben API zu ermöglichen. Die häufigste Lösung für dieses Problem besteht darin, spezielle Treiber im Gastbetriebssystem zu installieren. In einer KVM wird diese API als Virtio-API bezeichnet .

Bei Verwendung der Paravirtualisierung ist der Pfad zum physischen Gerät viel kürzer als in Fällen, in denen die Übersetzung verwendet wird, da Befehle direkt von der VM an den Hypervisor-Prozess auf dem Host gesendet werden. Dies beschleunigt die Ausführung aller Anweisungen innerhalb der VM. In einer KVM ist dafür eine virtio-API verantwortlich. Es funktioniert nur für einige Geräte wie Netzwerk- und Laufwerksadapter. Aus diesem Grund werden virtio-Treiber auf VMs installiert.

Die Kehrseite einer solchen Beschleunigung ist, dass nicht alle in einer VM ausgeführten Prozesse innerhalb der VM bleiben. Dies führt zu einer Reihe von Effekten, die zu Diebstahl führen können. Wenn Sie mehr erfahren möchten, beginnen Sie mit einer API für virtuelle E / A: virtio .

2.3. Faire Planung


Eine VM auf einem Hypervisor ist in der Tat ein regulärer Prozess, der in einem Linux-Kernel Planungsgesetzen (Ressourcenverteilung zwischen Prozessen) unterliegt. Schauen wir uns das genauer an.

Linux verwendet den sogenannten CFS (Completely Fair Scheduler), der mit Kernel 2.6.23 zum Standard wurde. Lesen Sie die Linux-Kernel-Architektur oder den Quellcode, um einen Überblick über diesen Algorithmus zu erhalten. Die Essenz von CFS liegt in der Verteilung der CPU-Zeit zwischen Prozessen, abhängig von ihrer Laufzeit. Je mehr CPU-Zeit ein Prozess benötigt, desto weniger CPU-Zeit wird benötigt. Dies garantiert die "faire" Ausführung aller Prozesse und hilft zu vermeiden, dass ein Prozess ständig alle Prozessoren beansprucht, und ermöglicht auch die Ausführung anderer Prozesse.

Manchmal führt dieses Paradigma zu interessanten Artefakten. Langjährige Linux-Benutzer werden sich zweifellos daran erinnern, wie ein normaler Texteditor auf dem Desktop einfrieren würde, wenn ressourcenintensive Anwendungen wie ein Compiler ausgeführt werden. Dies geschah, weil ressourcenarme Aufgaben wie Desktopanwendungen mit Aufgaben konkurrierten, die viele Ressourcen verwendeten, wie z. B. ein Compiler. CFS hält dies für unfair und stoppt daher von Zeit zu Zeit den Texteditor und lässt die CPU die Compiler-Aufgaben verarbeiten. Dies wurde mit dem Mechanismus sched_autogroup behoben . Es gibt jedoch viele andere Besonderheiten der CPU-Zeitverteilung. In diesem Artikel geht es nicht wirklich darum, wie schlecht CFS ist. Es ist eher ein Versuch, die Aufmerksamkeit auf die Tatsache zu lenken, dass eine "faire" Verteilung der CPU-Zeit nicht die trivialste Aufgabe ist.

Ein weiterer wichtiger Aspekt eines Schedulers ist die Vorauszahlung. Dies ist erforderlich, um die CPU von überlasteten Prozessen zu befreien und anderen die Arbeit zu ermöglichen. Dies wird als Kontextumschaltung bezeichnet . Der gesamte Aufgabenkontext bleibt erhalten: Stapelstatus, Register usw. Danach muss der Prozess warten und wird durch einen anderen Prozess ersetzt. Dies ist eine teure Operation für ein Betriebssystem. Es wird selten benutzt, aber es ist überhaupt nicht schlecht. Häufiges Wechseln des Kontexts kann ein Indikator für ein Betriebssystemproblem sein, tritt jedoch normalerweise kontinuierlich auf und ist kein Anzeichen für ein bestimmtes Problem.

Dieser lange Diskurs war notwendig, um eine Tatsache zu erklären: In einem fairen Linux-Scheduler wird der Prozess umso schneller gestoppt, je mehr CPU-Ressourcen der Prozess verbraucht, damit andere Prozesse funktionieren können. Ob dies richtig ist oder nicht, ist eine komplexe Frage, und die Lösung ist je nach Belastung unterschiedlich. Bis vor kurzem priorisierte Windows Scheduler Desktop-Anwendungen, was zu langsameren Hintergrundprozessen führte. In Sun Solaris gab es fünf verschiedene Scheduler-Klassen. Bei der Einführung der Virtualisierung wurde ein weiterer hinzugefügt, der Fair Share Scheduler , da die anderen mit der Solaris Zones-Virtualisierung nicht ordnungsgemäß ausgeführt wurden. Um dies näher zu untersuchen, empfehle ich, mit Solaris Internals: Solaris 10 und OpenSolaris Kernel Architecture zu beginnen oder den Linux-Kernel zu verstehen .

2.4. Wie können wir den Diebstahl überwachen?


Wie bei jeder anderen CPU-Metrik ist es einfach, den Diebstahl innerhalb einer VM zu überwachen. Sie können jedes CPU-Metrik-Messwerkzeug verwenden. Die Hauptsache ist, dass die VM unter Linux sein muss. Aus irgendeinem Grund stellt Windows dem Benutzer solche Informationen nicht zur Verfügung. :(


Top-Ausgabe: Angabe der CPU-Auslastung mit Steal in der rechten Spalte

Beim Versuch, diese Informationen von einem Hypervisor abzurufen, werden die Dinge kompliziert. Sie können versuchen, Steal auf einem Host-Computer vorherzusagen, z. B. mit Load Average (LA). Dies ist der Durchschnittswert der Anzahl der Prozesse in der Ausführungswarteschlange. Die Berechnungsmethode für diesen Parameter ist nicht einfach. Wenn jedoch eine LA, die gemäß der Anzahl der CPU-Threads standardisiert wurde, größer als 1 ist, bedeutet dies, dass der Linux-Server überlastet ist.

Worauf warten all diese Prozesse? Offensichtlich die CPU. Diese Antwort ist jedoch nicht ganz richtig, da manchmal die CPU frei und die LA viel zu hoch ist. Denken Sie daran, dass NFS fällt und LA gleichzeitig steigt . Eine ähnliche Situation kann beim Laufwerk und anderen Ein- / Ausgabegeräten auftreten. Tatsächlich warten die Prozesse möglicherweise auf das Ende einer Sperre: physisch (bezogen auf Eingabe- / Ausgabegeräte) oder logisch (z. B. ein Mutex-Objekt). Gleiches gilt für Sperren auf Hardwareebene (z. B. Festplattenantwort) oder Sperren auf Logikebene (sogenannte "Sperrprimitive"), zu denen eine Reihe von Entitäten, Mutex Adaptive und Spin, Semaphoren, Bedingungsvariablen, RW-Sperren, gehören. IPC-Sperren ...).

Ein weiteres Merkmal von LA ist, dass es als Durchschnittswert innerhalb des Betriebssystems berechnet wird. Wenn beispielsweise 100 Prozesse um eine Datei konkurrieren, beträgt die LA 50. Diese große Anzahl lässt den Eindruck entstehen, dass dies für das Betriebssystem schlecht ist. Bei schlecht geschriebenem Code kann dies jedoch normal sein. Nur dieser spezifische Code wäre schlecht, und der Rest des Betriebssystems könnte in Ordnung sein.

Aufgrund dieser Mittelung (für weniger als eine Minute) ist es nicht die beste Idee, mithilfe eines LA etwas zu bestimmen, da dies in einigen Fällen zu äußerst mehrdeutigen Ergebnissen führen kann. Wenn Sie versuchen, mehr darüber herauszufinden, werden Sie feststellen, dass Wikipedia und andere verfügbare Ressourcen nur den einfachsten Fall beschreiben und der Prozess nicht im Detail beschrieben wird. Wenn Sie daran interessiert sind, besuchen Sie erneut Brendann Gregg und folgen Sie den Links.

3. Spezialeffekte


Kommen wir nun zu den Hauptfällen von Diebstahl , auf die wir gestoßen sind. Lassen Sie mich erklären, wie sie sich aus den oben genannten Ergebnissen ergeben und wie sie mit Hypervisor-Metriken korrelieren.

Überlastung. Der einfachste und häufigste Fall: Der Hypervisor wird überlastet. In der Tat ist bei vielen VMs, die viele CPU-Ressourcen ausführen und verbrauchen, die Konkurrenz hoch und die Auslastung gemäß LA größer als 1 (standardisiert gemäß CPU-Threads). Alles bleibt in allen VMs zurück. Der vom Hypervisor gesendete Diebstahl wächst ebenfalls. Sie müssen die Last neu verteilen oder etwas ausschalten. Im Großen und Ganzen ist das alles logisch und unkompliziert.

Paravirtualisierung gegen einzelne Instanzen. Es gibt nur eine VM auf einem Hypervisor. Die VM verbraucht einen kleinen Teil davon, bietet jedoch eine hohe Eingabe- / Ausgabelast, z. B. für ein Laufwerk. Unerwarteterweise tritt ein kleiner Diebstahl von weniger als 10% auf (wie einige der von uns durchgeführten Tests zeigen).

Dies ist ein merkwürdiger Fall. Hier wird Steal aufgrund von Sperren auf der Ebene der paravirtualisierten Geräte angezeigt. Innerhalb der VM wird ein Haltepunkt erstellt. Dies wird vom Treiber verarbeitet und geht an den Hypervisor. Aufgrund der Haltepunktverarbeitung auf dem Hypervisor sieht die VM dies als gesendete Anforderung. Es ist betriebsbereit und wartet auf die CPU, erhält jedoch keine CPU-Zeit. Die VM glaubt, dass die Zeit gestohlen wurde.

Dies geschieht, wenn der Puffer gesendet wird. Es geht in den Kernelbereich des Hypervisors und wir warten darauf. Aus Sicht der VM sollte sie sofort zurückkehren. Daher wird diese Zeit gemäß unserem Diebstahlberechnungsalgorithmus als gestohlen betrachtet. Es ist wahrscheinlich, dass andere Mechanismen daran beteiligt sind (z. B. die Verarbeitung anderer Systemaufrufe ), sie sollten sich jedoch nicht wesentlich unterscheiden.

Scheduler gegen hoch geladene VMs. Wenn eine VM mehr als die anderen stiehlt , ist dies direkt mit dem Scheduler verbunden. Je höher die Last ist, die ein Prozess auf eine CPU ausübt, desto schneller wird sie von einem Scheduler verworfen, damit andere Prozesse funktionieren können. Wenn die VM wenig verbraucht, wird sie fast nicht gestohlen. Sein Prozess hat nur gesessen und gewartet, und es muss mehr Zeit gegeben werden. Wenn die VM alle Kerne maximal belastet, wird der Prozess häufiger weggeworfen und der VM wird weniger Zeit eingeräumt.

Es ist noch schlimmer, wenn Prozesse innerhalb der VM versuchen, mehr CPU zu erhalten, weil sie die Daten nicht verarbeiten können. Dann bietet das Betriebssystem auf dem Hypervisor aufgrund der fairen Optimierung weniger CPU-Zeit. Dieser Prozess verarbeitet Schneebälle und stiehlt Wellen in die Höhe, während andere VMs dies möglicherweise nicht einmal bemerken. Je mehr Kerne vorhanden sind, desto schlimmer ist es für die unglückliche VM. Kurz gesagt, hoch ausgelastete VMs mit vielen Kernen leiden am meisten.

Low LA aber stehlen ist vorhanden. Wenn der LA ungefähr 0,7 beträgt (was bedeutet, dass der Hypervisor unterlastet zu sein scheint), aber einige VMs stehlen :

  • Es gilt das oben genannte Paravirtualisierungsbeispiel. Die VM empfängt möglicherweise Metriken, die auf Diebstahl hinweisen, während der Hypervisor keine Probleme hat. Nach den Ergebnissen unserer Tests überschreitet ein solcher Diebstahl in der Regel nicht 10% und hat keinen wesentlichen Einfluss auf die Anwendungsleistung innerhalb der VM.
  • Der LA-Parameter wurde falsch berechnet. Genauer gesagt wurde es zu einem bestimmten Zeitpunkt korrekt berechnet, aber bei der Mittelwertbildung ist es niedriger als es für eine Minute sein sollte. Wenn beispielsweise eine VM (ein Drittel des Hypervisors) 30 Sekunden lang alle CPUs verbraucht, beträgt die LA für eine Minute 0,15. Vier solcher VMs, die gleichzeitig arbeiten, ergeben einen Wert von 0,6. Basierend auf der LA könnten Sie nicht ableiten, dass der Diebstahl für 30 Sekunden für jeden von ihnen fast 25% betrug.
  • Dies geschah wiederum aufgrund des Planers, der entschied, dass jemand zu viel "aß" und ihn warten ließ. In der Zwischenzeit wird der Kontext gewechselt, Haltepunkte verarbeitet und andere wichtige Systemangelegenheiten behandelt. Infolgedessen treten bei einigen VMs keine Probleme auf, bei anderen treten erhebliche Leistungsverluste auf.

4. Andere Verzerrungen


Es gibt eine Million mögliche Gründe für eine Verzerrung der fairen CPU-Zeitzuweisung auf einer VM. Zum Beispiel erhöhen Hyperthreading und NUMA die Komplexität der Berechnungen. Sie erschweren die Auswahl des Kerns, der zum Ausführen eines Prozesses verwendet wird, da ein Scheduler Koeffizienten verwendet. das heißt Gewichte, die die Berechnungen beim Kontextwechsel noch komplizierter machen.

Es gibt Verzerrungen, die durch Technologien wie Turbo Boost oder den entgegengesetzten Energiesparmodus entstehen und die CPU-Kerngeschwindigkeit und sogar die Zeitscheibe künstlich erhöhen oder verringern können. Wenn Sie Turbo Boost aktivieren, wird die Produktivität eines CPU-Threads aufgrund einer Leistungssteigerung in einem anderen verringert. In diesem Moment werden keine Informationen zur aktuellen CPU-Taktrate an die VM gesendet, die denkt, dass jemand seine Zeit stiehlt (z. B. 2 GHz angefordert und halb so viel erhalten).

In der Tat kann es viele Gründe für Verzerrungen geben. Möglicherweise finden Sie in einem bestimmten System etwas ganz anderes. Ich empfehle, mit den oben verlinkten Büchern zu beginnen und Statistiken vom Hypervisor mit Tools wie perf, sysdig, systemtap und Dutzenden anderen zu erhalten .

5. Schlussfolgerungen


  1. Einige Steals können aufgrund von Paravirtualisierung auftreten und dies kann als normal angesehen werden. Online-Quellen sagen, dass dieser Wert 5-10% betragen kann. Dies hängt von der Anwendung in einer VM und der Belastung der physischen Geräte durch die VM ab. Es ist wichtig zu beachten, wie sich Anwendungen in einer VM anfühlen.
  2. Die Korrelation zwischen der Belastung des Hypervisors und dem Diebstahl innerhalb einer VM ist nicht immer sicher. Beide Diebstahlberechnungen können in einigen Fällen und mit unterschiedlichen Belastungen falsch sein.
  3. Scheduler bevorzugt keine Prozesse, die viele Ressourcen erfordern. Es versucht, denen, die mehr verlangen, weniger zu geben. Große Instanzen sind gemein.
  4. Ein kleiner Diebstahl kann auch ohne Paravirtualisierung normal sein (unter Berücksichtigung der Last innerhalb der VM, der Besonderheiten der Last der Nachbarn, der Verteilung der Last zwischen den Threads und anderer Faktoren).
  5. Wenn Sie den Diebstahl in einem bestimmten System berechnen möchten, untersuchen Sie die verschiedenen Möglichkeiten, sammeln Sie Metriken, analysieren Sie sie gründlich und überlegen Sie, wie Sie die Last fair verteilen können. Unabhängig davon kann es zu Abweichungen kommen, die mithilfe von Tests überprüft oder in einem Kernel-Debugger angezeigt werden müssen.

Source: https://habr.com/ru/post/de453140/


All Articles