Anwendungen mit Kubernetes und KEDA auf Null skalieren
Aus Kostengründen ist es oft weder machbar noch wünschenswert, einer Anwendung so viele Ressourcen zuzuweisen, dass sie jederzeit in der Lage ist, Spitzenlasten zu bewältigen. Daher skalieren wir Anwendungen in der Regel auf der Grundlage der aktuellen Last. Dies beinhaltet normalerweise eine Mindestanzahl von Instanzen, die zu jeder Zeit eingesetzt werden, auch wenn keine Last vorhanden ist. Dieses Minimum kann uns dazu zwingen, mehr Worker Nodes in unserem Kubernetes Cluster zu behalten als nötig, da die Instanzen ein zugewiesenes Ressourcenbudget haben.
In diesem Blog-Beitrag sehen wir uns an, wie man die Mindestanzahl der bereitgestellten Instanzen auf Null reduzieren kann, und diskutieren, welche Arten von Anwendungen davon am meisten profitieren.
Use Cases
Wenn man Anwendungen auf Null skaliert, gibt es einige Dinge zu beachten. Erstens kann der eingebaute „HorizontalPodAutoscaler“ nur bis zu einem Minimum von einem Replikat skalieren, weshalb ein weiterer Scaler erforderlich ist. Dies erhöht den Overhead des Clusters ein wenig. In diesem Beitrag werden wir uns auf die Verwendung des Kubernetes Event-Driven Autoscaler (KEDA) für diesen Zweck konzentrieren.
Zweitens gehen wir oft davon aus, dass es mindestens ein Replikat gibt, wenn wir unsere Systeme entwerfen. Das bedeutet, dass bestimmte Metriken in der Regel nicht erfasst werden, wenn es keine Instanzen gibt. Wir benötigen eine Metrik, die dem Autoscaler zur Verfügung steht, während die Bereitstellung auf Null skaliert wird, da wir sonst nicht in der Lage sind, wieder hochzuskalieren. Und wie werden eigentlich eingehende Verbindungen behandelt, wenn keine Instanz läuft?
In einigen Fällen ist dies leicht zu lösen. Bei Anwendungen, die einem Producer-Consumer-Muster folgen, ist es einfach, den Consumer auf Null zu skalieren. Wenn eine Anwendung beispielsweise Nachrichten aus einer Warteschlange abruft, können wir die aktuelle Länge der Warteschlange als Maßstab für unsere Skalierung nehmen. Wenn die Warteschlange leer ist, besteht kein Bedarf an einem Worker, der die Warteschlange konsumiert, und sobald mindestens ein Eintrag in der Warteschlange vorhanden ist, können wir einen Consumer einsetzen.
Andere Fälle sind etwas schwieriger zu lösen. Bei einer Webanwendung haben wir keine gute Metrik zur Verfügung, wenn die Anwendung auf Null skaliert wird. Normalerweise würden wir die Skalierung auf die Anzahl der Anfragen in einem bestimmten Zeitrahmen oder die durchschnittliche Antwortzeit stützen wollen.
Wir könnten eine Metrik aus einer externen Quelle verwenden, falls verfügbar, oder eine weitere Komponente zur Überwachung eingehender Anfragen implementieren.
Die Notwendigkeit einer solchen Komponente wird noch deutlicher, wenn wir die Anfragen selbst betrachten. Wir wollen keine Anfragen verpassen, wenn die Anwendung gerade auf Null skaliert ist. Daher müssen wir die eingehenden Verbindungen verfolgen und unsere Anwendung bereitstellen, wenn sie auf null Replikate skaliert ist, wenn eine Anfrage eingeht.
Das KEDA HTTP Add-on ist eine Komponente von KEDA, die es uns ermöglicht, die Skalierung auf die Anzahl der eingehenden HTTP-Anfragen zu stützen. Es enthält einen Proxy, der zwischen dem Ingress Controller und der Anwendung in Kubernetes eingefügt wird. Dieser Proxy puffert eingehende Anfragen und meldet die Anzahl der ausstehenden Anfragen als Metrik an KEDA.
Eine Beispielkonfiguration für KEDA mit dem HTTP-Add-on könnte wie folgt aussehen:
apiVersion: http.keda.sh/v1alpha1 kind: HTTPScaledObject metadata: name: frontend-scaler namespace: demoapplication labels: deploymentName: frontend spec: host: "demo.example.com" scaleTargetRef: deployment: demoapplication service: frontend port: 8080 targetPendingRequests: 10 replicas: min: 0 max: 100
Diese Konfiguration skaliert die frontend
-Bereitstellung auf Null, wenn keine Anfragen anstehen, und skaliert bis zu einem Maximum von 100 Instanzen, wenn dies erforderlich ist, um die Warteschlange bei 10 anstehenden Anfragen zu halten. Während dies für Anwendungen mit einer allmählich ansteigenden Last gut funktioniert, könnten bei Anwendungen mit einem starken Anstieg der Anfragen Schwierigkeiten auftreten. In diesem Fall kann sich der Proxy zu einem Engpass entwickeln.
Eine andere Klasse von Anwendungen, die sich leicht auf Null skalieren lassen, sind solche, die nur in bestimmten Zeiträumen genutzt werden. Eine Lernplattform, die von einer Schule genutzt wird, hat zum Beispiel tagsüber an Tagen, die keine Feiertage sind, viel mehr Verkehr als nachts. Außerdem ist bekannt, dass diese Anwendungen eine nicht zu vernachlässigende Anlaufzeit haben, was bei einer Skalierung von Null auf Anfrage zu Timeouts führen kann.
Die Zeitabhängigkeit kann genutzt werden, um die Anwendung kurz vor einem zu erwartenden hohen Verkehrsaufkommen präventiv zu skalieren und so zu verhindern, dass die User während der normalen Arbeitszeiten auf eine unerreichbare Anwendung stoßen. Nachts könnte die Anwendung auf Null skaliert und bei Bedarf über den Proxy hochgefahren werden. Dies kann zu einer Zeitüberschreitung bei der ersten Anfrage führen, aber die Einsparungen können sich lohnen, insbesondere wenn diese Plattform von einem Dienstleister für mehrere Schulen gehostet wird.
Fazit
Natürlich ist eine Skalierung auf Null nicht immer eine praktikable Option, da einige Anwendungen davon nicht profitieren. Dazu gehören Anwendungen mit einer konstanten Grundlast oder nur kurzen Zeiträumen ohne Datenverkehr. In diesen Fällen kann der Overhead der Skalierung von eins auf null und wieder zurück die Vorteile der Skalierung auf null leicht überwiegen.
Kurz gesagt: Die meisten Anwendungen, die auf Kubernetes laufen, können mit ein wenig Aufwand auf Null skaliert werden, was sowohl die Infrastrukturrechnung als auch den CO2-Fußabdruck reduzieren kann.
Tobias Manske
Neueste Artikel von Tobias Manske (alle ansehen)
- Anwendungen mit Kubernetes und KEDA auf Null skalieren - 9. Oktober 2023
- Kubernetes-Cluster mit orcharhino provisionieren - 2. Dezember 2022