Kubernetes: Beschleunigen Sie Ihre Dienste, indem Sie CPU-Limits entfernen

Im Jahr 2016 waren wir bei Buffer auf Kubernetes umgestiegen, und jetzt arbeiten etwa 60 Knoten (auf AWS) und 1500 Container in unserem von verwalteten k8s-Cluster Kops. Wir sind jedoch durch Versuch und Irrtum zu Microservices übergegangen, und selbst nach mehreren Jahren der Arbeit mit k8s stehen wir immer noch vor neuen Problemen. In diesem Beitrag werden wir darüber sprechen Einschränkungen des Prozessors: Warum wir sie für eine gute Übung hielten und warum sie am Ende nicht so gut waren.

Prozessoreinschränkungen und Drosselung

Wie viele andere Kubernetes-Benutzer auch Google empfiehlt dringend, CPU-Limits festzulegen. Ohne eine solche Einstellung können Container in einem Knoten die gesamte Prozessorleistung beanspruchen, was wiederum dazu führt, dass wichtige Kubernetes-Prozesse (z. B kubelet) reagiert nicht mehr auf Anfragen. Daher ist das Festlegen von CPU-Grenzwerten eine gute Möglichkeit, Ihre Knoten zu schützen.

Prozessorlimits legen einen Container auf die maximale CPU-Zeit fest, die er für einen bestimmten Zeitraum nutzen kann (Standard ist 100 ms), und der Container wird dieses Limit niemals überschreiten. In Kubernetes für Drosselung Um den Behälter vor Überschreitung des Grenzwerts zu schützen, wird ein Spezialwerkzeug verwendet CFS-Kontingent, aber diese künstlichen CPU-Grenzwerte beeinträchtigen letztendlich die Leistung und verlängern die Reaktionszeit Ihrer Container.

Was kann passieren, wenn wir keine Prozessorgrenzen festlegen?

Leider mussten auch wir uns diesem Problem stellen. Jeder Knoten verfügt über einen Prozess, der für die Verwaltung von Containern verantwortlich ist kubelet, und er reagierte nicht mehr auf Anfragen. Wenn dies geschieht, geht der Knoten in den Zustand über NotReady, und Container daraus werden an einen anderen Ort umgeleitet und verursachen die gleichen Probleme auf neuen Knoten. Kein ideales Szenario, gelinde gesagt.

Manifestation des Problems der Drosselung und Reaktion

Die Schlüsselmetrik für die Containerverfolgung ist trottling, es zeigt an, wie oft Ihr Container gedrosselt wurde. Wir haben mit Interesse festgestellt, dass es in einigen Containern zu Throttling kommt, unabhängig davon, ob die Prozessorauslastung extrem war oder nicht. Schauen wir uns als Beispiel eine unserer Haupt-APIs an:

Kubernetes: Beschleunigen Sie Ihre Dienste, indem Sie CPU-Limits entfernen

Wie Sie unten sehen können, haben wir das Limit auf festgelegt 800m (0.8 oder 80 % Kern) und Spitzenwerte bestenfalls erreichen 200m (20 % Kern). Es scheint jedoch, dass wir vor der Drosselung des Dienstes noch über ausreichend Prozessorleistung verfügen ...

Kubernetes: Beschleunigen Sie Ihre Dienste, indem Sie CPU-Limits entfernen
Möglicherweise ist Ihnen aufgefallen, dass es auch dann zu einer Drosselung kommt, wenn die Prozessorauslastung unter den angegebenen Grenzwerten liegt – deutlich darunter.

Angesichts dieser Tatsache entdeckten wir bald mehrere Ressourcen (Problem auf Github, Präsentation über Zadano, Beitrag auf Omio) über den Leistungs- und Reaktionszeitabfall von Diensten aufgrund der Drosselung.

Warum kommt es bei geringer CPU-Auslastung zu einer Drosselung? Die Kurzfassung lautet: „Es gibt einen Fehler im Linux-Kernel, der zu einer unnötigen Drosselung von Containern mit bestimmten Prozessorgrenzen führt.“ Wenn Sie sich für die Art des Problems interessieren, können Sie die Präsentation lesen (Video и Text Optionen) von Dave Chiluk.

CPU-Einschränkungen entfernen (mit äußerster Vorsicht)

Nach langen Diskussionen haben wir beschlossen, Prozessoreinschränkungen von allen Diensten zu entfernen, die sich direkt oder indirekt auf wichtige Funktionen unserer Benutzer auswirken.

Die Entscheidung fiel uns nicht leicht, da wir großen Wert auf die Stabilität unseres Clusters legen. In der Vergangenheit haben wir bereits mit der Instabilität unseres Clusters experimentiert, und dann haben die Dienste zu viele Ressourcen verbraucht und die Arbeit ihres gesamten Knotens verlangsamt. Jetzt war alles etwas anders: Wir hatten eine klare Vorstellung davon, was wir von unseren Clustern erwarteten, und eine gute Strategie zur Umsetzung der geplanten Änderungen.

Kubernetes: Beschleunigen Sie Ihre Dienste, indem Sie CPU-Limits entfernen
Geschäftskorrespondenz zu einem drängenden Thema.

Wie können Sie Ihre Knoten schützen, wenn die Beschränkungen aufgehoben werden?

Isolierung „uneingeschränkter“ Dienste:

In der Vergangenheit haben wir bereits gesehen, dass einige Knoten in einen Zustand geraten sind notReady, hauptsächlich aufgrund von Diensten, die zu viele Ressourcen verbrauchten.

Wir haben beschlossen, solche Dienste in separaten („gekennzeichneten“) Knoten zu platzieren, damit sie „verwandte“ Dienste nicht beeinträchtigen. Durch die Markierung einiger Knoten und das Hinzufügen des Toleranzparameters zu „nicht verwandten“ Diensten erreichten wir dadurch eine bessere Kontrolle über den Cluster und es wurde für uns einfacher, Probleme mit Knoten zu identifizieren. Um ähnliche Prozesse selbst durchzuführen, können Sie sich damit vertraut machen Dokumentation.

Kubernetes: Beschleunigen Sie Ihre Dienste, indem Sie CPU-Limits entfernen

Zuweisen einer korrekten Prozessor- und Speicheranforderung:

Unsere größte Angst war, dass der Prozess zu viele Ressourcen verbrauchen würde und der Knoten nicht mehr auf Anfragen reagieren würde. Da wir nun (dank Datadog) alle Dienste in unserem Cluster klar überwachen konnten, habe ich mehrere Monate lang den Betrieb derjenigen analysiert, die wir als „nicht verwandt“ bezeichnen wollten. Ich habe einfach die maximale CPU-Auslastung mit einer Marge von 20 % festgelegt und so Speicherplatz im Knoten zugewiesen, für den Fall, dass k8s versucht, dem Knoten andere Dienste zuzuweisen.

Kubernetes: Beschleunigen Sie Ihre Dienste, indem Sie CPU-Limits entfernen

Wie Sie in der Grafik sehen können, ist die maximale Belastung des Prozessors erreicht 242m CPU-Kerne (0.242 Prozessorkerne). Für eine Prozessoranforderung reicht es aus, eine Zahl zu nehmen, die etwas größer als dieser Wert ist. Bitte beachten Sie, dass die Spitzenlastwerte mit dem Datenverkehr übereinstimmen, da die Dienste benutzerzentriert sind.

Machen Sie dasselbe mit der Speichernutzung und den Abfragen, und voilà – schon sind Sie fertig! Für mehr Sicherheit können Sie eine horizontale Pod-Autoskalierung hinzufügen. Jedes Mal, wenn die Ressourcenlast hoch ist, erstellt die automatische Skalierung neue Pods und Kubernetes verteilt sie an Knoten mit freiem Speicherplatz. Falls im Cluster selbst kein Platz mehr vorhanden ist, können Sie sich eine Warnung einrichten oder das Hinzufügen neuer Knoten über deren automatische Skalierung konfigurieren.

Von den Minuspunkten ist anzumerken, dass wir verloren haben in „Behälterdichte", d.h. Anzahl der Container, die auf einem Knoten laufen. Bei geringer Verkehrsdichte kann es auch zu vielen „Entspannungen“ kommen, und es besteht auch die Möglichkeit, dass Sie eine hohe Prozessorauslastung erreichen, aber Autoscaling-Knoten sollten bei Letzterem Abhilfe schaffen.

Ergebnisse

Ich freue mich, diese hervorragenden Ergebnisse der Experimente der letzten Wochen veröffentlichen zu können. Wir haben bereits deutliche Verbesserungen bei der Reaktion bei allen geänderten Diensten festgestellt:

Kubernetes: Beschleunigen Sie Ihre Dienste, indem Sie CPU-Limits entfernen

Die besten Ergebnisse haben wir auf unserer Homepage erzielt (puffer.com), dort beschleunigte sich der Dienst zweiundzwanzig Mal!

Kubernetes: Beschleunigen Sie Ihre Dienste, indem Sie CPU-Limits entfernen

Ist der Linux-Kernel-Fehler behoben?

Ja, Der Fehler wurde bereits behoben und der Fix wurde dem Kernel hinzugefügt Distributionen Version 4.19 und höher.

Allerdings beim Lesen Kubernetes-Probleme auf Github für den 2020. September XNUMX Wir stoßen immer noch auf Erwähnungen einiger Linux-Projekte mit einem ähnlichen Fehler. Ich glaube, dass einige Linux-Distributionen diesen Fehler immer noch haben und gerade daran arbeiten, ihn zu beheben.

Wenn Ihre Distributionsversion niedriger als 4.19 ist, würde ich ein Update auf die neueste Version empfehlen, aber Sie sollten auf jeden Fall versuchen, die Prozessoreinschränkungen zu entfernen und prüfen, ob die Drosselung weiterhin besteht. Unten sehen Sie eine unvollständige Liste der Kubernetes-Verwaltungsdienste und Linux-Distributionen:

  • Debian: Fix in die neueste Version der Distribution integriert, Buster, und sieht ziemlich frisch aus (August 2020 Jahre). Einige frühere Versionen können ebenfalls behoben werden.
  • Ubuntu: Fix in neueste Version integriert Ubuntu Focal Fossa 20.04
  • EKS hat noch eine Lösung gefunden im Dezember 2019 des Jahres. Wenn Ihre Version niedriger ist, sollten Sie das AMI aktualisieren.
  • Kops: Ab Juni 2020 у kops 1.18+ Das Haupt-Host-Image wird Ubuntu 20.04 sein. Wenn Ihre Kops-Version älter ist, müssen Sie möglicherweise auf einen Fix warten. Wir selbst warten jetzt.
  • GKE (Google Cloud): Fix integriert im Januar 2020Allerdings gibt es Probleme mit der Drosselung werden weiterhin beobachtet.

Was tun, wenn der Fix das Drosselungsproblem behoben hat?

Ich bin nicht sicher, ob das Problem vollständig gelöst ist. Wenn wir mit dem Fix zur Kernel-Version gelangen, werde ich den Cluster testen und den Beitrag aktualisieren. Wenn jemand bereits aktualisiert hat, wäre ich daran interessiert, Ihre Ergebnisse zu lesen.

Abschluss

  • Wenn Sie mit Docker-Containern unter Linux arbeiten (egal Kubernetes, Mesos, Swarm oder andere), kann es durch Drosselung zu Leistungseinbußen bei Ihren Containern kommen;
  • Versuchen Sie, auf die neueste Version Ihrer Distribution zu aktualisieren, in der Hoffnung, dass der Fehler bereits behoben wurde;
  • Durch die Aufhebung der Prozessorgrenzen lässt sich das Problem lösen. Dies ist jedoch eine gefährliche Technik, die mit äußerster Vorsicht angewendet werden sollte (es ist besser, zuerst den Kernel zu aktualisieren und die Ergebnisse zu vergleichen).
  • Wenn Sie die CPU-Grenzwerte aufgehoben haben, überwachen Sie sorgfältig Ihre CPU- und Speicherauslastung und stellen Sie sicher, dass Ihre CPU-Ressourcen Ihren Verbrauch übersteigen.
  • Eine sichere Option wäre die automatische Skalierung von Pods, um bei hoher Hardwarelast neue Pods zu erstellen, sodass Kubernetes sie freien Knoten zuweist.

Ich hoffe, dieser Beitrag hilft Ihnen, die Leistung Ihrer Containersysteme zu verbessern.

PS Hier Der Autor korrespondiert mit Lesern und Kommentatoren (auf Englisch).


Source: habr.com

Kommentar hinzufügen