Kubernetes optimieren: Wie API-Streaming die Effizienz steigert
Entdecken Sie, wie API-Streaming in Kubernetes die Speicherbelastung verringert und die Effizienz erhöht. Praktische Tipps und Anwendungsfälle.
Effizientes Management von Kubernetes-Clustern wird zunehmend wichtiger, insbesondere bei wachsender Clustergröße. Eine der größten Herausforderungen bei großen Clustern ist der Speicheraufwand, der durch list-Anfragen verursacht wird.
In der aktuellen Implementierung verarbeitet der kube-apiserver list-Anfragen, indem er die gesamte Antwort im Speicher zusammenstellt, bevor er Daten an den Client überträgt. Aber was passiert, wenn der Antwortinhalt umfangreich ist, sagen wir mehrere hundert Megabyte? Und stellen Sie sich vor, mehrere list-Anfragen treffen gleichzeitig ein, vielleicht nach einem kurzen Netzwerk-Ausfall. Während API Priority and Fairness sich als wirksam erwiesen hat, um den kube-apiserver vor CPU-Überlastung zu schützen, ist der Einfluss auf den Spe Schutz sichtbar geringer. Dies kann durch die unterschiedliche Natur des Ressourcenverbrauchs einer einzelnen API-Anfrage erklärt werden - die CPU-Nutzung zu einem bestimmten Zeitpunkt ist durch einen konstanten Wert begrenzt, während der Speicher, der nicht komprimierbar ist, proportional mit der Anzahl der verarbeiteten Objekte wachsen kann und unbegrenzt ist.
Diese Situation stellt ein echtes Risiko dar, das jeden kube-apiserver innerhalb von Sekunden aufgrund von Out-of-Memory (OOM)-Bedingungen überwältigen und zum Absturz bringen kann. Um das Problem besser zu veranschaulichen, betrachten wir das folgende Diagramm.
Das Diagramm zeigt den Speicherverbrauch eines kube-apiserver während eines synthetischen Tests. (Siehe den Abschnitt synthetischer Test für weitere Details). Die Ergebnisse zeigen deutlich, dass die Anzahl der Informer den Speicherverbrauch des Servers erheblich erhöht. Bemerkenswert ist, dass der Server um etwa 16:40 abstürzte, als er nur 16 Informer bediente.
Warum benötigt kube-apiserver so viel Speicher für list-Anfragen?
Unsere Untersuchung ergab, dass diese beträchtliche Speicherzuweisung auftritt, weil der Server, bevor er das erste Byte an den Client sendet, Folgendes tun muss:
- Daten aus der Datenbank abrufen,
- die Daten aus ihrem gespeicherten Format deserialisieren,
- und schließlich die endgültige Antwort konstruieren, indem er die Daten in das vom Client angeforderte Format umwandelt und serialisiert.
Diese Abfolge führt zu einem erheblichen temporären Speicherverbrauch. Der tatsächliche Verbrauch hängt von vielen Faktoren ab, wie der Seitengröße, angewendeten Filtern (z. B. Label-Selektoren), Abfrageparametern und den Größen einzelner Objekte.
Leider können weder API Priority and Fairness noch die Garbage Collection von Golang oder die Speicherlimits von Golang verhindern, dass das System unter diesen Bedingungen den Speicher erschöpft. Der Speicher wird plötzlich und schnell zugewiesen, und nur wenige Anfragen können schnell den verfügbaren Speicher aufbrauchen, was zu Ressourcenerschöpfung führt.
Je nachdem, wie der API-Server auf dem Knoten ausgeführt wird, könnte er entweder durch OOM vom Kernel getötet werden, wenn die konfigurierten Speicherlimits während dieser unkontrollierten Spitzen überschritten werden, oder, wenn keine Limits konfiguriert sind, könnte es noch schlimmere Auswirkungen auf den Steuerungsknoten haben. Und das Schlimmste: Nach dem ersten Ausfall des API-Servers werden die gleichen Anfragen wahrscheinlich einen anderen Steuerungsknoten in einer HA-Umgebung treffen, mit wahrscheinlich denselben Auswirkungen. Eine potenziell schwer zu diagnostizierende und schwer wiederherzustellende Situation.
Durch die Einführung von API-Streaming könnte jedoch eine signifikante Verbesserung erzielt werden. Mit API-Streaming wird der Speicherverbrauch optimiert, da die Daten in kleineren, handlicheren Stücken verarbeitet werden können, wodurch der Druck auf den kube-apiserver verringert wird. Dies ist ein großartiges Beispiel dafür, wie ayedo als Kubernetes-Partner dazu beiträgt, die Effizienz und Stabilität von Clustern zu steigern.
Quelle: Kubernetes Blog