Kubernetes v1.33: Effiziente Datenübertragung durch Streaming-Listenantworten
Erfahren Sie, wie Kubernetes v1.33 durch Streaming-Listenantworten die Stabilität großer Cluster verbessert.
Managing Kubernetes-Cluster-Stabilität wird zunehmend kritisch, je größer Ihre Infrastruktur wird. Eine der herausforderndsten Aspekte beim Betrieb von großen Clustern war bisher die Handhabung von List-Anfragen, die umfangreiche Datensätze abrufen - eine häufige Operation, die unerwartete Auswirkungen auf die Stabilität Ihres Clusters haben kann.
Heute freut sich die Kubernetes-Community, eine bedeutende architektonische Verbesserung anzukündigen: Streaming-Codierung für List-Antworten.
Das Problem: Unnötiger Speicherverbrauch bei großen Ressourcen
Aktuelle API-Antwortencoder serialisieren eine gesamte Antwort in einen einzigen zusammenhängenden Speicherbereich und führen einen einzigen ResponseWriter.Write
-Aufruf aus, um die Daten an den Client zu übertragen. Trotz der Fähigkeit von HTTP/2, Antworten in kleinere Frames für die Übertragung zu splitten, hält der zugrunde liegende HTTP-Server die vollständigen Antwortdaten weiterhin als einen einzigen Puffer. Selbst wenn einzelne Frames an den Client übertragen werden, kann der Speicher, der mit diesen Frames verbunden ist, nicht inkrementell freigegeben werden.
Wenn die Clustergröße wächst, kann der einzelne Antwortkörper beträchtlich sein - wie Hundert Megabyte groß. Bei großem Maßstab wird der aktuelle Ansatz besonders ineffizient, da er eine inkrementelle Freigabe des Speichers während der Übertragung verhindert. Man stelle sich vor, dass bei Netzwerküberlastung der große Antwortkörper für Dutzende von Sekunden oder sogar Minuten aktiv bleibt. Diese Einschränkung führt zu unnötig hohem und langanhaltendem Speicherverbrauch im kube-apiserver-Prozess. Wenn mehrere große List-Anfragen gleichzeitig auftreten, kann der kumulative Speicherverbrauch schnell ansteigen und möglicherweise zu einer Out-of-Memory (OOM)-Situation führen, die die Stabilität des Clusters gefährdet.
Das Paket encoding/json
verwendet sync.Pool
, um Speicherspeicher während der Serialisierung wiederzuverwenden. Obwohl dies für konsistente Workloads effizient ist, schafft dieser Mechanismus Herausforderungen bei sporadisch großen List-Antworten. Bei der Verarbeitung dieser großen Antworten expandieren die Speicherpools erheblich. Aufgrund des Designs von sync.Pool
bleiben diese übergroßen Puffer jedoch nach der Verwendung reserviert. Nachfolgende kleine List-Anfragen nutzen weiterhin diese großen Speicherzuweisungen, was die Garbage Collection verhindert und einen dauerhaft hohen Speicherverbrauch im kube-apiserver aufrechterhält, selbst nachdem die ursprünglichen großen Antworten abgeschlossen sind.
Darüber hinaus sind Protocol Buffers nicht für die Verarbeitung großer Datensätze konzipiert. Sie eignen sich jedoch hervorragend für die Handhabung einzelner Nachrichten innerhalb eines großen Datensatzes. Dies verdeutlicht die Notwendigkeit für Streaming-basierte Ansätze, die große Sammlungen inkrementell verarbeiten und übertragen können, anstatt sie als monolithische Blöcke zu behandeln.
Als allgemeine Faustregel gilt: Wenn Sie mit Nachrichten arbeiten, die größer als ein Megabyte sind, wird es möglicherweise Zeit, eine alternative Strategie in Betracht zu ziehen.
Von https://protobuf.dev/programming-guides/techniques/
Quelle: Kubernetes Blog