Den Linux-OOM-Killer standardmäßig deaktivieren?

37

Der OOM-Killer unter Linux bringt von Zeit zu Zeit verschiedene Anwendungen durcheinander, und es scheint, dass auf der Kernel-Entwicklungsseite nicht wirklich viel getan wird, um dies zu verbessern. Wäre es nicht besser, als bewährte Methode beim Einrichten eines neuen Servers die Standardeinstellung für die Speicherüberbelegung umzukehren, dh sie auszuschalten ( vm.overcommit_memory=2), wenn Sie nicht wissen, dass Sie sie für Ihre spezielle Verwendung aktivieren möchten? Und was wären diese Anwendungsfälle, bei denen Sie wissen, dass Sie das Overcommitting durchführen möchten?

Als Bonus, da das Verhalten im Fall von vm.overcommit_memory=2von vm.overcommit_ratiound Swap Space abhängt , was wäre eine gute Faustregel, um die beiden letzteren so zu dimensionieren, dass das gesamte Setup vernünftig funktioniert?

Peter Eisentraut
quelle

Antworten:

63

Eine interessante Analogie (von http://lwn.net/Articles/104179/ ):

Eine Flugzeugfirma stellte fest, dass es billiger war, ihre Flugzeuge mit weniger Treibstoff an Bord zu fliegen. Die Flugzeuge wären leichter und würden weniger Treibstoff verbrauchen, und es würde Geld gespart. In seltenen Fällen war die Treibstoffmenge jedoch unzureichend und das Flugzeug stürzte ab. Dieses Problem wurde von den Ingenieuren des Unternehmens durch die Entwicklung eines speziellen OOF-Mechanismus (Out-of-Fuel) gelöst. In Notfällen wurde ein Passagier ausgewählt und aus dem Flugzeug geworfen. (Wenn nötig, wurde das Verfahren wiederholt.) Es wurde eine große Anzahl von Theorien entwickelt, und viele Veröffentlichungen widmeten sich dem Problem der richtigen Auswahl des auszustoßenden Opfers. Sollte das Opfer zufällig ausgewählt werden? Oder sollte man die schwerste Person wählen? Oder der älteste? Sollten Passagiere zahlen, um nicht ausgeworfen zu werden, damit das Opfer das Ärmste an Bord ist? Und wenn zum Beispiel die schwerste Person ausgewählt wurde, sollte es eine besondere Ausnahme geben, falls es sich um den Piloten handelte? Sollten Passagiere der ersten Klasse freigestellt werden? Jetzt, wo es den OOF-Mechanismus gab, wurde er von Zeit zu Zeit aktiviert und warf Passagiere aus, auch wenn kein Kraftstoffmangel bestand. Die Ingenieure untersuchen noch genau, wie diese Störung verursacht wird.

Und zog
quelle
11
Das hat mir sehr gut gefallen, danke, dass du es ausgegraben hast.
Nick Bolton
32

Der OOM-Killer kann nur dann Chaos anrichten, wenn Sie Ihr System überlastet haben. Nehmen Sie genügend Swap-Speicher in Anspruch und führen Sie keine Anwendungen aus, die plötzlich zu einem erheblichen RAM-Verbrauch führen, und Sie werden kein Problem haben.

Um Ihre Fragen gezielt zu beantworten:

  • Ich halte es nicht für eine gute Idee, das Overcommit im allgemeinen Fall auszuschalten. Nur sehr wenige Anwendungen sind für die ordnungsgemäße Verarbeitung von brk(2) (und den Wrappern, die sie verwenden, z. B. malloc(3)) geschrieben und geben einen Fehler zurück. Als ich bei meinem vorherigen Job damit experimentiert habe, war es für mich ein größerer Aufwand, alles in die Lage zu versetzen, um Speicherfehler zu beheben, als sich nur mit den Folgen eines OOM zu befassen (was in unserem Fall war weitaus schlimmer, als den gelegentlichen Dienst neu starten zu müssen, wenn ein OOM auftrat - wir mussten einen gesamten Cluster neu starten, da GFS ein dampfender Haufen von Fäkalien ist.
  • Sie möchten ein Overcommitting für jeden Prozess durchführen, der einen Overcommit für den Speicher ausführt. Die beiden häufigsten Schuldigen sind Apache und die JVM. Viele Apps tun dies jedoch mehr oder weniger. Sie denken , sie könnten in der Zukunft irgendwann viel Speicher benötigen, so dass sie einen großen Teil sofort greifen. Auf einem System mit Überlastungsschutz geht der Kernel auf "Meh, was auch immer, stört mich, wenn Sie tatsächlich auf diese Seiten schreiben möchten" und es passiert nichts Schlimmes. Auf einem Overcommit-Off-System sagt der Kernel "Nein, Sie können nicht so viel Speicher haben, wenn Sie irgendwann in der Zukunft darauf schreiben, bin ich entbeint, also kein Speicher für Sie!" und die Zuordnung schlägt fehl. Da nixDa draußen heißt es: "Oh, OK, kann ich diese kleinere Menge an Prozessdatensegmenten haben?", dann wird der Prozess entweder (a) mit einem Fehler wegen Speichermangel beendet oder (b) überprüft nicht den Rückkehrcode von malloc, denkt, es ist in Ordnung zu gehen und schreibt in einen ungültigen Speicherort, was einen Segfault verursacht. Zum Glück erledigt die JVM beim Start alle Vorbereitungen (Ihre JVM wird also entweder gestartet oder stirbt sofort, was Sie normalerweise bemerken), aber Apache erledigt alles mit jedem neuen Kind, was aufregende Auswirkungen in der Produktion haben kann (nicht reproduzierbare "Nicht-Bearbeitung von Verbindungen") "Arten von Aufregung).
  • Ich möchte mein overcommit_ratio nicht höher als die Standardeinstellung von 50% einstellen. Auch von meinen Tests, obwohl es bis etwa 80 oder 90 könnte Einstellung Klang wie eine coole Idee, erfordert der Kernel große Brocken Speicher zu ungünstigen Zeiten, und ein voll ausgelastetes System mit einem hohen Verhältnis overcommit ist wahrscheinlich nicht ausreichend Ersatzspeicher haben , wenn der Kernel es braucht (was zu Angst, Pest und Hoppla führt). Wenn Sie also mit Overcommit spielen, wird ein neuer, noch unterhaltsamerer Fehlermodus eingeführt - anstatt einfach den Prozess neu zu starten, der bei unzureichendem Arbeitsspeicher unterbrochen wurde. Jetzt stürzt Ihr Computer ab, was zu einem Ausfall von allem auf dem Computer führt. GENIAL!
  • Der Swap Space in einem System ohne Overcommit hängt davon ab, wie viel angeforderter, aber nicht genutzter Speicher Ihre Anwendungen benötigen, sowie von einer gesunden Sicherheitsmarge. Das Herausfinden, was in einem bestimmten Fall benötigt wird, bleibt dem Leser als Übung.

Grundsätzlich habe ich die Erfahrung gemacht, dass das Ausschalten von Overcommit ein schönes Experiment ist, das in der Praxis selten so gut funktioniert, wie es sich theoretisch anhört. Dies entspricht gut meinen Erfahrungen mit anderen Tunables im Kernel - die Linux-Kernel-Entwickler sind fast immer schlauer als Sie, und die Standardeinstellungen funktionieren in den allermeisten Fällen am besten . Lassen Sie sie in Ruhe, und suchen Sie stattdessen, welcher Prozess das Leck hat, und beheben Sie es.

womble
quelle
2
Ich möchte nicht, dass mein Sicherungsvorgang abgebrochen wird, weil jemand meinen Webserver in Betrieb nimmt. Ausnahmen sind in Ordnung, aber die Standardeinstellung sollte Sicherheit und Konsistenz sein. Optimierungen wie OOM sollten IMHO manuell aktiviert werden. Es ist wie beim Codieren, Sie codieren sauber und optimieren dann. Over-Commit ist eine nette Funktion, sollte aber nicht die Standardeinstellung sein.
Aki
1
Wenn Sie nicht möchten, dass Ihr Sicherungsvorgang beendet wird, weil jemand Ihren Webserver mit DoS bearbeitet, konfigurieren Sie Ihren Webserver nicht so, dass ein DoS dazu führen kann, dass die Ressourcen auf dem System überlastet werden.
womble
Ich habe 8 GB RAM und nur Firefox und eine virtuelle Maschine führt manchmal dazu, dass der OOM-Killer die VM tötet. Beim Kompilieren von Unreal Engine 4 benötigt jeder Clang-Aufruf 1 ~ 1,5 GB Speicher und OOM-Killer tötet immer wieder einen. Jetzt bin ich im Allgemeinen damit einverstanden, ohne den OOM-Killer würden sie wahrscheinlich sowieso einen Fehler machen. Es ist nur so, dass jedes Mal, wenn OOM Killer einen Prozess beenden möchte, mein System 10 Minuten lang einfriert, bevor der fehlerhafte Prozess tatsächlich beendet wird. Bug vielleicht? Höchstwahrscheinlich. Will ich es Definitiv nicht. Und das ist der Grund, warum man den OOM-Killer deaktivieren möchte.
Shahbaz
1
Wenn Sie all das auf einer Box machen, benötigen Sie mehr RAM, und das Deaktivieren von Overcommit wird es nur noch schlimmer machen.
Ben Lutgens
6

Hmm, ich bin nicht ganz überzeugt von Argumenten für Overcommit und OOM-Killer ... Wenn Womble schreibt,

"Der OOM-Killer ist nur dann verheerend, wenn Sie Ihr System überlastet haben. Geben Sie ihm genügend Swap, und führen Sie keine Anwendungen aus, die sich plötzlich dazu entschließen, große Mengen an RAM zu verbrauchen, und Sie werden kein Problem haben."

Er beschreibt ein Umgebungsszenario, in dem Overcommit und OOM-Killer nicht erzwungen werden oder nicht "wirklich" agieren (wenn allen Anwendungen nach Bedarf Speicher zugewiesen wird und genügend virtueller Speicher zugewiesen werden kann, folgen die Speicherschreibvorgänge genau den Speicherzuweisungen ohne Fehler, so dass wir nicht wirklich über ein überlastetes System sprechen könnten, selbst wenn eine Überlastungsstrategie aktiviert wäre). Es geht um eine implizite Annahme, dass Overcommit und OOM-Killer am besten funktionieren, wenn ihre Intervention nicht benötigt wird. Soweit ich das beurteilen kann (und ich gebe zu, dass ich nicht viel sagen kann ...), teilen das die meisten Befürworter dieser Strategie. Wenn ich mich außerdem auf Anwendungen mit bestimmten Verhaltensweisen beziehe, wenn Speicher vorab zugewiesen wird, denke ich, dass eine bestimmte Behandlung auf Verteilungsebene optimiert werden könnte, anstatt eine Standardeinstellung zu haben.

Für welche Anliegen der JVM, na ja, es ist eine virtuelle Maschine zu einem gewissen Grad muss es alle Ressourcen zuzuteilen es muss beim Start, so kann es seine ‚falsche‘ Umgebung für seine Anwendungen erstellen, und halten Sie die verfügbaren Ressourcen vom Host getrennt Umwelt, so weit wie möglich. Daher ist es möglicherweise vorzuziehen, wenn der Startvorgang fehlschlägt, anstatt nach einer bestimmten Zeit als Folge eines „externen“ OOM-Zustands (verursacht durch einen Overcommit / OOM-Killer / was auch immer) oder wenn ein solcher Zustand seine eigenen Probleme verursacht Interne OOM-Handlungsstrategien (im Allgemeinen sollte eine VM die erforderlichen Ressourcen von Anfang an erhalten und das Hostsystem sollte sie bis zum Ende ignorieren), so wie es eine beliebige Menge an physischem RAM, die mit einer Grafikkarte geteilt wird, niemals ist - und nicht sein kann - vom Betriebssystem berührt).

In Bezug auf Apache bezweifle ich, dass es besser ist, den gesamten Server gelegentlich zu töten und neu zu starten, als zuzulassen, dass ein einzelnes Kind zusammen mit einer einzelnen Verbindung von Anfang an (= der des Kindes / der Verbindung) ausfällt (als wäre es eine ganz neue Instanz von die JVM, die nach einer Weile ausgeführt wurde). Ich denke, die beste "Lösung" hängt von einem bestimmten Kontext ab. Wenn Sie beispielsweise einen E-Commerce-Dienst in Betracht ziehen, ist es möglicherweise weitaus besser, wenn manchmal einige Verbindungen zu einem Einkaufsdiagramm nicht zufällig hergestellt werden können, anstatt den gesamten Dienst zu verlieren. Dies birgt beispielsweise das Risiko, eine laufende Auftragsabwicklung zu unterbrechen (vielleicht noch schlimmer) ein Bezahlungsprozess mit allen Konsequenzen des Falls

Ebenso kann auf einer Workstation der Prozess, der die meisten Ressourcen verbraucht und daher für den OOM-Killer die erste Wahl ist, eine speicherintensive Anwendung sein, wie z. B. ein Video-Transcoder oder eine Rendering-Software, wahrscheinlich die einzige Anwendung der Benutzer möchte unberührt bleiben. Diese Überlegungen deuten darauf hin, dass die OOM-Killer-Standardrichtlinie zu aggressiv ist. Es wird ein "Worst - Fit" - Ansatz verwendet, der dem einiger Dateisysteme ähnelt (das OOMK versucht, so viel Speicher wie möglich freizugeben und gleichzeitig die Anzahl der getöteten Unterprozesse zu verringern, um weitere Eingriffe in kurzer Zeit zu verhindern) Außerdem kann eine fs mehr Speicherplatz zuweisen, als tatsächlich für eine bestimmte Datei benötigt wird, um eine weitere Zuweisung zu verhindern, wenn die Datei größer wird, und so die Fragmentierung in gewissem Maße zu verhindern.

Ich bin jedoch der Meinung, dass eine umgekehrte Strategie, wie ein "Best-Fit" -Ansatz, vorzuziehen sein könnte, um genau den Speicher freizugeben, der zu einem bestimmten Zeitpunkt benötigt wird, und sich nicht mit "großen" Prozessen zu beschäftigen, die durchaus verschwenden könnten Speicher, aber möglicherweise auch nicht, und der Kernel kann das nicht wissen (hmm, ich kann mir vorstellen, dass das Verfolgen der Seitenzugriffe und der Zeit darauf hindeuten kann, dass ein Prozess Speicher zuweist, den er nicht mehr benötigt, um zu erraten, ob ein Prozess vorhanden ist Speicher verschwenden oder nur viel verbrauchen, aber Zugriffsverzögerungen sollten in CPU-Zyklen gewichtet werden, um eine Speicherverschwendung von einer speicher- und CPU-intensiven Anwendung zu unterscheiden. Eine solche Heuristik kann jedoch möglicherweise ungenau sein und einen übermäßigen Overhead verursachen.

Darüber hinaus ist es möglicherweise nicht richtig, dass das Beenden der weniger möglichen Prozesse immer eine gute Wahl ist. In einer Desktop-Umgebung (zum Beispiel ein Nettop oder ein Netbook mit begrenzten Ressourcen) kann ein Benutzer beispielsweise einen Browser mit mehreren Registerkarten ausführen. , sowie einige andere Anwendungen (ein Textverarbeitungsprogramm mit nicht gespeicherten Daten, ein Mail-Client, ein PDF-Reader, ein Media-Player, ...), sowie einige (System-) Dämonen und einige Dateimanager-Instanzen. Jetzt tritt ein OOM-Fehler auf, und der OOMK entscheidet sich dafür, den Browser zu beenden, während der Benutzer etwas tut, das über das Netz als "wichtig" erachtet wird. Der Benutzer wäre enttäuscht. Auf der anderen Seite schließen die wenigen Dateimanager '

Ich denke jedenfalls, dass der Benutzer in die Lage versetzt werden sollte, selbst zu entscheiden, was zu tun ist. In einem Desktop (= interaktiven) System sollte dies relativ einfach zu bewerkstelligen sein, vorausgesetzt, es sind genügend Ressourcen reserviert, um den Benutzer aufzufordern, eine Anwendung zu schließen (aber auch das Schließen einiger Registerkarten könnte ausreichen) und seine Wahl zu treffen (eine Option könnte dies sein) besteht darin, eine zusätzliche Auslagerungsdatei zu erstellen, wenn genügend Speicherplatz vorhanden ist. Für Services (und im Allgemeinen) würde ich auch zwei weitere mögliche Verbesserungen in Betracht ziehen: Eine protokolliert OOM-Killer-Interventionen sowie Prozesse, die Fehler starten / forken, sodass der Fehler leicht behoben werden kann (z. B. eine API) Informieren Sie den Prozess, der den neuen Prozess erstellt oder das Forken durchführt. Ein Server wie Apache mit einem korrekten Patch kann daher eine bessere Protokollierung für bestimmte Fehler bieten. Dies könnte unabhängig davon geschehen, dass das Overcommit / OOMK aktiv ist. Zweitens könnte ein Mechanismus zur Feinabstimmung des OOMK-Algorithmus eingerichtet werden, der jedoch nicht von Bedeutung ist. Ich weiß, dass es bis zu einem gewissen Grad möglich ist, eine bestimmte Richtlinie prozessweise zu definieren, aber ich möchte a 'zentralisierter' Konfigurationsmechanismus, basierend auf einer oder mehreren Listen von Anwendungsnamen (oder IDs), um relevante Prozesse zu identifizieren und ihnen einen bestimmten Grad an Wichtigkeit zu verleihen (gemäß den aufgelisteten Attributen); Ein solcher Mechanismus sollte (oder könnte zumindest) auch geschichtet sein, so dass es eine benutzerdefinierte Liste auf oberster Ebene, eine system- (verteilungs-) definierte Liste und (unterste Ebene) anwendungsdefinierte Einträge geben kann Beispielsweise könnte ein DE-Dateimanager das OOMK anweisen, jede Instanz sicher zu töten.

Darüber hinaus könnte eine API bereitgestellt werden, die es Anwendungen ermöglicht, ihren "Wichtigkeitsgrad" zur Laufzeit zu erhöhen oder zu verringern (in Bezug auf Speicherverwaltungszwecke und unabhängig von der Ausführungspriorität), so dass beispielsweise eine Textverarbeitung beginnen könnte eine niedrige 'Wichtigkeit', aber erhöhen Sie sie, da einige Daten vor dem Löschen in eine Datei oder dem Ausführen einer Schreiboperation gehalten werden, und verringern Sie die Wichtigkeit erneut, wenn eine solche Operation endet (analog dazu könnte ein Dateimanager die Ebene ändern, wenn sie von gerade abgelaufen ist Wenn Sie Dateien für den Umgang mit Daten und umgekehrt bereitstellen, anstatt separate Prozesse zu verwenden, kann Apache verschiedenen Kindern unterschiedliche Wichtigkeitsstufen zuweisen oder einen untergeordneten Status gemäß einer Richtlinie ändern, die von Sysadmins festgelegt und über Apaches - oder eine andere Art von Servern - verfügbar gemacht wird - die Einstellungen). Na sicher, Eine solche API könnte und würde missbraucht / missbraucht werden, aber ich denke, das ist ein geringes Problem im Vergleich zum Kernel, der Prozesse abbricht, um Speicher freizugeben, ohne relevante Informationen darüber, was auf dem System vor sich geht (und Speicherbedarf / Erstellungszeit oder Ähnliches) Für mich nicht relevant oder "validierend") - nur Benutzer, Administratoren und Programmierer können wirklich feststellen, ob ein Prozess aus irgendeinem Grund "noch benötigt" wird, was der Grund ist und / oder ob sich die Anwendung in einem führenden Status befindet zu Datenverlust oder anderen Schäden / Problemen, wenn sie getötet werden; Es könnte jedoch noch eine gewisse Annahme getroffen werden, zum Beispiel, dass nach Ressourcen einer bestimmten Art (Dateideskriptoren, Netzwerksockets usw.) gesucht wird, die von einem Prozess erfasst wurden und bei ausstehenden Vorgängen festgestellt werden kann, ob sich ein Prozess in einem höheren Status als befindet der eine satz,

Oder vermeiden Sie einfach eine Überbeanspruchung, und lassen Sie den Kernel genau das tun, was ein Kernel tun muss, indem Sie Ressourcen zuweisen (aber nicht willkürlich wie der OOM-Killer retten), Prozesse planen, Hunger und Deadlocks verhindern (oder aus ihnen retten) und die vollständige Verfügbarkeit sicherstellen Speicherplatztrennung und so weiter ...

Ich würde auch noch ein paar Worte über Overcommit-Ansätze verlieren. Aus anderen Diskussionen habe ich den Gedanken gewonnen, dass eines der Hauptprobleme bei Überbeanspruchungen (sowohl als Grund, es zu wollen, als auch als Quelle möglicher Probleme) in der Handhabung von Gabeln besteht: Ehrlich gesagt, ich weiß nicht, wie genau die Kopie ist. Die On-Write-Strategie wird implementiert, aber ich denke, dass aggressive (oder optimistische) Richtlinien durch eine Swap-ähnliche Lokalitätsstrategie gemildert werden könnten. Das heißt, anstatt nur gegabelte Prozesscodeseiten und Planungsstrukturen zu klonen (und anzupassen), könnten einige andere Datenseiten vor einem tatsächlichen Schreibvorgang kopiert werden, wobei unter den Seiten ausgewählt wird, auf die der übergeordnete Prozess zugegriffen hat, um häufiger zu schreiben (d. H. Verwenden eines Zählers für Schreiboperationen).

Alles natürlich, IMHO.


quelle
5
"Darüber hinaus könnte eine API bereitgestellt werden, die es Anwendungen ermöglicht, ihre Wichtigkeit zur Laufzeit zu erhöhen oder zu verringern /proc/$PID/oom_adj."
Vi.
1
In Bezug auf die JVM gibt es in einigen Fällen ein GOTCHA, das zu einer Speicherüberbeanspruchung führt: Wenn Sie eine andere JVM aus Ihrer ursprünglichen JVM erstellen möchten, wird fork () aufgerufen. Ein Fork-Aufruf reserviert so viel Speicher wie der ursprüngliche Prozess (zuerst), bis er den Prozess wirklich startet. Angenommen, Sie haben eine 4-GB-JVM und möchten eine neue 512-KB-JVM daraus erstellen. Wenn Sie keine Überlastung haben, benötigen Sie 8 GB Speicher, um dies zu tun ...
alci
4
@Vi. Scheint jetzt/proc/$PID/oom_score_adj
erm3nda
1

Wenn Ihr Speicher durch die Prozesse in dem Maße erschöpft ist, in dem die Stabilität des Systems möglicherweise gefährdet ist, kommt der OOM-Killer ins Spiel. Es ist die Aufgabe des OOM-Killers, die Prozesse abzubrechen, bis genügend Speicherplatz frei ist, damit der Rest des Prozesses reibungslos funktioniert. Der OOM-Killer muss den „besten“ Prozess zum Töten auswählen. "Am besten" bezieht sich hier auf den Prozess, der beim Beenden den maximalen Speicher freigibt und für das System am wenigsten wichtig ist. Das Hauptziel ist es, die geringste Anzahl von Prozessen zu beenden, die den verursachten Schaden minimieren und gleichzeitig die Menge des freigewordenen Speichers maximieren. Um dies zu erleichtern, verwaltet der Kernel für jeden der Prozesse oom_score. Sie können den oom_score jedes Prozesses im Dateisystem / proc im Verzeichnis pid sehen

# cat /proc/10292/oom_score

Je höher der Wert von oom_score für einen Prozess ist, desto höher ist die Wahrscheinlichkeit, dass der OOM-Killer in einer Situation außerhalb des Arbeitsspeichers getötet wird.

Credit: - Der Linux-Kernel startet den OOM-Killer

dinkey jhanwar
quelle