Custom Metrics sind in der Regel präziser und nützlicher als CPU- und RAM-basiertes Autoscaling. Trotzdem ist das Skalieren auf Basis von Custom Metrics und externen Metriken nach wie vor ein etwas wildes Terrain mit klarem Verbesserungspotenzial.

Kubernetes entwickelt sich permanent weiter. Deshalb sehe ich mir gelegentlich Funktionen noch einmal genauer an, mit denen ich seit ein paar Jahren nicht mehr gearbeitet habe. Genau das habe ich kürzlich mit Horizontal Pod Autoscalers (HPAs) gemacht – und dabei einige interessante Eigenheiten und Einschränkungen entdeckt, die wissenswert, aber weder gut dokumentiert noch offensichtlich sind.
Eine erwähnenswerte Stolperfalle: Die apiVersion: autoscaling/v2 von HPA legt nahe, dass HPAs eine ausgereifte API sind. Tatsächlich ist das Skalieren auf Basis von Custom Metrics und externen Metriken aber noch ein etwas wildes Terrain mit Luft nach oben. Schade, denn Custom Metrics sind tendenziell präziser und nützlicher als CPU- und RAM-basiertes Autoscaling.
Schauen wir uns ein paar Use Cases an, in denen Custom Metrics die Skalierbarkeit verbessern – und welche Tools dabei helfen.
Use Cases
Sind Custom Metrics einmal eingerichtet und in einem HPA-tauglichen Format verfügbar, können HPAs anhand mehrerer Metriken skalieren. Die Kubernetes-Doku zeigt dazu ein Teilbeispiel: Ein HPA wird so konfiguriert, dass er anhand von CPU-Auslastung, Paketen pro Sekunde und Requests pro Sekunde skaliert. Die Idee dahinter: Jede Metrik kann eine andere Anzahl gewünschter Replicas vorschlagen, etwa 3, 5 und 8. Der HPA skaliert dann auf den höchsten dieser Werte.
- Das Kube Prometheus Stack Helm Chart gehört zu den beliebtesten und am besten unterstützten cloud-agnostischen Lösungen für Custom Metrics. Der Stack umfasst mehrere Apps; der Prometheus Adapter for Kubernetes Metrics APIs ist dabei die Komponente, die Prometheus-Metriken in ein Format konvertiert und bereitstellt, mit dem HPAs etwas anfangen können.
Eingehende Requests pro Sekunde sowie Request-Dauer bzw. Latenz sind solide Metriken, um Web-Services zu skalieren.
Architekturen mit Queues oder Storage Buckets, in die zu verarbeitende Objekte hochgeladen werden, können Services anhand der Anzahl erkannter Items autoskalieren.
- Kubernetes Event Driven Autoscaling (KEDA) bringt Scaler mit, die mit verschiedenen Queues ( z. B. Pub/Sub) und Object-Storage-Buckets sprechen. KEDA kann zudem Abfragen gegen Metric-, Log-, SQL- und NoSQL-Datenbanken ausführen, um daraus Metriken zu erzeugen.
Variable Minimum Replicas helfen, Traffic-Spitzen abzufangen und gleichzeitig die Kosten im Griff zu behalten. Wer schon einmal eine App betreut hat, deren Replicas langsam starten oder die heftige Traffic-Spitzen erlebt, kennt die Notwendigkeit, die minimale Replica-Anzahl anzuheben, um die Servicequalität zu sichern.
- Beispiel: Wenn ein Replica 100 Requests/Sek. verarbeiten kann, ließe sich Autoscaling bei 50 Requests/Sek. konfigurieren, um Fehler oder Latenz jenseits von 100 Requests/Sek. zu vermeiden. Mit einem Minimum von 10 Replicas fängt man Traffic-Spitzen deutlich besser ab als mit einem Minimum von zwei.
- Der einzige Haken: Die Kosten steigen. Allerdings ist es realistisch, dass eine App halbwegs vorhersehbare Traffic-Spitzen hat. Außerhalb der üblichen Geschäftszeiten reicht vielleicht ein Minimum von zwei, in spitzenlastigen Stunden ein Minimum von 10 – und sonst eines von fünf.
- KEDA hat vor Kurzem eine Option gemergt, mit der sich mehrere Metriken in eine benutzerdefinierte Formel einbinden lassen, um daraus zusammengesetzte Metriken zu bauen. So lässt sich "desired count = Autoscaling-Metrik + cron-basierter desired count" umsetzen – und damit faktisch eine variable Minimum-Replica-Anzahl erzeugen.
Serverless- und Functions-as-a-Service-Plattformen, die auf Kubernetes laufen, zum Beispiel:
- keda.sh
- knative.dev
- openfaas.com
Einschränkungen und Konsequenzen
Das alles klingt gut – und das nötige Tooling gibt es. Was also ist diese problematische Einschränkung, die HPAs daran hindert, richtig gut zu sein?
Die folgende Einschränkung hat spürbare Folgen für die UX (User Experience): https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/70
Kurz gesagt: "Es kann nur einen Custom Metrics Server geben." Wer den beliebten kube-prometheus-stack mit Standardeinstellungen installiert, bekommt den Prometheus Adapter. Parallel dazu lassen sich KEDAs keda-operator-metrics-apiserver, Knatives Knative Pod Autoscaler, der Autoscaler von OpenFaaS Pro, der Autoscaler von Datadog und ähnliche nicht betreiben. Der Grund: Sie alle bringen einen eigenen Custom Metrics Server mit. Genau das ist meiner Ansicht nach der Grund, warum KEDA so viele Scaler hat, dass man fast den Eindruck gewinnt, das Projekt wolle Aushängeschild für Feature Creep werden. KEDA bringt über 60 Scaler mit, darunter welche für Prometheus und Datadog. Das ergibt erst Sinn, wenn man begreift, dass ein Teil davon schlicht dazu dient, diese Einschränkung zu umgehen.
Warum verschlechtert diese Einschränkung also die UX? Werfen wir zunächst einen Blick darauf, wie gute UX aussieht.
Der Kube Prometheus Stack und Helm sind aus gutem Grund beliebt. Sie bieten eine erstklassige UX, und Teil des Erfolgsrezepts ist das Prinzip "Convention over Configuration". Sie liefern sinnvolle Default-Werte und eine Default-Konfiguration, in der Hunderte bis Tausende YAML-Objekte nach Konventionen miteinander vorverdrahtet sind – das Ergebnis ist eine Turnkey-UX, bei der vieles direkt out of the box läuft.
Voraussetzung für diese magische UX: ein eigener Namespace, der nicht mit anderem kollidiert. Erst dann lassen sich darin Konventionen etablieren, sodass alles vorverdrahtet werden kann, ohne dass jemand eine maßgeschneiderte Konfiguration von Hand bauen muss.
Für dieses weit verbreitete Problem gibt es bereits mehrere Proofs-of-Concept (PoCs), und es wurde sogar ein Kubernetes Enhancement Proposal eingereicht, das es lösen sollte – das ist allerdings im Sande verlaufen. Ich hoffe, dass dieser Artikel das Problem stärker ins Bewusstsein rückt und den Custom-Metric-Scaling-APIs zu neuem Schwung verhilft.