Auf dieser Seite erfahren Sie, wie Sie Probleme mit Ereignissen vom Typ „Out of Memory“ (OOM) in Google Kubernetes Engine (GKE) beheben. Hier erfahren Sie, wie Sie die häufigsten Ursachen für OOM-Ereignisse ermitteln, zwischen Ereignissen auf Container- und Knotenebene unterscheiden und Lösungen anwenden.
Diese Seite richtet sich an Anwendungsentwickler, die überprüfen möchten, ob ihre Apps erfolgreich bereitgestellt wurden, sowie an Plattformadministratoren und ‑betreiber, die die Ursache von OOM-Ereignissen ermitteln und die Plattformkonfiguration überprüfen möchten. Weitere Informationen zu gängigen Rollen und Beispielaufgaben, auf die wir in Google Cloud Inhalten verweisen, finden Sie unter Häufig verwendete GKE Enterprise-Nutzerrollen und -Aufgaben.
Häufige Ursachen für OOM-Ereignisse
OOM-Ereignisse treten in der Regel bei Last- oder Traffic-Spitzen auf, wenn die Arbeitsspeichernutzung der App sprunghaft ansteigt und das für den Container konfigurierte Arbeitsspeicherlimit erreicht.
Die folgenden Szenarien können ein OOM-Ereignis verursachen:
- Unzureichendes Arbeitsspeicherlimit: Die Einstellung
resources.limits.memory
im Manifest des Pods ist zu niedrig für den typischen oder maximalen Arbeitsspeicherbedarf der App. - Nicht definierte Arbeitsspeicheranfragen oder ‑limits: Wenn sowohl
resources.limits.memory
als auchresources.requests.memory
nicht definiert sind, ist die Arbeitsspeichernutzung des Containers unbegrenzt. - Hohe oder sprunghafte Last: Plötzliche, extreme Lastspitzen können die Ressourcen eines Systems, einschließlich des Arbeitsspeichers, überfordern, auch wenn die Limits normalerweise ausreichend sind.
- Speicherleck: Die App hat möglicherweise einen Codefehler, der dazu führt, dass der Speicher nicht richtig freigegeben wird.
OOM-Ereignisse können einen kaskadierenden Fehler auslösen, da weniger Container zur Verarbeitung des Traffics verbleiben, was die Last auf den verbleibenden Containern erhöht. Diese Container werden dann möglicherweise auch geschlossen.
Umgang von Kubernetes mit OOM-Ereignissen
Der Linux OOM Killer verarbeitet jedes OOM-Ereignis. Der OOM-Killer ist ein Kernelprozess, der aktiviert wird, wenn das System nur noch sehr wenig Arbeitsspeicher hat. Es soll einen totalen Systemabsturz verhindern, indem Prozesse strategisch beendet werden, um Ressourcen freizugeben. Der Kernel verwendet ein Punktesystem, um auszuwählen, welcher Prozess beendet werden soll. Ziel ist es, die Systemstabilität aufrechtzuerhalten und Datenverlust zu minimieren.
In einer Kubernetes-Umgebung ist der OOM Killer in zwei verschiedenen Bereichen aktiv: in der Kontrollgruppe (cgroup), die sich auf einen Container auswirkt, und im System, das sich auf den gesamten Knoten auswirkt.
Beendigung aufgrund Arbeitsspeichermangels auf Containerebene
Ein OOM-Kill auf Containerebene tritt auf, wenn ein Container versucht, sein vordefiniertes Speicherlimit zu überschreiten. Kubernetes weist jeden Container einer bestimmten Cgroup mit einem festen Arbeitsspeicherlimit zu. Wenn die Arbeitsspeichernutzung eines Containers dieses Limit erreicht, versucht der Kernel zuerst, Arbeitsspeicher innerhalb dieser Cgroup freizugeben. Wenn der Kernel durch diesen Prozess nicht genügend Arbeitsspeicher freigeben kann, wird der OOM Killer der Cgroup aufgerufen. Damit werden Prozesse innerhalb dieser bestimmten Cgroup beendet, um die Ressourcengrenze zu erzwingen.
Wenn der Hauptprozess in einem Container auf diese Weise beendet wird, beobachtet Kubernetes das Ereignis und kennzeichnet den Status des Containers als OOMKilled
. Die konfigurierte restartPolicy
des Pods bestimmt dann das Ergebnis:
Always
oderOnFailure
: Der Container wird neu gestartet.Never
: Der Container wird nicht neu gestartet und bleibt im beendeten Zustand.
Durch die Isolierung des Fehlers auf den betreffenden Container verhindert der OOM Killer, dass ein einzelner fehlerhafter Pod den gesamten Knoten zum Absturz bringt.
Auswirkungen der cgroup-Version auf das Verhalten des OOM-Killers
Das Verhalten bei OOM-Kill kann sich zwischen den Cgroup-Versionen erheblich unterscheiden. Wenn Sie nicht sicher sind, welche cgroup-Version Sie verwenden, prüfen Sie den cgroup-Modus der Clusterknoten.
In
cgroup v1
kann ein OOM-Ereignis in der Memory-Cgroup eines Containers zu unvorhersehbarem Verhalten führen. Der OOM Killer kann jeden Prozess in dieser Cgroup beenden, einschließlich untergeordneter Prozesse, die nicht der Hauptprozess des Containers (PID 1) sind.Dieses Verhalten stellt eine erhebliche Herausforderung für Kubernetes dar. Da Kubernetes in erster Linie den Zustand des Hauptcontainerprozesses überwacht, werden diese „teilweisen“ OOM-Vorgänge nicht erkannt. Der Hauptcontainerprozess wird möglicherweise weiter ausgeführt, auch wenn wichtige untergeordnete Prozesse beendet wurden. Dieses Verhalten kann zu subtilen App-Fehlern führen, die für Kubernetes oder Operatoren nicht sofort sichtbar sind, aber dennoch im Systemprotokoll des Knotens (
journalctl
) angezeigt werden.cgroup v2
bietet ein besser vorhersehbares Verhalten des OOM-Killers.Um die Integrität von Arbeitslasten in einer cgroup v2-Umgebung zu gewährleisten, verhindert der OOM-Killer das teilweise Beenden von Prozessen und sorgt für eines von zwei Ergebnissen: Entweder werden alle Aufgaben, die zu dieser cgroup und ihren untergeordneten Elementen gehören, beendet (wodurch der Fehler für Kubernetes sichtbar wird), oder wenn die Arbeitslast keine Aufgaben hat, die zu viel Arbeitsspeicher verwenden, bleibt die Arbeitslast unverändert und wird ohne unerwartete interne Prozessbeendigungen weiter ausgeführt.
Für Szenarien, in denen Sie das
cgroup v1
-Verhalten zum Beenden eines einzelnen Prozesses wünschen, bietet das Kubelet das FlagsingleProcessOOMKill
fürcgroup v2
. Dieses Flag bietet Ihnen eine genauere Steuerung, da einzelne Prozesse bei einem OOM-Ereignis beendet werden können und nicht die gesamte Cgroup.
OOM-Beendigung auf Systemebene
Ein OOM-Kill auf Systemebene ist ein schwerwiegenderes Ereignis, das auftritt, wenn der gesamte Knoten und nicht nur ein einzelner Container nicht mehr genügend Arbeitsspeicher hat. Dieses Ereignis kann auftreten, wenn die kombinierte Arbeitsspeichernutzung aller Prozesse (einschließlich aller Pods und System-Daemons) die Kapazität des Knotens überschreitet.
Wenn auf diesem Knoten der Arbeitsspeicher aufgebraucht ist, bewertet der globale OOM Killer alle Prozesse auf dem Knoten und beendet einen Prozess, um Arbeitsspeicher für das gesamte System freizugeben. Der ausgewählte Prozess ist in der Regel kurzlebig und nutzt viel Arbeitsspeicher.
Um schwerwiegende OOM-Situationen zu vermeiden, verwendet Kubernetes Node-Pressure-Eviction, um Knotenressourcen zu verwalten. Bei diesem Vorgang werden weniger wichtige Pods von einem Knoten entfernt, wenn Ressourcen wie Arbeitsspeicher oder Speicherplatz kritisch niedrig werden. Ein OOM-Kill auf Systemebene weist darauf hin, dass bei diesem Bereinigungsvorgang nicht schnell genug Arbeitsspeicher freigegeben werden konnte, um das Problem zu verhindern.
Wenn der OOM Killer den Prozess eines Containers beendet, ist die Wirkung in der Regel identisch mit einem durch eine Cgroup ausgelösten Beenden: Der Container wird als OOMKilled
markiert und entsprechend seiner Richtlinie neu gestartet. Wenn jedoch ein kritischer Systemprozess beendet wird (was selten vorkommt), kann der Knoten selbst instabil werden.
OOM-Ereignisse untersuchen
In den folgenden Abschnitten erfahren Sie, wie Sie ein OOM-Ereignis erkennen und bestätigen können. Wir beginnen mit den einfachsten Kubernetes-Tools und gehen dann zur detaillierteren Loganalyse über.
Pod-Status auf sichtbare OOM-Ereignisse prüfen
Der erste Schritt zur Bestätigung eines OOM-Ereignisses besteht darin, zu prüfen, ob Kubernetes das OOM-Ereignis erkannt hat. Kubernetes beobachtet das Ereignis, wenn der Hauptprozess des Containers beendet wird. Das ist das Standardverhalten in cgroup v2
-Umgebungen.
Prüfen Sie den Status des Pods:
kubectl describe pod POD_NAME
Ersetzen Sie
POD_NAME
durch den Namen des Pods, den Sie sich prüfen möchten.Wenn ein sichtbares OOM-Ereignis aufgetreten ist, sieht die Ausgabe in etwa so aus:
... Last State: Terminated Reason: OOMKilled Exit Code: 137 Started: Tue, 13 May 2025 19:05:28 +0000 Finished: Tue, 13 May 2025 19:05:30 +0000 ...
Wenn im Feld Reason
der Wert OOMKilled
angezeigt wird, haben Sie die Veranstaltung bestätigt. Ein Exit Code
von 137
weist ebenfalls auf einen OOM-Kill hin. Wenn das Feld Reason
einen anderen Wert hat oder der Pod trotz App-Fehlern noch ausgeführt wird, fahren Sie mit dem nächsten Abschnitt fort, um das Problem weiter zu untersuchen.
In Protokollen nach unsichtbaren OOM-Ereignissen suchen
Ein OOM-Kill ist für Kubernetes „unsichtbar“, wenn ein untergeordneter Prozess beendet wird, der Hauptcontainerprozess aber weiterhin ausgeführt wird. Das ist ein häufiges Szenario in cgroup v1
-Umgebungen. Sie müssen in den Protokollen des Knotens nach Beweisen für diese Ereignisse suchen.
So finden Sie unsichtbare OOM-Kills mit dem Log-Explorer:
Rufen Sie in der Google Cloud Console den Log-Explorer auf.
Geben Sie im Bereich „Abfrage“ eine der folgenden Abfragen ein:
Wenn Sie bereits einen Pod haben, bei dem Sie vermuten, dass ein OOM-Ereignis aufgetreten ist, fragen Sie diesen bestimmten Pod ab:
resource.type="k8s_node" jsonPayload.MESSAGE:(("POD_NAME" AND "ContainerDied") OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"
Ersetzen Sie Folgendes:
POD_NAME
: Der Name des Pods, den Sie abfragen möchten.CLUSTER_NAME
: der Name des Clusters, zu dem der Pod gehört.
Wenn Sie herausfinden möchten, bei welchen Pods oder Knoten ein OOM-Ereignis aufgetreten ist, fragen Sie alle GKE-Arbeitslasten ab:
resource.type="k8s_node" jsonPayload.MESSAGE:("ContainerDied" OR "TaskOOM event") resource.labels.cluster_name="CLUSTER_NAME"
Klicken Sie auf Abfrage ausführen.
Suchen Sie in der Ausgabe nach OOM-Ereignissen, indem Sie nach Logeinträgen mit dem String
TaskOOM
suchen.Optional: Wenn Sie nach OOM-Ereignissen für alle GKE-Arbeitslasten gesucht haben und den spezifischen Pod ermitteln möchten, bei dem die OOM-Ereignisse aufgetreten sind, führen Sie die folgenden Schritte aus:
- Notieren Sie sich für jedes Ereignis die zugehörige Container-ID.
Suchen Sie in den Logs nach Einträgen, die den String
ContainerDied
enthalten und kurz nach den OOM-Ereignissen aufgetreten sind, um Containerstopps zu identifizieren. Gleichen Sie die Container-ID aus dem OOM-Ereignis mit der entsprechendenContainerDied
-Zeile ab.Nachdem Sie die
container IDs
gefunden haben, enthält dieContainerDied
-Zeile in der Regel den Pod-Namen, der dem fehlgeschlagenen Container zugeordnet ist. Dieser Pod war vom OOM-Ereignis betroffen.
journalctl für Echtzeitinformationen verwenden
Wenn Sie eine Echtzeitanalyse Ihres Systems durchführen müssen, verwenden Sie journalctl
-Befehle.
Stellen Sie über SSH eine Verbindung zum Knoten her:
gcloud compute ssh NODE_NAME --location ZONE
Ersetzen Sie Folgendes:
NODE_NAME
: Der Name des Knotens, den Sie untersuchen möchten.ZONE
: die Compute Engine-Zone, zu der Ihr Knoten gehört.
Sehen Sie sich in der Shell die Kernel-Meldungen aus dem Systemjournal des Knotens an:
journalctl -k
Analysieren Sie die Ausgabe, um den Ereignistyp zu unterscheiden:
- Beenden auf Containerebene: Der Logeintrag enthält Begriffe wie
memory cgroup
,mem_cgroup
odermemcg
, die darauf hinweisen, dass ein cgroup-Limit erzwungen wurde. - Beenden auf Systemebene: Der Logeintrag ist eine allgemeine Meldung wie
Out of memory: Killed process...
, in der keine Cgroup erwähnt wird.
- Beenden auf Containerebene: Der Logeintrag enthält Begriffe wie
OOM-Ereignisse beheben
Versuchen Sie Folgendes, um ein OOM-Ereignis zu beheben:
- Speicherlimits erhöhen: Dies ist die direkteste Lösung. Bearbeiten Sie das Pod-Manifest, um einen höheren
resources.limits.memory
-Wert anzugeben, der der Spitzenlast der App entspricht. Weitere Informationen zum Festlegen von Limits finden Sie in der Kubernetes-Dokumentation unter Ressourcenverwaltung für Pods und Container. - Speicheranforderungen hinzufügen oder anpassen: Prüfen Sie im Manifest des Pods, ob das Feld
resources.requests.memory
auf einen realistischen Wert für die typische Nutzung festgelegt ist. Mit dieser Einstellung kann Kubernetes den Pod auf einem Knoten mit ausreichend Arbeitsspeicher planen. - Arbeitslast horizontal skalieren: Um die Trafficlast zu verteilen und den Arbeitsspeicherbedarf für einzelne Pods zu reduzieren, erhöhen Sie die Anzahl der Replikate. Wenn Kubernetes die Arbeitslast proaktiv skalieren soll, sollten Sie horizontales Pod-Autoscaling aktivieren.
- Knoten vertikal skalieren: Wenn viele Pods auf einem Knoten sich ihren Limits nähern, ist der Knoten möglicherweise zu klein. Wenn Sie die Größe der Knoten erhöhen möchten, migrieren Sie Ihre Arbeitslasten zu einem Knotenpool mit mehr Arbeitsspeicher. Wenn Kubernetes die Knoten proaktiv skalieren soll, sollten Sie vertikales Pod-Autoscaling aktivieren.
- App optimieren: Überprüfen Sie Ihre App, um Speicherlecks zu erkennen und zu beheben, und optimieren Sie Code, der bei Trafficspitzen große Mengen an Arbeitsspeicher verbraucht.
- Problematische Arbeitslasten löschen: Als letzte Möglichkeit für nicht kritische Arbeitslasten können Sie den Pod löschen, um den Cluster sofort zu entlasten.
Nächste Schritte
Wenn Sie in der Dokumentation keine Lösung für Ihr Problem finden, lesen Sie den Abschnitt Support erhalten. Dort finden Sie weitere Hilfe, z. B. zu den folgenden Themen:
- Sie können eine Supportanfrage erstellen, indem Sie sich an Cloud Customer Care wenden.
- Support von der Community erhalten, indem Sie Fragen auf Stack Overflow stellen und mit dem Tag
google-kubernetes-engine
nach ähnlichen Problemen suchen. Sie können auch dem#kubernetes-engine
-Slack-Kanal beitreten, um weiteren Community-Support zu erhalten. - Sie können Fehler melden oder Funktionsanfragen stellen, indem Sie die öffentliche Problemverfolgung verwenden.