Kubernetes: Kubelet/Kubernetes sollte mit aktiviertem Swap funktionieren

Erstellt am 6. Okt. 2017  ·  94Kommentare  ·  Quelle: kubernetes/kubernetes

Ist dies ein FEHLERBERICHT oder eine FEATURE-ANFRAGE? :

Entkommentieren Sie nur einen, lassen Sie ihn in einer eigenen Zeile:

/ freundlicher Fehler
/freundliches Feature

Was ist passiert :

Kubelet/Kubernetes 1.8 funktioniert nicht mit aktiviertem Swap auf Linux-Maschinen.

Ich habe dieses ursprüngliche Problem gefunden https://github.com/kubernetes/kubernetes/issues/31676
Diese PR https://github.com/kubernetes/kubernetes/pull/31996
und letzte Änderung, die es standardmäßig aktiviert hat https://github.com/kubernetes/kubernetes/commit/71e8c8eba43a0fade6e4edfc739b331ba3cc658a

Wenn Kubernetes nicht weiß, wie es mit der Speicherbereinigung umgeht, wenn Swap aktiviert ist, sollte es einen Weg finden, dies zu tun, aber nicht darum bitten, Swap loszuwerden.

Bitte folgen Sie zum Beispiel Kernel.org Kapitel 11 Swap Management

Der Gelegenheitsleser mag denken, dass Swap bei ausreichender Speicherkapazität unnötig ist, aber das bringt uns zum zweiten Grund. Ein erheblicher Teil der Seiten, auf die ein Prozess zu Beginn seines Lebens referenziert, darf nur zur Initialisierung und dann nie wieder verwendet werden. Es ist besser, diese Seiten auszulagern und mehr Plattenpuffer zu erstellen, als sie resident und ungenutzt zu lassen.

Bei vielen Node/Java-Anwendungen habe ich immer gesehen, dass viele Seiten ausgetauscht wurden, nur weil sie nicht mehr verwendet werden.

Was Sie erwartet haben, zu passieren :

Kubelet/Kubernetes sollte mit aktiviertem Swap funktionieren. Ich glaube, anstatt Swap zu deaktivieren und Benutzern keine Wahlmöglichkeiten zu geben, sollte Kubernetes mehr Anwendungsfälle und verschiedene Workloads unterstützen, einige von ihnen können Anwendungen sein, die auf Caches angewiesen sein könnten.

Ich bin mir nicht sicher, wie Kubernetes entschieden hat, was mit der Speicherräumung getötet werden soll, aber wenn man bedenkt, dass Linux diese Fähigkeit hat, sollte es vielleicht damit übereinstimmen, wie Linux dies tut? https://www.kernel.org/doc/gorman/html/understand/understand016.html

Ich würde vorschlagen, die Änderung für das Fehlschlagen bei aktiviertem Swap rückgängig zu machen und zu überprüfen, wie die Speicherbereinigung derzeit in Kubernetes funktioniert. Swap kann für einige Workloads wichtig sein.

So reproduzieren Sie es (so minimal und genau wie möglich) :

Führen Sie kubernetes/kublet mit den Standardeinstellungen auf der Linux-Box aus

Müssen wir noch etwas wissen? :

Umgebung :

  • Kubernetes-Version (verwenden Sie kubectl version ):
  • Cloud-Anbieter oder Hardwarekonfiguration**:
  • Betriebssystem (zB aus /etc/os-release):
  • Kernel (zB uname -a ):
  • Tools installieren:
  • Andere:

/sig-Knoten
cc @mtaufen @vishh @derekwaynecarr @dims

kinfeature sinode

Hilfreichster Kommentar

Wird Swap nicht standardmäßig unterstützt? Ich war überrascht, das zu hören – ich dachte, Kubernetes wäre bereit für die Hauptsendezeit? Swap ist eine dieser Funktionen.

Dies ist in den meisten offenen Anwendungsfällen nicht wirklich optional – so ist das Unix-Ökosystem für den Betrieb ausgelegt, wobei der VMM inaktive Seiten ausschaltet.

Wenn die Wahl kein Swap oder keine Speicherbeschränkungen ist, werde ich Swap jeden Tag beibehalten und einfach mehr Hosts hochfahren, wenn ich mit dem Paging beginne, und ich werde immer noch Geld sparen.

Kann jemand klarstellen, dass das Problem mit der Speicherentfernung nur ein Problem darstellt, wenn Sie Speichergrenzen in der Pod-Definition verwenden, aber ansonsten ist es in Ordnung?

Es wäre schön, in einer Welt zu arbeiten, in der ich die Kontrolle über die Arbeitsweise eines Anwendungsspeichers habe, damit ich mir keine Sorgen über eine schlechte Speicherauslastung machen muss, aber die meisten Anwendungen haben viel inaktiven Speicherplatz.

Ich glaube ehrlich gesagt, dass dieser kürzliche Schritt, Server ohne Swap zu betreiben, von den PaaS-Anbietern angetrieben wird, die versuchen, die Leute in größere Speicherinstanzen zu zwingen – während sie ~40 Jahre Speicherverwaltungsdesign außer Acht lassen. Die Realität ist, dass der Kernel wirklich gut darin weiß, welche Speicherseiten aktiv sind oder nicht – lassen Sie ihn seine Arbeit machen.

Alle 94 Kommentare

Die Unterstützung für Swap ist nicht trivial. Garantierte Pods sollten niemals ausgetauscht werden müssen. Burstable-Pods sollten ihre Anforderungen erfüllen, ohne dass ein Austausch erforderlich ist. BestEffort-Pods haben keine Garantie. Dem Kubelet fehlt derzeit die Intelligenz, um hier über Pods hinweg das richtige Maß an vorhersehbarem Verhalten bereitzustellen.

Wir haben dieses Thema Anfang des Jahres auf der Ressourcen mgmt von Angesicht zu Angesicht diskutiert. Wir sind nicht sehr daran interessiert, dies in naher Zukunft im Verhältnis zu den möglichen Gewinnen anzugehen. Wir würden es vorziehen, die Zuverlässigkeit rund um die Druckerkennung zu verbessern und Probleme rund um die Latenz zu optimieren, bevor wir versuchen, für den Swap zu optimieren, aber wenn dies für Sie eine höhere Priorität hat, würden wir uns über Ihre Hilfe freuen.

/freundliches Feature

@derekwaynecarr danke für die Erklärung! Es war schwierig, Informationen/Dokumentationen zu erhalten, warum Swap für Kubernetes deaktiviert werden sollte. Dies war der Hauptgrund, warum ich dieses Thema eröffnet habe. An dieser Stelle habe ich keine hohe Priorität für dieses Thema, wollte nur sichergehen, dass wir einen Ort haben, an dem es diskutiert werden kann.

Hier gibt es mehr Kontext in der Diskussion: https://github.com/kubernetes/kubernetes/issues/7294 – Wenn Swap verfügbar ist, hat dies sehr seltsame und schlechte Interaktionen mit Speicherlimits. Zum Beispiel würde ein Container, der sein Speicherlimit erreicht, _dann_ in den Swap überlaufen (dies scheint seit f4edaf2b8c32463d6485e2c12b7fd776aef948bc behoben zu sein – sie dürfen keinen Swap verwenden, egal ob er vorhanden ist oder nicht).

Dies ist auch für uns ein kritischer Anwendungsfall. Wir haben einen Cron-Job, der gelegentlich auf eine hohe Speicherauslastung (> 30 GB) stößt, und wir möchten nicht dauerhaft 40 + GB-Knoten zuweisen. Da wir in drei Zonen (GKE) ausgeführt werden, werden dadurch 3 solcher Maschinen zugewiesen (1 in jeder Zone). Und diese Konfiguration muss in 3+ Produktionsinstanzen und 10+ Testinstanzen wiederholt werden, was die Verwendung von K8s extrem teuer macht. Wir sind gezwungen, 25+ 48 GB Knoten zu haben, was enorme Kosten verursacht!.
Bitte Swap aktivieren!.

Ein Workaround für diejenigen, die wirklich tauschen wollen. wenn du

  • kubelet starten mit --fail-swap-on=false
  • Swap zu deinen Knoten hinzufügen
  • Behälter , die in der Lage, dann keinen Speicherbedarf angeben standardmäßig alle Gerätespeicher zu verwenden, einschließlich Swap.

Das ist, was wir tun. Oder zumindest bin ich mir ziemlich sicher, dass ich es nicht persönlich umgesetzt habe, aber das ist es, was ich vermute.

Dies könnte nur dann wirklich eine praktikable Strategie sein, wenn keiner Ihrer Container jemals eine explizite Speicheranforderung angibt...

Wir laufen in GKE, und ich kenne keine Möglichkeit, diese Optionen festzulegen.

Ich wäre offen für die Einführung von zswap, wenn jemand die Auswirkungen auf Speicherentfernungen in kubelet bewerten kann.

Ich führe Kubernetes auf meinem lokalen Ubuntu-Laptop aus und bei jedem Neustart muss ich Swap ausschalten. Außerdem muss ich mir Sorgen machen, dass ich nicht in die Nähe des Speicherlimits komme, da der Swap ausgeschaltet ist.

Gibt es eine Möglichkeit, bei jedem Neustart den Swap nicht wie bei einer Änderung der Konfigurationsdatei in einer bestehenden Installation zu deaktivieren?

Ich brauche keinen Swap auf Knoten, die im Cluster ausgeführt werden.

Es sind nur andere Anwendungen auf meinem Laptop außer dem Kubernetes Local Dev-Cluster, die den Swap aktivieren müssen.

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.2", GitCommit:"5fa2db2bd46ac79e5e00a4e6ed24191080aa463b", GitTreeState:"clean", BuildDate:"2018-01-18T10:09:24Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.2", GitCommit:"5fa2db2bd46ac79e5e00a4e6ed24191080aa463b", GitTreeState:"clean", BuildDate:"2018-01-18T09:42:01Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}

Im Moment funktioniert die Flagge nicht.

# systemctl restart kubelet --fail-swap-on=false
systemctl: unrecognized option '--fail-swap-on=false'

Legen Sie das folgende Kubelet-Flag fest: --fail-swap-on=false

Am Dienstag, 30. Januar 2018 um 13:59 Uhr schrieb icewheel [email protected] :

Ich führe Kubernetes auf meinem lokalen Ubuntu-Laptop aus und bei jedem Neustart ich
muss den Swap ausschalten. Außerdem muss ich mir Sorgen machen, dass ich nicht in die Nähe der Erinnerung komme
begrenzen wenn tauschen wenn aus.

Gibt es eine Möglichkeit bei jedem Neustart, dass ich den Swap nicht wie einige ausschalten muss?
Konfigurationsdatei in bestehender Installation ändern?

Ich brauche keinen Swap auf Knoten, die im Cluster ausgeführt werden.

Es sind nur andere Anwendungen auf meinem Laptop als Kubernetes Local Dev
Cluster, die den Swap aktivieren müssen.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/kubernetes/kubernetes/issues/53533#issuecomment-361748518 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AA3JwQdj2skL2dSqEVyV46iCllzT-sOVks5tP5DSgaJpZM4PwnD5
.

--
Michael Taufen
Google SWE

danke @mtaufen

Bei Systemen, die Cluster für Sie booten (wie Terraform), müssen Sie möglicherweise die Servicedatei ändern

Das hat bei mir funktioniert

sudo sed -i '/kubelet-wrapper/a \ --fail-swap-on=false \\\' /etc/systemd/system/kubelet.service

Wird Swap nicht standardmäßig unterstützt? Ich war überrascht, das zu hören – ich dachte, Kubernetes wäre bereit für die Hauptsendezeit? Swap ist eine dieser Funktionen.

Dies ist in den meisten offenen Anwendungsfällen nicht wirklich optional – so ist das Unix-Ökosystem für den Betrieb ausgelegt, wobei der VMM inaktive Seiten ausschaltet.

Wenn die Wahl kein Swap oder keine Speicherbeschränkungen ist, werde ich Swap jeden Tag beibehalten und einfach mehr Hosts hochfahren, wenn ich mit dem Paging beginne, und ich werde immer noch Geld sparen.

Kann jemand klarstellen, dass das Problem mit der Speicherentfernung nur ein Problem darstellt, wenn Sie Speichergrenzen in der Pod-Definition verwenden, aber ansonsten ist es in Ordnung?

Es wäre schön, in einer Welt zu arbeiten, in der ich die Kontrolle über die Arbeitsweise eines Anwendungsspeichers habe, damit ich mir keine Sorgen über eine schlechte Speicherauslastung machen muss, aber die meisten Anwendungen haben viel inaktiven Speicherplatz.

Ich glaube ehrlich gesagt, dass dieser kürzliche Schritt, Server ohne Swap zu betreiben, von den PaaS-Anbietern angetrieben wird, die versuchen, die Leute in größere Speicherinstanzen zu zwingen – während sie ~40 Jahre Speicherverwaltungsdesign außer Acht lassen. Die Realität ist, dass der Kernel wirklich gut darin weiß, welche Speicherseiten aktiv sind oder nicht – lassen Sie ihn seine Arbeit machen.

Dies hat auch den Effekt, dass, wenn der Speicher auf dem Knoten erschöpft ist, dieser möglicherweise vollständig blockiert wird – was einen Neustart des Knotens erfordert, anstatt nur langsamer zu werden und sich eine Weile später wieder zu erholen.

Die Probleme veralten nach 90 Tagen Inaktivität.
Markieren Sie das Problem mit /remove-lifecycle stale .
Veraltete Ausgaben verrotten nach weiteren 30 Tagen Inaktivität und werden schließlich geschlossen.

Wenn dieses Problem jetzt sicher geschlossen werden kann, tun Sie dies bitte mit /close .

Senden Sie Feedback an sig-testing, kubernetes/test-infra und/oder fejta .
/Lebenszyklus veraltet

Ich habe eine hohe Anzahl von Festplattenlesevorgängen in meinen Clusterknoten ( K8s Version - v1.11.2 ). Kann es daran liegen, dass der Swap-Speicher deaktiviert ist?

https://stackoverflow.com/questions/51988566/high-number-of-disk-reads-in-kubernetes-nodes

@srevenant In der Clusterwelt ist der RAM des anderen Knotens der neue Swap. Das heißt, ich betreibe zwei Ein-Knoten-K8-Instanzen, bei denen ein Austausch sinnvoll ist. Dies ist jedoch nicht der typische Anwendungsfall von K8s.

@srevenant Ich stimme Ihnen
Das Problem SWAP ist standardmäßig immer aktiviert, wenn wir eine Linux-Distribution installieren, also muss ich es deaktivieren, bevor ich K8s installiere, und das war eine Überraschung.
Der Linux-Kernel weiß gut, wie man SWAP verwaltet, um die Leistung von Servern insbesondere vorübergehend zu erhöhen, wenn der Server kurz vor dem Erreichen des RAM-Limits steht.
Bedeutet das, dass ich SWAP ausschalten muss, damit K8s gut funktioniert?

Ich habe ein Interesse daran, dass dies funktioniert, und ich habe die Fähigkeiten und eine Reihe von Maschinen, an denen ich sie testen kann. Wenn ich einen Beitrag leisten wollte, wo fange ich am besten an?

@superdave bitte

Ich stehe dafür, dass der Swap in Kubernetes Pods ordnungsgemäß aktiviert wird. Es macht wirklich keinen Sinn, keinen Swap zu haben, da fast alle Container benutzerdefinierte Linux-Instanzen sind und daher Swap standardmäßig unterstützen.
Es ist verständlich, dass die Implementierung der Funktion komplex ist, aber seit wann hat uns das daran gehindert, voranzukommen?

Ich muss zustimmen, dass die Swap-Probleme in Kubernetes gelöst werden sollten, da das Deaktivieren von Swap zu einem Knotenfehler führt, wenn der Speicher auf dem Knoten knapp wird. Wenn Sie beispielsweise 3 Worker-Nodes (jeweils 20 GB RAM) haben und ein Node ausfällt, weil das RAM-Limit erreicht ist, werden 2 andere Worker-Nodes ebenfalls ausfallen, nachdem alle Pods in dieser Zeit auf sie übertragen wurden.

Sie können dies verhindern, indem Sie Speicheranforderungen entsprechend der aktuellen
Bedarf der Anwendung.

Wenn sich ein Drittel des Speichers Ihrer Anwendung auf 2 Größenordnungen befindet
langsamerer Speicher, wird er in der Lage sein, nützliche Arbeit zu leisten?

Am Mittwoch, den 26. September 2018 um 6:51 Uhr schrieb vasicvuk [email protected] :

Ich muss zustimmen, dass die Swap-Probleme in Kubernetes gelöst werden sollten, da
Das Deaktivieren von Swap führt zu einem Knotenfehler, wenn der Speicher auf dem Knoten knapp wird. Zum
Beispiel, wenn Sie 3 Worker-Knoten (jeweils 20 GB RAM) haben und ein Knoten geht
unten, weil das RAM-Limit erreicht ist 2 andere Worker-Knoten werden auch gehen
herunter, nachdem Sie in dieser Zeit alle Kapseln auf sie übertragen haben.


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/kubernetes/kubernetes/issues/53533#issuecomment-424604731 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AAICBqZApBscFl5aNA4IcYvlxcvPA88Tks5ueyPlgaJpZM4PwnD5
.

@matthiasr Sie können das tun, wenn Sie 10-50 Dienste haben. Aber wenn Sie Cluster haben, auf dem über 200 Dienste ausgeführt werden und die Hälfte davon mit offiziellen Helm-Charts ohne Speicheranforderung bereitgestellt wird, sind Sie in der Hand.

Aber sind dann nicht fehlende Speicheranforderungen das zu lösende Problem?

@matthiasr In vielen Fällen wird der Speicher, der einmal dem Prozess zugeordnet wurde, nur einmal verwendet oder nie tatsächlich verwendet. Das sind gültige Fälle und keine Speicherlecks. Wenn Sie Swap haben, werden diese Seiten schließlich ausgetauscht und werden möglicherweise nie wieder eingelagert, aber Sie geben schnellen RAM zur besseren Verwendung frei.

Auch das Ausschalten von Swap ist kein guter Weg, um die Reaktionsfähigkeit sicherzustellen. Sofern Sie keine Dateien im Speicher anheften (eine Fähigkeit, die K8s zumindest für ausführbare Dateien haben sollte), lagert der Kernel dennoch alle dateigestützten Seiten als Reaktion auf Speicherdruck oder einfach nur mangelnde Nutzung aus.

Wenn Swap aktiviert ist, ändert sich das Kernel-Verhalten nicht merklich. Es bietet lediglich einen Platz zum Auslagern anonymer Seiten oder modifizierter Seiten, die aus COW-zugeordneten Dateien geladen wurden.

Sie können das Swapping nicht vollständig deaktivieren, daher muss K8s seine Existenz überleben, unabhängig davon, ob der Sonderfall des anonymen Speicher-Swapping aktiviert ist

Das macht dies zu einem Fehler: Sie unterstützen eine Kernel-Funktion nicht, die nicht wirklich ausgeschaltet werden kann.

@Baughn

der Kernel lagert immer noch alle dateigestützten Seiten als Reaktion auf Speicherdruck oder einfach nur mangelnde Nutzung aus. Wenn Swap aktiviert ist, ändert sich das Kernel-Verhalten nicht merklich.

Sie können den Austausch nicht vollständig deaktivieren,

Können Sie dazu eine Referenz geben, damit ich mich weiterbilden kann?

Sofern Sie keine Dateien im Speicher anheften (eine Fähigkeit, die K8s zumindest für ausführbare Dateien haben sollte),

Welche Fähigkeiten soll k8s nutzen? Wenn eine Binärdatei statisch ist, sollte das einfache Kopieren in ein tmpfs auf dem Pod bei der Paging-Latenz helfen.

@adityakali irgendwelche Gedanken zu den Auswirkungen von Swap im Kernel, wenn Swap ausgeschaltet ist?

Können Sie dazu eine Referenz geben, damit ich mich weiterbilden kann?

Wie alle modernen virtuellen Speicherbetriebssysteme fordert Linux ausführbare Dateien von der Festplatte in den Speicher. Unter Speicherdruck lagert der Kernel den eigentlichen ausführbaren Code Ihres Programms wie jede andere Speicherseite Das _nur_ Swapping, das Sie durch "Deaktivieren von Swap" deaktivieren, ist "anonymer Speicher" - Speicher, der _nicht_ einer Datei zugeordnet ist (die besten Beispiele sind die "Stack"- und "Heap"-Datenstrukturen).

Es gibt viele Details, die ich in der obigen Beschreibung natürlich überspringe. Insbesondere können ausführbare Dateien mit der mlock Familie von Systemaufrufen Teile ihres Speicherplatzes im RAM "sperren", clevere Dinge über madvise() tun. Es wird kompliziert, wenn die gleichen Seiten von mehreren Prozessen geteilt werden (zB libc.so), etc. Ich fürchte, ich habe keinen nützlicheren Hinweis, um mehr zu lesen als diese Manpages oder allgemeine Dinge wie Lehrbücher oder Linux-Kernel-Quellen/Dokumente/Mailing-Listen.

Ein praktischer Effekt des Obigen besteht also darin, dass der Kernel gezwungen ist, _code_-Anteile und Konstanten aus dem RAM zu entfernen, wenn sich Ihr Prozess seiner Speichergrenze nähert. Wenn dieses Bit Code oder konstanter Wert das nächste Mal benötigt wird, hält das Programm an und wartet darauf, es wieder von der Festplatte zu holen (und etwas anderes zu entfernen). Selbst wenn "Swap" deaktiviert ist, erhalten Sie immer noch die gleiche Verschlechterung, wenn Ihr Arbeitssatz den verfügbaren Speicher überschreitet.

Bevor die Leute das Obige lesen und im Rahmen der Anti-Swap-Hexenjagd anrufen, um alles in den Speicher zu sperren oder alles in einen Ramdrive zu kopieren, möchte ich wiederholen, dass die wirkliche Ressource, die hier von Interesse ist, die Arbeitssatzgröße ist – nicht die Gesamtgröße . Ein Programm, das linear durch Gigabytes an Daten im RAM arbeitet, arbeitet möglicherweise nur mit einem schmalen Fenster dieser Daten gleichzeitig. Dieses hypothetische Programm würde mit einer großen Menge an Swap und einem kleinen RAM-Limit gut funktionieren - und es wäre schrecklich ineffizient, alles in echtem RAM zu sperren. Wie Sie aus der obigen Erklärung erfahren haben, ist dies genau dasselbe wie ein Programm, das eine große Menge an _Code_ hat, aber zu einem bestimmten Zeitpunkt nur eine kleine Menge davon ausführt.

Mein neuestes persönliches Beispiel aus der Praxis für so etwas ist das Verknüpfen der ausführbaren Kubernetes-Dateien. Ich bin derzeit (ironischerweise) nicht in der Lage, Kubernetes auf meinem Kubernetes-Cluster zu kompilieren, da die Go-Link-Stufe mehrere Gigabyte (anonymen) virtuellen Speicher erfordert, obwohl der Arbeitssatz viel kleiner ist.

Um den Punkt "es geht um Working Set, nicht um virtuellen Speicher" wirklich zu vertiefen, sollten Sie sich ein Programm vorstellen, das viele normale Datei-I/Os ausführt und nichts mit mmap zu tun hat. Wenn Sie über genügend RAM verfügen, wird der Kernel wiederholt verwendete Verzeichnisstrukturen und Dateidaten im RAM zwischenspeichern und vermeiden, auf die Festplatte zu gehen, und es ermöglicht, dass Schreibvorgänge vorübergehend in den RAM platzen, um das Ausschreiben der Festplatte zu optimieren. Sogar ein "naives" Programm wie dieses wird von RAM-Geschwindigkeit auf Festplattengeschwindigkeit herabgesetzt, abhängig von der Größe des Arbeitssatzes im Vergleich zum verfügbaren RAM. Wenn Sie etwas unnötig in den Arbeitsspeicher stecken (zB: mlock verwenden oder Swap deaktivieren), verhindern Sie, dass der Kernel diese Seite des physischen Arbeitsspeichers für etwas wirklich Nützliches verwendet und (wenn Sie nicht genug Arbeitsspeicher für das Arbeitsset hatten) haben Sie einfach habe die Festplatten-E/A an einen noch teureren Ort verlegt.

@superdave : Auch ich bin daran interessiert, den Status Quo hier zu verbessern. Bitte fügen Sie mich hinzu, wenn Sie möchten, dass ein anderes Augenpaar ein Dokument überprüft oder Hände an einer Tastatur.

Mein neuestes persönliches Beispiel aus der Praxis für so etwas ist das Verknüpfen der ausführbaren Kubernetes-Dateien. Ich bin derzeit (ironischerweise) nicht in der Lage, Kubernetes auf meinem Kubernetes-Cluster zu kompilieren, da die Go-Link-Stufe mehrere Gigabyte (anonymen) virtuellen Speicher erfordert, obwohl der Arbeitssatz viel kleiner ist.

@superdave : Auch ich bin daran interessiert, den Status Quo hier zu verbessern. Bitte fügen Sie mich hinzu, wenn Sie möchten, dass ein anderes Augenpaar ein Dokument überprüft oder Hände an einer Tastatur.

Gute Zusammenfassung des vorliegenden Problems! Swap-Thrashing ist hier tatsächlich das Hauptproblem; es ist etwas, was ich hoffe, rational ansprechen zu können. Es scheint mir, obwohl ich nicht wirklich genug Zeit hatte, um darüber nachzudenken, dass irgendeine Art von Metrik der Austauschaktivität (Pageins/Outs über einen bestimmten Zeitraum, vielleicht mit einer Perzentilregel, um übereifriges Springen zu vermeiden, wenn a Prozess plötzliche Spitzen temporär) kann eine gute Möglichkeit sein, Dinge für die Entfernung zu bewerten, wenn Swap aktiviert ist. Es gibt eine Reihe von Metriken, und ich vermute, wir möchten viele Drehknöpfe anbieten und die wahrscheinlichen Anwendungsfälle sorgfältig bewerten. Ich vermute auch, dass die Möglichkeit, Pods für virtuelle Speicherinteraktionen zu instrumentieren, den Leuten helfen sollte, besser abzustimmen; Ich bin mit dem, was bereits angeboten wird, nicht vertraut genug, um zu sagen, was jetzt da ist, aber ich vermute, ich werde es herausfinden.

Ich bin auch nicht vertraut genug mit den Steuerelementen, die wir benötigen, um zu wissen, wie gut wir das Austauschverhalten in einzelnen Pods/Containern steuern können; es wäre hilfreich, Dinge für die Aufbewahrung oder den Austausch "renice" zu können, aber Entwicklern steht es natürlich immer frei, mlock() zu versuchen, wenn sie unbedingt garantieren müssen, dass die Dinge sowieso resident sind.

Auf jeden Fall, ja, ich möchte das unbedingt vorantreiben. Ich war in letzter Zeit bei der Arbeit überfordert (Bewältigung einiger OOM-Probleme mit unseren eigenen Microservices unter k8s, die davon profitiert hätten, unter Last austauschen zu können, da sie in 99% der Fälle keine Gigs an RAM benötigen, es sei denn, jemand macht einen unratsam großen Wert Anfrage), aber zögern Sie nicht, mich darüber zu informieren. Ich habe noch nie am KEP-Prozess teilgenommen, also werde ich ziemlich grün sein, aber heutzutage arbeite ich viel besser auf Interrupt-Basis als auf Polling-Basis. :-)

Ich möchte darauf hinweisen, dass Zram funktioniert, indem es Swaps huckepack trägt. Wenn es keine Swaps auf k8 gibt, gibt es keine Speicherkomprimierung, was die meisten Nicht-Linux-Betriebssysteme standardmäßig aktiviert haben (Stichwort Windows, MacOS).

Wir haben eine Ubuntu-Instanz auf k8, die jede Nacht einen großen Batch-Job ausführt, der viel Speicher verbraucht. Da die Arbeitslast nicht vorbestimmt ist, sind wir gezwungen, dem Knoten unabhängig von seinem tatsächlichen Speicherverbrauch (teure) 16 GB zuzuweisen, um OOM zu vermeiden. Mit der Speicherkomprimierung auf unserem lokalen Entwicklungsserver erreicht der Job nur 3 GB. Ansonsten benötigt es tagsüber nur 1 GB Speicher. Das Verbot von Swaps und damit der Speicherkomprimierung ist ein ziemlich alberner Schachzug.

Ich denke, das Hauptanliegen hier ist wahrscheinlich die Isolation. Eine typische Maschine kann eine Menge Pods hosten, und wenn der Speicher knapp wird, könnten sie anfangen zu tauschen und die Leistung füreinander vollständig zu zerstören. Wenn es keinen Tausch gibt, ist die Isolierung viel einfacher.

Ich denke, das Hauptanliegen hier ist wahrscheinlich die Isolation. Eine typische Maschine kann eine Menge Pods hosten, und wenn der Speicher knapp wird, könnten sie anfangen zu tauschen und die Leistung füreinander vollständig zu zerstören. Wenn es keinen Tausch gibt, ist die Isolierung viel einfacher.

Aber wie bereits erwähnt, bringt uns die Deaktivierung des Swaps hier nichts. Da es den Speicherdruck insgesamt erhöht, kann es den Kernel sogar dazu zwingen, Teile des Workingsets zu verwerfen, wenn er sonst ungenutzte Daten hätte auslagern können – was die Situation verschlimmert .

Das Aktivieren von Swap allein sollte die Isolation verbessern.

Aber es bringt Ihnen viel, wenn Sie die Dinge so ausführen, wie Sie es sollen (und wie Google die Dinge auf Borg ausführt): Alle Container sollten die obere Speichergrenze angeben. Borg nutzt die Vorteile von Google Infra und lernt die Grenzen, wenn Sie dies wünschen (aus der Ressourcennutzung in der Vergangenheit und dem OOM-Verhalten), aber es gibt trotzdem Grenzen.

Ich bin eigentlich etwas verblüfft, dass die K8S-Leute das Speicherlimit optional zugelassen haben. Im Gegensatz zur CPU hat der Speicherdruck einen sehr nichtlinearen Effekt auf die Systemleistung, wie jeder bestätigen kann, der gesehen hat, dass ein System aufgrund von Auslagerungen vollständig blockiert ist. Es sollte es wirklich standardmäßig erfordern und Sie warnen, wenn Sie es deaktivieren möchten.

Aber es bringt Ihnen viel, wenn Sie die Dinge so ausführen, wie Sie es sollen (und wie Google die Dinge auf Borg ausführt): Alle Container sollten die obere Speichergrenze angeben. Borg nutzt die Vorteile von Google Infra und lernt die Grenzen, wenn Sie dies wünschen (aus der Ressourcennutzung in der Vergangenheit und dem OOM-Verhalten), aber es gibt trotzdem Grenzen.

Ich bin eigentlich etwas verblüfft, dass die K8S-Leute das Speicherlimit optional zugelassen haben. Im Gegensatz zur CPU hat der Speicherdruck einen sehr nichtlinearen Effekt auf die Systemleistung, wie jeder bestätigen kann, der gesehen hat, dass ein System aufgrund von Auslagerungen vollständig blockiert ist. Es sollte es wirklich standardmäßig erfordern und Sie warnen, wenn Sie es deaktivieren möchten.

Ich denke, das Problem, das damit nicht behoben wird, ist, dass die Obergrenze variabel und für einige Prozesse nicht immer bekannt ist. Das Problem, mit dem ich mich beschäftige, konzentriert sich speziell auf die Verwendung von k8s zur Verwaltung von 3D-Modell-Renderer-Knoten. Abhängig von den Assets für das Modell und die Szene, die gerendert werden, kann die erforderliche RAM-Menge ziemlich unterschiedlich sein, und obwohl die meisten Renderings klein sind, bedeutet die Tatsache, dass _einige_ riesig sein können, dass unsere Anforderungen und Grenzen viel mehr Speicher reservieren müssen als wir tatsächlich 90 % der Zeit benötigen, um OOM zu vermeiden, anstatt dass der Pod gelegentlich das konfigurierte Limit überschreitet und in den Swap-Bereich überschwappen kann.

Ja, und in diesem Fall würden Sie dann Ihre Obergrenze auf "Keine" oder ähnliches setzen. Mein Punkt ist, es sollte nicht die Standardeinstellung sein. Es auf nichts zu setzen, macht jede Art von intelligentem Workload-Scheduling völlig zunichte, da der Master einfach nicht die Größe des "Items" (Jobs) kennt, das er in einen "Rucksack" (Kubelet) stecken soll.

Das Problem dabei ist nicht, dass Ihr Job zum Swap verschüttet wird, sondern dass alle anderen Jobs, die auf diesem Knoten ausgeführt werden, dies auch tun. Und einige (die meisten?) von ihnen werden es überhaupt nicht mögen.

Programme auf Borg sind so geschrieben, dass sie jederzeit präemptiv (killable, für diejenigen, die nicht mit dem Jargon vertraut sind) ohne Auswirkung auf die Datenintegrität sind. Dies ist eigentlich etwas, was ich außerhalb von Google nicht viel sehe, und wenn Sie die potenzielle plötzliche Sterblichkeit Ihres Programms anerkennen, können Sie viel zuverlässigere Software schreiben. Aber ich schweife ab.

Systeme, die mit solchen Programmen gebaut wurden, würden es viel vorziehen, dass diese Programme sterben und an anderer Stelle in der Zelle (Borg-Cluster) wieder inkarniert werden, anstatt weiterhin auf einem überzeichneten Knoten zu leiden. Die Tail-Latenz kann ansonsten sehr problematisch sein, insbesondere wenn die Anzahl der Aufgaben in einem Job groß ist.

Versteh mich nicht falsch, ich sage nicht, dass dies der einzige "richtige" Weg ist, Dinge zu erledigen. Ich versuche nur, die mögliche Begründung zu erläutern, die in das Design eingeflossen ist.

Haftungsausschluss: Ich bin ein ehemaliger Google-Mitarbeiter, der mit Borg mehrere sehr große Dienste betrieben hat, also kenne ich ihn ziemlich gut, und dieses Wissen lässt sich größtenteils auf Kubernetes übertragen. Ich bin derzeit nicht bei Google und was ich hier schreibe, sind meine eigenen Gedanken.

@1e100 : Sie

(Ich bin auch ein ehemaliger Google-SRE und ich stimme zu, dass diese gängigen Google-Mythen mit ziemlicher Sicherheit zu der Entscheidung geführt haben, dass es in Ordnung (oder sogar wünschenswert) war, den Swap auch auf k8s zu deaktivieren. Ich habe mehrere Google-Teams beim Gehen beobachtet durch die Erkenntnis, dass das Deaktivieren von Swap das Swapping nicht deaktiviert, und die aggregierte Speicherverschwendung, die sich daraus ergibt, nur eine "harte" (oom-kill) Grenze für den Speicher zu beschreiben - dies sind genau einige der Dinge, die ich mit k8s verbessern möchte gibt es jetzt eine Reihe von einstellbaren Reglern/Austausch-Knöpfen, die wir noch nicht hatten, als das Borg-Ressourcenmodell ursprünglich entworfen wurde, und ich bin überzeugt, dass wir die gewünschten Ergebnisse ohne einen solchen Ansatz zum Wegwerfen des Babys mit dem Badewasser erzielen können Ich werde auch anmerken, dass der Kompromiss von Google _oft_ im Durchschnitt weniger effizient ist, um eine bessere/bekannte Worst-Case-Zeit (dh: Echtzeitverhalten) zu erreichen, und dass dies außerhalb von Google oft _nicht_ die gewünschte Wahl ist - kleiner/ weniger Hosts, entspanntere SLOs, geringere Budgets, weniger definierte ed Batch-Jobs, mehr Verwendung von nicht kompilierten heap-ineffizienten Sprachen usw.)

Ein Austausch des anonymen Speichers findet nicht statt. Alles, was im Speicher abgebildet ist (einschließlich Programmcode und Daten) kann und wird immer noch ausgelagert, wenn Speicherdruck besteht, deshalb habe ich vorgeschlagen, dass standardmäßig RAM-Limits erforderlich sind: um die Wahrscheinlichkeit zu verringern, dass Speicherdruck überhaupt vorhanden ist. Für Workloads, die noch strengere Garantien erfordern, gibt es auch mlockall() und einen niedrigen swappiness Wert.

Als ehemaliger Google-SRE können Sie nicht argumentieren, dass es eine gute Sache ist, die obere RAM-Grenze nicht anzugeben oder Aufgaben zu ermöglichen, nach Lust und Laune zu tauschen, was sie wollen, es sei denn, Sie möchten einfach ein Konträr sein. Das Austauschen von Memory-Mapping-Dateien ist schon schlimm genug, noch mehr potenzielle Leistungsklippen in die Mischung einzubringen, ist keine gute Sache.

Dies sind vom Design her gemeinsam genutzte Umgebungen, und Sie möchten verhindern, dass Programme die Leistung der anderen unvorhersehbar machen, und nicht neue hinzufügen. Wie Google SREs sagen "Hoffnung ist keine Strategie". Swap-Thrashing ist der einfachste Weg, den ich kenne, um einen Linux-Rechner vollständig und unwiederbringlich zu blockieren, selbst wenn Sie auf SSD wechseln. Das kann nicht gut sein, selbst wenn Sie nur einen Workload auf dem Computer ausführen, geschweige denn ein paar Dutzend. Korrelierte Fehler können in kleineren Clustern mit wenigen Aufgaben/Pods besonders schmerzhaft sein.

Man kann den Swap-Check auch heute ignorieren, wenn man will, aber mit dem ausdrücklichen Verständnis, dass in diesem Fall alle Wetten aus sind.

Ja, stimme voll und ganz zu, dass wir eine "Größe" haben müssen, die wir für die Planung verwenden und um (unbeabsichtigte) Überbelegung zu vermeiden. Und wir wollen auch globalen VM-Thrash vermeiden, da Linux sich davon nur schwer erholen kann. Was wir _möchten_, ist, dass der Kernel _in der Lage ist, anonymen Speicher auszulagern und diesen RAM für etwas anderes wiederzuverwenden, wo dies sinnvoll ist, da dies einem System, das dies nicht kann, strikt überlegen ist. Im Idealfall möchten wir es einzelnen Containern ermöglichen, RAM/Disk-Kompromisse zu bewältigen und die Konsequenzen ihrer eigenen Ressourcenauswahl (über-/unterzugeordnet) mit minimalen Auswirkungen auf andere Container zu bewältigen.

Nur um zu zeigen, wohin ich damit gehe, ist mein aktueller Strohmann-Vorschlag:

  • Metapher ist, dass sich jeder Container so verhält, als wäre er auf einer eigenen Maschine mit einer bestimmten Menge an RAM (gegeben durch limits.memory ) und Swap.
  • Wie bei anderen Ressourcen: Zeitplan basierend auf requests.memory , Begrenzung basierend auf limits.memory . "Memory" bedeutet in diesem Fall "RAM" - die Nutzung des Swaps ist kostenlos.
  • Insbesondere k8s requests.memory -> cgroup memory.low (verkleinert um jeden Overcommit-Faktor); k8s limits.memory -> Kontrollgruppe memory.high .
  • Wenn ein Container sein konfiguriertes Speicherlimit überschreitet, beginnt er mit dem Auslagern - _unabhängig_ von der Menge des verfügbaren freien RAMs. Dank cgroups ist dies _nicht_ nur die VM-Nutzung, sondern umfasst auch Block-Cache, Socket-Puffer usw., die dem Container zuzuordnen sind. Dies verhindert, dass wir Speicherdruck auf andere Container (oder Hostprozesse) ausüben. Bei der Suche nach einer zu entfernenden Seite sucht der Kernel nach Containern, die ihre Speicheranforderungsgröße überschreiten.
  • Führen Sie ein Kubelet-Softlimit für die totale Swap-Nutzung ein, bei dem k8s aufhört, neue Pods auf dem Host zu planen (genau wie andere "gemeinsam genutzte Dateisysteme" wie imagefs).
  • Wenn wir das harte Limit für die Gesamt-Swap-Nutzung erreichen, beginnen Sie mit dem Entfernen von Pods basierend auf qos-Klasse/Priorität und VM-Größe über "Anfragen" (genau wie andere "gemeinsam genutzte Dateisysteme" wie imagefs).
  • Wenn ein Container sein Workingset ( requests.memory ) stark überschreitet, kann er thrashen (wenn er auch limits.memory überschreitet oder nicht genügend RAM auf dem Host verfügbar ist). Wir unternehmen _nicht_ explizit etwas dagegen über den Ressourcenmechanismus. Wenn der Container über Swap-Thrashing verfügt, schlägt er (vermutlich) fehl bei Überprüfungen der Lebendigkeit/Bereitschaft und wird durch diesen Mechanismus beendet (dh: Swap-Thrashing ist in Ordnung, wenn wir keine konfigurierten Reaktionsfähigkeits-SLAs haben).

Das Endergebnis ist, dass der Administrator dafür verantwortlich ist, auf jedem System "genug" Swap zu konfigurieren. Anwendungen sollten limits.memory mit dem _max_ RAM konfigurieren, das sie jemals verwenden möchten, und requests.memory mit ihrem beabsichtigten Arbeitssatz (einschließlich Kernelpuffer usw.). Wie bei anderen Ressourcen gelten weiterhin die QOS-Klassen garantiert (Limit==Request), Burstable (Limit undefined oder !=Request), Best-Effort (kein Limit oder Request). Dies ermutigt insbesondere Burst-Prozesse, nahe an ihrem beabsichtigten Working-Set zu deklarieren (kein großer Sicherheitspuffer), was eine effiziente Zuweisung ermöglicht (idealerweise genau 100 % des für das Working-Set zugewiesenen RAM) und eine reibungslose Leistungsverschlechterung ergibt, wenn Container diesen Wert überschreiten - genau wie andere "verzeihende" Ressourcen wie CPU.

Ich denke, dies ist in Linux-Cgroups implementierbar, adressiert die Isolationsbedenken, setzt die konzeptionellen Präzedenzfälle fort, die von anderen k8s-Ressourcen geschaffen wurden, und verschlechtert sich zum bestehenden Verhalten, wenn Swap deaktiviert ist (was die Migration erleichtert). Die einzige offene Frage, die ich habe, ist, ob dies _schon_ implementiert ist (abzüglich des "swapfs" -Kubelet-Soft- / Hard-Limits) - ich muss den eigentlichen kubelet / CRI-cgroups-Code lesen, bevor ich einen konkreten Vorschlag und Aktionspunkte schreiben kann .

Kommentare/Diskussionen zu den oben genannten Punkten sind in dieser Github-Ausgabe wahrscheinlich nicht angebracht (es ist ein schlechtes Diskussionsforum). Wenn mit dem oben Gesagten etwas schrecklich falsch ist, würde ich mich über Feedback zu guslees zu k8s Slack freuen, ansonsten werde ich ein richtiges Dokument schreiben und irgendwann die übliche Designdiskussion durchgehen.

Ich empfehle, ein formelles Dokument zu schreiben, damit wir ein besseres Diskussionsforum haben.

Einverstanden. Ich helfe gerne beim Schreiben eines KEP, da ich dafür schon einige konkrete Ideen habe, aber noch nie zuvor eine gemacht habe und lieber eine erfahrenere Hand am Ruder hätte.

Aber ich habe auch nicht die Bandbreite, um in meiner Freizeit mit einem Slack-Kanal mitzuhalten; Wenn es eine asynchronere Methode zur Koordinierung gibt, lassen Sie es mich wissen.

Nur um die Dinge am Leben zu erhalten: Ich bin immer noch sehr daran interessiert, an einem KEP und/oder einer Implementierung dafür zu arbeiten; Sobald sich die Dinge beruhigt haben (ich habe einen Workshop für das nächste Wochenende), werde ich versuchen, dem Slack-Kanal beizutreten.

Hallo, gibt es derzeit eine öffentliche Diskussion zu diesem Thema? (Der Slack von k8s steht im Moment nicht jedem offen, und ich gehe davon aus, dass dies für einige Zeit nicht der Fall sein wird).

@leonaves es gibt derzeit keine Diskussion über Slack AFAIK. der letzte Kommentar von @guslees ist der letzte der Diskussion. Beachten Sie, dass es eine KEP mit Details im kubernetes/enhancements-Repository geben muss, um die Dinge zu starten, und wahrscheinlich auch in Mailinglisten-Threads.

Auch für die lockere Wiedereröffnung scheint bald ein Ende des Tunnels zu sein. drücke die Daumen.

Wie sich herausstellt, habe ich immer noch nicht die mentale Bandbreite, um einem weiteren Slack-Kanal beizutreten. Ich würde immer noch nicht daran interessiert sein, per E-Mail daran zu arbeiten.

Ein Workaround für diejenigen, die wirklich tauschen wollen. wenn du

  • kubelet starten mit --fail-swap-on=false
  • Swap zu deinen Knoten hinzufügen
  • Container, die _keinen_ Speicherbedarf angeben, können dann standardmäßig den gesamten Maschinenspeicher verwenden, einschließlich Swap.

Das ist, was wir tun. Oder zumindest bin ich mir ziemlich sicher, dass ich es nicht persönlich umgesetzt habe, aber das ist es, was ich vermute.

Dies könnte nur dann wirklich eine praktikable Strategie sein, wenn keiner Ihrer Container jemals eine explizite Speicheranforderung angibt...

Funktioniert diese Methode nicht mehr!? Ich schalte den Swap ein und stelle einen Pod ohne Speichereinstellung bereit und habe diesen Container erhalten

$ docker inspect <dockerID> | grep Memory
            "Memory": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": -1

MemorySwap ist "0", was bedeutet, dass dieser Container nicht auf den Swap zugreifen kann :(

Die Probleme veralten nach 90 Tagen Inaktivität.
Markieren Sie das Problem mit /remove-lifecycle stale .
Veraltete Ausgaben verrotten nach weiteren 30 Tagen Inaktivität und werden schließlich geschlossen.

Wenn dieses Problem jetzt sicher geschlossen werden kann, tun Sie dies bitte mit /close .

Senden Sie Feedback an sig-testing, kubernetes/test-infra und/oder fejta .
/Lebenszyklus veraltet

/remove-lifecycle veraltet.

/Entferne-Lebenszyklus veraltet

Ich werde dies hier als weitere Referenz für die Leser dieser Ausgabe einfügen :

Die Probleme veralten nach 90 Tagen Inaktivität.
Markieren Sie das Problem mit /remove-lifecycle stale .
Veraltete Ausgaben verrotten nach weiteren 30 Tagen Inaktivität und werden schließlich geschlossen.

Wenn dieses Problem jetzt sicher geschlossen werden kann, tun Sie dies bitte mit /close .

Senden Sie Feedback an sig-testing, kubernetes/test-infra und/oder fejta .
/Lebenszyklus veraltet

/Entferne-Lebenszyklus veraltet

Diese Funktion wird in einigen Anwendungsfällen wirklich benötigt. Derzeit verwenden wir k8s für maschinelles Lernen und müssen manchmal große Modelle in den Speicher laden (in unserem Fall manchmal 500 MB pro API-Anfrage!) , und die Grenzen des physischen Speichers verursachen ernsthafte Probleme. Scale-out würde vom technischen POV aus funktionieren, aber die Kosten würden in die Höhe schießen. Wenn wir den virtuellen Speicher als Option hätten, wäre es großartig.

Gibt es eine Chance, dass dieses Ticket wieder auf die Roadmap zurückkehrt?

Klingt nach einem Fall für mmap.

Ich interessiere mich auch sehr für diese Funktion. Gibt es dazu Neuigkeiten?

Ich würde mich freuen, mich damit zu befassen, wenn ich die Zeit habe, die gerade knapp ist, aber es wäre gut, ein oder zwei kanonische Fälle zu haben, die das Problem verschärfen, damit es vollständiger charakterisiert werden kann (über "es" hinaus) beginnt zu verprügeln und alles geht zur Hölle") und der ultimative Ansatz und Fix validiert.

Jede mögliche Lösung sollte auch die Sicherheitsauswirkungen des Swaps berücksichtigen. Dies gilt natürlich für alles, was in einer Unix-Umgebung läuft, aber wenn sich die Leute daran gewöhnt haben, k8s-Pods mit einer Pseudo-Garantie ohne Swap zu betreiben, und bei der Speicherdisziplin faul geworden sind, könnte dies eine ziemlich unhöfliche Überraschung sein, wenn es aktiviert wird von Ursprünglich.

Es wäre gut, ein oder zwei kanonische Fälle zu haben, die das Problem verschärfen, damit es vollständiger charakterisiert werden kann

Das klingt nach KEP .

Jede mögliche Lösung sollte auch die Sicherheitsauswirkungen des Swaps berücksichtigen. Dies gilt natürlich für alles, was in einer Unix-Umgebung läuft, aber wenn sich die Leute daran gewöhnt haben, k8s-Pods mit einer Pseudo-Garantie ohne Swap zu betreiben, und bei der Speicherdisziplin faul geworden sind, könnte dies eine ziemlich unhöfliche Überraschung sein, wenn es aktiviert wird von Ursprünglich.

Diese Logik würde für alle Prozesse gelten, die in einer Mischung von Containern ausgeführt werden, unabhängig davon, ob Kubernetes verwendet wird oder nicht.

Einverstanden! Docker unterstützt aber bereits explizit das Ausführen mit Swap. Kubernetes tut dies ausdrücklich nicht (obwohl Sie es erzwingen können). Ich behaupte, dass es zumindest erwähnt werden sollte, weil es nicht in jedem Bedrohungsmodell ist, besonders wenn sie vorher nicht darüber nachdenken mussten.

Auch ja, @sftim , das tut es. :-) Ich denke, was ich sagen möchte, ist, dass ich gerne an einem KEP schreiben/beitragen würde, aber ich würde gerne ein oder zwei minimale Testfälle sehen, die das Problem zuverlässig auf einem bestimmten Testsystem ausüben, bevor ich mich darauf einlasse dass wir sicher sein können, die richtigen Probleme zu lösen.

@superdave was für einen Testfall hast du im Sinn?

Hier ist ein trivialer Test:

  1. Richten Sie einen Cluster mit 1 Knoten, 16 GiB RAM und 64 GiB Auslagerungsdatei ein.
  2. Versuchen Sie, 20 Pods zu planen, jeweils mit 1-GiB-Speicheranforderung und 1-GiB-Speicherlimit.
  3. Beachten Sie, dass nicht alles geplant ist.

Hier ist ein anderes:

  1. Richten Sie 6 Maschinen mit jeweils 16 GiB RAM und 64 GiB Auslagerungsdatei ein.
  2. Versuchen Sie, kubeadm mit Standardoptionen zu verwenden, um diese Maschinen als Kubernetes-Cluster zu konfigurieren.
  3. Beachten Sie, dass kubeadm nicht glücklich darüber ist, dass Swap verwendet wird.

Auf den meisten angesehenen Cloud-Plattformen gibt es jetzt eine große Verschiebung für SSD, und wenn man bedenkt, dass Linux dedizierte Optimierungen für den Austausch auf SSD hat https://lwn.net/Articles/704478/ mit zusätzlicher Komprimierungsmöglichkeit, bietet diese Situation ganz neue Möglichkeiten, Swap als zu nutzen vorhersehbare und schnelle Ressource für zusätzlichen RAM bei Speicherdruck.
Deaktivierter Swap wird zu verschwendeter Ressource, genauso wie ungenutzter RAM verschwendet wird, wenn er nicht für E/A-Puffer verwendet wird.

@superdave

Einverstanden! Docker unterstützt aber bereits explizit das Ausführen mit Swap. Kubernetes tut dies ausdrücklich nicht (obwohl Sie es erzwingen können). Ich behaupte, dass es zumindest erwähnt werden sollte, weil es nicht in jedem Bedrohungsmodell ist, besonders wenn sie vorher nicht darüber nachdenken mussten.

In diesem Fall wäre es fair davon auszugehen, dass kubelet seinen Speicherplatz mlock() verwendet und die OOM-Kill-Priorität niedrig setzt, um ein Auslagern oder das Beenden von OOM zu vermeiden, und alle Container in Gruppen mit swapiness ausführen 0 . Wenn jemand vom Form-Swapping profitieren möchte, kann er sich mit einer Option, zB enableSwapiness: 50 für bestimmte Container im Pod anmelden.
Keine Überraschungen, Batterien inklusive.

@sftim Das würde zeigen, dass a) Kubelet die Container nicht planen möchte und b) Kubelet standardmäßig nicht mit aktiviertem Swap ausgeführt wird. Was ich trainieren möchte, sind die Situationen ganz oben im Thread von

Die Unterstützung für Swap ist nicht trivial. Garantierte Pods sollten niemals ausgetauscht werden müssen. Burstable-Pods sollten ihre Anforderungen erfüllen, ohne dass ein Austausch erforderlich ist. BestEffort-Pods haben keine Garantie. Dem Kubelet fehlt derzeit die Intelligenz, um hier über Pods hinweg das richtige Maß an vorhersehbarem Verhalten bereitzustellen.

Wir haben dieses Thema Anfang des Jahres auf der Ressourcen mgmt von Angesicht zu Angesicht diskutiert. Wir sind nicht sehr daran interessiert, dies in naher Zukunft im Verhältnis zu den möglichen Gewinnen anzugehen. Wir würden es vorziehen, die Zuverlässigkeit rund um die Druckerkennung zu verbessern und Probleme rund um die Latenz zu optimieren, bevor wir versuchen, für den Swap zu optimieren, aber wenn dies für Sie eine höhere Priorität hat, würden wir uns über Ihre Hilfe freuen.

Und auch gleich darunter, von @matthiasr :

Hier gibt es mehr Kontext in der Diskussion: #7294 – Wenn Swap verfügbar ist, hat dies sehr seltsame und schlechte Interaktionen mit Speicherlimits. Zum Beispiel würde ein Container, der sein Speicherlimit erreicht, _dann_ in Swap überlaufen (dies scheint seit f4edaf2 behoben zu sein – sie dürfen keinen Swap verwenden, egal ob er vorhanden ist oder nicht).

Beide geben einen guten Überblick über die bereits gesehenen Probleme, aber es wäre gut, ein Gefühl für bekannte, reproduzierbare Szenarien zu bekommen, die die Probleme verschärfen könnten. Ich kann sie mir selbst ausdenken, aber wenn das schon jemand anderes getan hat, wäre es ein Rad, das ich nicht neu erfinden würde.

@superdave

Einverstanden! Docker unterstützt aber bereits explizit das Ausführen mit Swap. Kubernetes tut dies ausdrücklich nicht (obwohl Sie es erzwingen können). Ich behaupte, dass es zumindest erwähnt werden sollte, weil es nicht in jedem Bedrohungsmodell ist, besonders wenn sie vorher nicht darüber nachdenken mussten.

In diesem Fall wäre es fair davon auszugehen, dass kubelet seinen Speicherplatz mlock() verwendet und die OOM-Kill-Priorität niedrig setzt, um ein Auslagern oder das Beenden von OOM zu vermeiden, und alle Container in Gruppen mit swapiness ausführen 0 . Wenn jemand vom Form-Swapping profitieren möchte, kann er sich mit einer Option, zB enableSwapiness: 50 für bestimmte Container im Pod anmelden.
Keine Überraschungen, Batterien inklusive.

Ich glaube, ich stimme hier mit allem überein. Setzen Sie auf das aktuelle Verhalten, um unangenehme Überraschungen zu vermeiden.

Hier ein Beispiel, wie eine einfache Anwendung aussehen könnte, bei der aus irgendeinem Grund ein großer Teil des Speichers zugewiesen, aber nie wieder darauf zugegriffen wird. Sobald der gesamte verfügbare Speicher aufgefüllt ist, hängt die Anwendung entweder auf oder gerät in eine Endlosschleife, die im Grunde Ressourcen blockiert oder den Killer für unzureichenden Speicher erzwingt:

#include <iostream>
#include <vector>
#include <unistd.h>
int main() {
  std::vector<int> data;
  try
    {
        while(true) { data.resize(data.size() + 200); };
    }
    catch (const std::bad_alloc& ex)
    {
        std::cerr << "Now we filled up memory, so assume we never access that stuff again and just moved on, or we're stuck in an endless loop of some sort...";
        while(true) { usleep(20000); };
    }
  return 0;
}

Ein Workaround für diejenigen, die wirklich tauschen wollen. wenn du

  • kubelet starten mit --fail-swap-on=false
  • Swap zu deinen Knoten hinzufügen
  • Container, die _keinen_ Speicherbedarf angeben, können dann standardmäßig den gesamten Maschinenspeicher verwenden, einschließlich Swap.

Das ist, was wir tun. Oder zumindest bin ich mir ziemlich sicher, dass ich es nicht persönlich umgesetzt habe, aber das ist es, was ich vermute.

Dies könnte nur dann wirklich eine praktikable Strategie sein, wenn keiner Ihrer Container jemals eine explizite Speicheranforderung angibt...

Hallo @hjwp , danke für

Darf ich danach eine Frage stellen?

Gibt es eine Möglichkeit, die Verwendung des Swap-Speichers durch Container zu begrenzen, nachdem Sie alles eingerichtet haben, wie Sie es gesagt haben?

Ich habe darüber nachgedacht, --memory-swap Parameter von Docker zu setzen
https://docs.docker.com/config/containers/resource_constraints/# --memory-swap-details
Derzeit hat mein Container keine Begrenzung der Swap-Nutzung ( "MemorySwap": -1 )

sudo docker inspect 482d70f73c7c | grep Memory
            "Memory": 671088640,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": -1,
            "MemorySwappiness": null,

Aber ich konnte diesen Parameter in k8s nicht finden.

Wird das Limit des Pod-Speichers übrigens auch die Swap-Nutzung einschränken?

Meine VM-bezogenen Einstellungen

vm.overcommit_kbytes = 0
vm.overcommit_memory = 1
vm.overcommit_ratio = 50
vm.swappiness = 20
vm.vfs_cache_pressure = 1000

Dankeschön!

@pai911 Ich glaube nicht, dass das möglich ist,

Derzeit unterstützt CRI das nicht, siehe dies , es gibt keine Option wie --memory-swap im Docker

Dies ist jedoch eine CRI-Einschränkung, OCI-Spezifikationen unterstützen diese Option, werden jedoch nicht in die CRI-Ebene exportiert

Eine mögliche (theoretische) Lösung besteht darin, ein privilegiertes DaemonSet zu erstellen, das wiederum die Anmerkungsdaten aus den Pods liest, und dann das DaemonSet den cgroup-Wert manuell bearbeitet

Kontrollgruppe

Hallo @win-t,

Danke für die Bewertung!

Also ist diese Option vorerst nur für den internen Gebrauch?

Wissen Sie zufällig, welcher Kontrollgruppenwert dieser --memory-swap-Option zugeordnet ist?

Also ist diese Option vorerst nur für den internen Gebrauch?

Ja, Sie können diese Option nicht einstellen, da sie in k8s nicht angezeigt werden

btw, MemorySwap inspiziert in Docker sollte gleich sein mit Memory nach dieser , ich weiß nicht , wie Sie bekommen können -1 in Ihrem Docker inspiziert

Wissen Sie zufällig, welcher Kontrollgruppenwert dieser --memory-swap-Option zugeordnet ist?

  • --memory in Docker-Map zu memory.limit_in_bytes in Kontrollgruppe v1
  • --memory-swap in Docker-Map zu memory.memsw.limit_in_bytes in Kontrollgruppe v1

@win-t Vielen Dank!

Ich verwende die folgende Version

Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:16:51Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.10", GitCommit:"1bea6c00a7055edef03f1d4bb58b773fa8917f11", GitTreeState:"clean", BuildDate:"2020-02-11T20:05:26Z", GoVersion:"go1.12.12", Compiler:"gc", Platform:"linux/amd64"}

und ich habe mir die geschichte angeschaut. es scheint, dass der Fix in diesem Commit hinzugefügt wurde

Vielleicht ist es nicht in der Version enthalten, die ich verwende?

Also ist diese Option vorerst nur für den internen Gebrauch?

Ja, Sie können diese Option nicht einstellen, da sie in k8s nicht angezeigt werden

btw, MemorySwap inspiziert in Docker sollte gleich sein mit Memory nach dieser , ich weiß nicht , wie Sie bekommen können -1 in Ihrem Docker inspiziert

Wissen Sie zufällig, welcher Kontrollgruppenwert dieser --memory-swap-Option zugeordnet ist?

  • --memory in Docker-Map zu memory.limit_in_bytes in Kontrollgruppe v1
  • --memory-swap in Docker-Map zu memory.memsw.limit_in_bytes in Kontrollgruppe v1

Das ist komisch.

Ich habe kops + Debian verwendet und der Docker-Inspect zeigt, dass es keine Begrenzung für den Swap-Speicher gibt
(Die Docker-Inspect-Informationen, die ich zuvor gepostet habe)

Aber dann bin ich auf das Amazon Linux-Image umgestiegen und das habe ich bekommen

            "Memory": 671088640,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 671088640,
            "MemorySwappiness": null,

Ich werde weitere Nachforschungen anstellen und sehen, ob dies ein Fehler ist

Also ist diese Option vorerst nur für den internen Gebrauch?

Ja, Sie können diese Option nicht einstellen, da sie in k8s nicht angezeigt werden
btw, MemorySwap inspiziert in Docker sollte gleich sein mit Memory nach dieser , ich weiß nicht , wie Sie bekommen können -1 in Ihrem Docker inspiziert

Wissen Sie zufällig, welcher Kontrollgruppenwert dieser --memory-swap-Option zugeordnet ist?

  • --memory in Docker-Map zu memory.limit_in_bytes in Kontrollgruppe v1
  • --memory-swap in Docker-Map zu memory.memsw.limit_in_bytes in Kontrollgruppe v1

Das ist komisch.

Ich habe kops + Debian verwendet und der Docker-Inspect zeigt, dass es keine Begrenzung für den Swap-Speicher gibt
(Die Docker-Inspect-Informationen, die ich zuvor gepostet habe)

Aber dann bin ich auf das Amazon Linux-Image umgestiegen und das habe ich bekommen

            "Memory": 671088640,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 671088640,
            "MemorySwappiness": null,

Ich werde weitere Nachforschungen anstellen und sehen, ob dies ein Fehler ist

Ich kann jetzt reproduzieren, dass das Problem im offiziellen Debian-Image von kops existiert

Es scheint, dass dieses offizielle Image des kops den Swap-Speicher unbegrenzt machen wird
kope.io/k8s-1.15-debian-stretch-amd64-hvm-ebs-2020-01-17

Reproduktionsschritte:

Meine kops-Instanzgruppe ist wie folgt definiert:

apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: "2020-03-12T06:33:09Z"
  generation: 5
  labels:
    kops.k8s.io/cluster: solrcluster.k8s.local
  name: node-2
spec:
  additionalUserData:
  - content: |
      #!/bin/sh
      sudo cp /etc/fstab /etc/fstab.bak
      sudo mkfs -t ext4 /dev/nvme1n1
      sudo mkdir /data
      sudo mount /dev/nvme1n1 /data
      echo '/dev/nvme1n1       /data   ext4    defaults,nofail        0       2' | sudo tee -a /etc/fstab
      sudo fallocate -l 2G /data/swapfile
      sudo chmod 600 /data/swapfile
      sudo mkswap /data/swapfile
      sudo swapon /data/swapfile
      echo '/data/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
      sudo sysctl vm.swappiness=10
      sudo sysctl vm.overcommit_memory=1
      echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
      echo 'vm.overcommit_memory=1' | sudo tee -a /etc/sysctl.conf
    name: myscript.sh
    type: text/x-shellscript
  image: kope.io/k8s-1.15-debian-stretch-amd64-hvm-ebs-2020-01-17
  instanceProtection: true
  kubelet:
    failSwapOn: false
  machineType: t3.micro

Schritte:

  1. Nachdem der Cluster betriebsbereit ist.

  2. Stellen Sie das Solr-Helm-Diagramm mit der folgenden Ressourceneinstellung bereit

resources:
  limits:
    cpu: "1"
    memory: 640Mi
  requests:
    cpu: 100m
    memory: 256Mi

** Jeder andere Pod sollte auch funktionieren

  1. Container auflisten, um eine Container-ID zu finden
    sudo docker container ls

  2. Überprüfen Sie die Speicherparameter eines Containers
    sudo docker inspect d67a72bba427 | grep Memory

            "Memory": 671088640,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": -1,
            "MemorySwappiness": null,

Soll ich das Problem irgendwo einreichen? k8s oder kops?

Schritte:

  1. Nachdem der Cluster betriebsbereit ist.
  2. Stellen Sie das Solr-Helm-Diagramm mit der folgenden Ressourceneinstellung bereit
resources:
  limits:
    cpu: "1"
    memory: 640Mi
  requests:
    cpu: 100m
    memory: 256Mi

** Jeder andere Pod sollte auch funktionieren

  1. Container auflisten, um eine Container-ID zu finden
    sudo docker container ls
  2. Überprüfen Sie die Speicherparameter eines Containers
    sudo docker inspect d67a72bba427 | grep Memory
            "Memory": 671088640,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": -1,
            "MemorySwappiness": null,

Soll ich das Problem irgendwo einreichen? k8s oder kops?

Ich kann bestätigen, dass ich das korrekte Verhalten nur unter Amazon Linux sehen kann
ami-0cbc6aae997c6538a : amzn2-ami-hvm-2.0.20200304.0-x86_64-gp2

            "Memory": 671088640,
            "CpusetMems": "",
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 671088640,
            "MemorySwappiness": null,

Das heißt: "MemorySwap" == "Memory"

Die anderen beiden Bilder haben beide die gleiche Einstellung: "MemorySwap": -1 , was zu einer unbegrenzten Swap-Nutzung führt.

  • Debian

    • ami-075e61ad77b1269a7 : k8s-1.15-debian-stretch-amd64-hvm-ebs-2020-01-17

  • Ubuntu

    • ami-09a4a9ce71ff3f20b : ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-20200112

Ich denke also, es könnte das Problem von k8s sein?

Benutzergeschichten:

(1) Mein vom Anbieter bereitgestelltes Programm verwendet eine Sprachlaufzeit, die den Zugriff auf den Quellcode des Programmcodes vorschreibt. Aus diesem Grund wird während der Initialisierung der gesamte Programmquellcode in einer separaten Speicherarena angeordnet. Sobald das Programm initialisiert ist und der Container bereit wird, wird auf diesen Speicher nicht mehr zugegriffen (Sie können dies nicht beweisen, aber es wird nicht gehen). Darüber hinaus weist das Programm einige Seiten zu, die für die benutzerdefinierte OOM-Bearbeitung reserviert werden. Dieser Speicher kann ausgelagert werden. Ich möchte nicht, dass dieser "tote Speicher" andere Clusteranwendungen verdrängt. Ich kann die Speichermenge, die tot wird, genau berechnen und als Swap-Anfrage in der Pod-Spezifikation auflisten.

(2) Ich führe eine Arbeitslast für maschinelles Lernen oder Datenanalyse aus, bei der die Speichernutzung plötzlich anschwellen und zurückgehen kann. Es ist in Ordnung, wenn diese Anwendungen langsamer werden, solange sie nicht beendet und schließlich beendet werden. Ich möchte den Cluster mit Swap bereitstellen, um Räumungen zu vermeiden, wenn diese Speicherballons auftreten. Diese Pods hätten geringe Anforderungen an Speicher und Swap, ein moderates Speicherlimit – vielleicht genug für Baseline + ein Workingset – und ein großes Swap-Limit.

(3) Ich betreibe einen Webserver in einem Interpreter (zB Ruby on Rails), der gelegentlich fork+exec benötigt. Eine strikte Speicherabrechnung führt zu inakzeptablen Fork-Fehlern. Ich möchte Swap bereitstellen, damit der Kernel die garantierte Speicherreserve hat, um das Prozessverhalten zwischen den fork- und exec-Aufrufen abzudecken. Der Wert vm.swappiness kann so eingestellt werden, dass er den Austausch extrem verhindert, und ich richte Warnungen ein, um Operationen zu benachrichtigen, wenn der Swap tatsächlich während der Produktion verwendet wird. Die Pod-Spezifikation würde die Swap-Anfrage und das Limit auf denselben Wert setzen.

Vor kurzem haben wir versucht, alle unsere Docker-basierten Dienste in Kubernetes zu migrieren, mussten das Projekt jedoch abbrechen, da Swap nicht unterstützt wird.

Wir haben festgestellt, dass wir die dreifache Menge an Hardware bereitstellen müssen, um genau die gleiche Anzahl von Containern zu unterstützen, die wir derzeit mit aktiviertem Swap ausführen.

Das Hauptproblem besteht darin, dass unsere Arbeitslast aus einer Reihe von Containern besteht, die bis zu 1 GB Speicher (oder Swap) verwenden können, aber normalerweise etwa 50 MB im normalen Betrieb verwenden.

Da wir nicht in der Lage waren, auszutauschen, mussten wir alles für die größtmögliche Last entwerfen, die es möglicherweise verarbeiten musste, anstatt einen Swap-Block zur Verfügung zu haben, wenn große „Aufträge“ bearbeitet werden mussten.

Wir haben unsere Migration zu Kubernetes letztendlich abgebrochen und haben stattdessen vorübergehend alles auf Swarm verschoben, in der Hoffnung, dass Swap in Zukunft unterstützt wird.

Das Hauptproblem besteht darin, dass unsere Arbeitslast aus einer Reihe von Containern besteht, die bis zu 1 GB Speicher (oder Swap) verwenden können, aber normalerweise etwa 50 MB im normalen Betrieb verwenden.

Man könnte sagen, dass die Anwendungen, die in diesen Containern laufen, unglaublich schlecht geschrieben sind.

Man könnte sagen, dass die Anwendungen, die in diesen Containern laufen, unglaublich schlecht geschrieben sind.

Das ist irgendwie irrelevant, und Fingerzeigen ist selten konstruktiv. Das Kubernetes-Ökosystem ist so konzipiert, dass es eine Vielzahl von Anwendungsprofilen unterstützt, und es macht wenig Sinn, eines davon herauszugreifen.

Das Hauptproblem besteht darin, dass unsere Arbeitslast aus einer Reihe von Containern besteht, die bis zu 1 GB Speicher (oder Swap) verwenden können, aber normalerweise etwa 50 MB im normalen Betrieb verwenden.

Man könnte sagen, dass die Anwendungen, die in diesen Containern laufen, unglaublich schlecht geschrieben sind.

lol, dies ist eine Kernel-Funktion, eine Anwendung kann madvise(2) für die shm-Datei verwenden und wir blockieren den Madvise-Systemaufruf nicht.
Daher ist es für den Benutzer berechtigt, diese Funktion für sein Design zu nutzen, Sie können nicht sagen "sind unglaublich schlecht geschrieben",

Das Hauptproblem besteht darin, dass unsere Arbeitslast aus einer Reihe von Containern besteht, die bis zu 1 GB Speicher (oder Swap) verwenden können, aber normalerweise etwa 50 MB im normalen Betrieb verwenden.

Man könnte sagen, dass die Anwendungen, die in diesen Containern laufen, unglaublich schlecht geschrieben sind.

Ihre Antwort zeigt an, dass Sie die Workloads, mit denen viele Entwickler arbeiten, nicht verstehen.

Der von mir erwähnte Arbeitsaufwand beschäftigt sich mit unterschiedlich großen Datensätzen, die von Benutzern bereitgestellt werden, daher die große Bandbreite an möglicherweise Ressourcenanforderungen.

Sicher, wir _könnten_ speicherzugeordnete Dateien verwenden, um die Speichernutzung konsistent zu halten. Dann müssten wir dann alle Bibliotheken neu schreiben, um die Speicherzuordnung selbst zu verwenden, was mehr oder weniger jede vorhandene Bibliothek einschließen würde ... je.

Aber dann hätten wir eine im Wesentlichen anwendungsspezifische Auslagerungsdatei erstellt, die mit ziemlicher Sicherheit schlechter abschneiden würde als eine vom Kernel verwaltete.

Einige Kubernetes-Bereitstellungen müssen ausgetauscht werden

Ich habe einen gültigen Anwendungsfall - ich entwickle ein lokales Produkt, eine Linux-Distribution, die in kubeadm enthalten ist. keine horizontale Skalierung durch Design. Um opportunistische Speicherspitzen zu überstehen und trotzdem (aber langsam) zu funktionieren, brauche ich definitiv swap .

So installieren Sie kubeadm mit aktiviertem Swap

  1. Erstellen Sie eine Datei in /etc/systemd/system/kubelet.service.d/20-allow-swap.conf mit dem Inhalt:

    [Service]
    Environment="KUBELET_EXTRA_ARGS=--fail-swap-on=false"
    
  2. Lauf

    sudo systemctl daemon-reload
    
  3. Initialisieren Sie kubeadm mit dem Flag --ignore-preflight-errors=Swap

    kubeadm init --ignore-preflight-errors=Swap
    

https://stackoverflow.com/a/62158455/3191896

Als naiver Softwareentwickler erscheint es mir völlig vernünftig, dass System-Pods mit zeitkritischen Workloads ein Nicht-Swap-Verhalten anfordern und andere Workloads (standardmäßig) in eine Best-Effort-Kategorie geschoben werden. Würde das nicht alle Bedenken lösen?

Für meinen eigenen Bedarf profitieren viele meiner Apps von Caches. Wenn eine App jedoch plötzlich viel Speicher benötigt, ist es vorzuziehen, den ältesten Cache auf die Festplatte zu verschieben, wenn diese Apps nicht auf eine Anforderung reagieren, um den Speicherdruck zu verringern, als den neuen Workload keinen Speicher mehr zu haben oder zu haben um den Burst mit physischem Speicher zu unterstützen + mehr für rollierende Bereitstellungen + mehr für einen potenziellen Knotenausfall.

@metatic sagte:

Sicher, wir könnten speicherzugeordnete Dateien verwenden, um die Speichernutzung konsistent zu halten. Dann müssten wir dann alle Bibliotheken neu schreiben, um die Speicherzuordnung selbst zu verwenden, was mehr oder weniger jede vorhandene Bibliothek einschließen würde ... je.

Die Linux-Standard-C-Bibliothek wurde entwickelt, um den Speicherzuordner zu ersetzen; die malloc , realloc und free werden zu diesem Zweck durch Zeiger aufgerufen. Sie könnten also einfach eine Bibliothek LD_PRELOAD, die sie überschreiben würde, um aus einer mmapped-Datei zuzuordnen.

Aber dann hätten wir eine im Wesentlichen anwendungsspezifische Auslagerungsdatei erstellt, die mit ziemlicher Sicherheit schlechter abschneiden würde als eine vom Kernel verwaltete.

Es würde tatsächlich genau wie normaler Swap ausgeführt werden, da es von demselben Code im Kernel verwaltet würde. Der einzige Unterschied wäre das Fehlen eines Swappiness-Parameters, um seine Priorität anzupassen.

Die einzige offene Frage, die ich habe, ist, ob dies bereits implementiert ist (abzüglich des "swapfs" kubelet soft/hard limit) - ich muss den eigentlichen kubelet/CRI cgroups-Code lesen, bevor ich einen konkreten Vorschlag und Maßnahmen schreiben kann .

@anguslees ,
Sind Sie jemals dazu gekommen, das Verhalten zu überprüfen. Wenn ja, können Sie bitte eine Auflösung oder einen Link zu einer hinzufügen?

Vielen Dank,
Jan

Sind Sie jemals dazu gekommen, das Verhalten zu überprüfen. Wenn ja, können Sie bitte eine Auflösung oder einen Link zu einer hinzufügen?

Ich habe nicht. (Ich habe mich ein wenig mit dem Docker-Code beschäftigt, aber ich habe ihn inzwischen ganz vergessen und müsste wieder von vorne beginnen)

Andere Freiwillige sind willkommen! Ich hoffe, ich habe nicht jemandem den Sauerstoff gestohlen, indem ich sagte, ich würde daran arbeiten und es dann nicht durchziehen :(

Um die Geschichte von @metatick hinzuzufügen:

Ich verwende derzeit Gigalixir als meinen Host, der auf Kubernetes läuft. Es ist eine Web-App. Manchmal laden Kunden einen Stapel von Fotos hoch, sodass meine App eine Reihe (hässlicher) ImageMagick-Prozesse hochfährt, um ihre Größe zu ändern. Die Speicherauslastung steigt, der OOM-Killer wird ausgelöst und meine App geht (kurz) aus und der Upload ist ruiniert.

Am Ende muss ich Gigalixir Tonnen mehr zahlen, als ich sollte, nur wegen des spitzen Verbrauchs. Wie andere schon erwähnt haben.

Vielleicht mögen Sie den Tausch aus gestalterischer Sicht nicht, aber Ihre Entscheidung kostet Geschäftsleute Geld... und es ist verschwenderisch.

Bitte repariere. :)

Das ist auch für mich ein sehr großes Thema. In meinem Anwendungsfall müsste ich Pods ausführen, die die meiste Zeit ~ 100 MB verbrauchen, aber von Zeit zu Zeit, wenn ein Benutzer bestimmte Ereignisse auslöst, kann es für einige Minuten bis zu 2 GB RAM platzen, bevor es zurückfällt (und nein, es liegt nicht daran, dass es schlecht geschrieben ist, es ist die Realität der Arbeitsbelastung).
Ich führe fast hundert solcher Workloads gleichzeitig auf 16-GB-Rechnern mit Swap aus. Ich kann diese Arbeitslast einfach nicht auf Kubernetes verschieben, weil das überhaupt nicht funktionieren würde. Im Moment habe ich also meinen eigenen Orchestrator, der diese Workloads auf Nicht-Kubernetes-Systemen ausführt, während meine Hauptanwendung in Kubernetes ausgeführt wird, und er verfehlt den Zweck meiner Migration zu k8s. Ohne Swap wird es entweder beendet, oder ich muss immer viel verfügbaren RAM für die wenigen Minuten verschwenden, in denen die Apps möglicherweise (oder nicht) platzen.

Wenn Sie ein CPU-Limit festlegen können, das die CPU für einen Pod drosselt, sollten Sie in der Lage sein, ein Speicherlimit festzulegen, das den von einem Pod verwendeten Speicher drosselt. Einen Pod zu töten, wenn er das Speicherlimit erreicht, ist genauso lächerlich, wie einen zu töten, wenn er mehr CPU-Ressourcen verbraucht als das festgelegte CPU-Limit (sorry, aber nicht jeder Pod ist eine Nachbildung, die ohne Konsequenzen heruntergefahren werden kann).

Kubernetes kann nicht mit Swap-Set auf dem Knoten arbeiten, da dies die gesamte Leistung des gesamten Clusters beeinträchtigen kann, gut (obwohl ich das nicht für ein gültiges Argument halte). Idealerweise müsste der Pod selbst über eine Auslagerungsdatei auf Pod-Ebene verfügen, in die nur die Prozesse innerhalb dieser Container ausgelagert werden. Dies würde theoretisch die RAM-Auslastung und Leistung (aufgrund des Swappings) der Pods drosseln, die ihre Speichergrenzen überschreiten, genau wie CPU-Limits sie drosseln.
Leider sieht es nicht so aus, als könnten Cgroups eine Auslagerungsdatei angeben, nur ihre Auslagerung, und Sie können dem Kernel nicht sagen, dass er "auswechseln sollte, wenn die Speichernutzung über dieser Grenze liegt", da er stattdessen scheint zu entscheiden, wann er basierend auf dem letzten auswechseln soll Zugriff und andere Metriken.

Aber warum lassen Sie in der Zwischenzeit nicht Swap auf einem Knoten existieren, setzen Sie swappiness auf 0 für die Pods, für die kein Limit festgelegt ist, und wenn ein Limit festgelegt ist (oder ein anderes Spezifikationsfeld mit "swapInsteadOfKill"), setzen Sie das Swappiness auf einen Wert ungleich Null?

Neben der Diskussion um "Swap or not to swap" macht es mich neugierig, dass das von @pai911 beschriebene Verhalten vom k8s-Team nicht weiter adressiert wurde.

Ich kann bestätigen, dass sich Kubelet in Bezug auf die Docker-Deamon-Speichereinstellungen anders zu verhalten scheint (und auf einigen Betriebssystemen nicht gemäß dem oben genannten Code). Unsere Cluster laufen unter SUSE Linux und wir erleben die gleiche unbegrenzte Swap-Nutzung, die in https://github.com/kubernetes/kubernetes/issues/53533#issuecomment -598056151 erwähnt wird

Betriebssystemdetails: SUSE Linux Enterprise Server 12 SP4 - Linux 4.12.14-95.45-default

Ohne die richtige Unterstützung für Swap in k8s würde ich mir zumindest wünschen, dass kubelet die Docker-Speichereinstellungen unabhängig vom zugrunde liegenden Betriebssystem konsistent behandelt.

Ich habe Swap auf die Tagesordnung gesetzt, um zu sehen, ob die Community Appetit hat oder Freiwillige helfen, dies in 1.21 voranzutreiben. Ich habe keine Einwände gegen die Unterstützung von Swap, wie ich 2017 festgestellt habe. All diese Dinge sind wichtig, um sicherzustellen, dass Pods tragbar sind.

In letzter Zeit wurde viel Energie darauf verwendet, Dinge wie NUMA-ausgerichtetes Gedächtnis zum Laufen zu bringen, aber wenn es Leute gibt, die weniger leistungssensitiv und gleichermaßen motiviert sind, diesen Bereich voranzutreiben, würden wir gerne helfen, einen Vorsprung beim Design von . zu bekommen detaillierte KEP in diesem Bereich.

Ich habe den Community-Prozess in letzter Zeit nicht besonders gut mitgehalten, da die Dinge in letzter Zeit für mich sehr beschäftigt waren, aber es sieht so aus, als ob sie sich bald etwas beruhigen sollten. Gibt es eine Möglichkeit, mich zu engagieren, ohne einem Slack-Kanal beitreten zu müssen?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen