Kontext
Was wie ein Autoscaling-Projekt aussah, wurde schnell zu einer Frage nach Zuverlässigkeit und Betriebsverhalten: Wann ist ein Job wirklich fertig und welche Metrik sollte KEDA beobachten?
Ansatz
Der Vergleich stellt einen dauerhaft laufenden Go-HTTP-Service für klassische MinIO-Events einem Go-Worker auf k3s gegenüber. MinIO publiziert Serverless-Events nach NATS JetStream; KEDA beobachtet den Consumer-Lag und skaliert den Worker.
System
- MinIO Classic Webhook → Go-HTTP-Service als Always-on-Baseline
- MinIO Event → NATS JetStream Stream und Pull Consumer
- KEDA: Worker anhand des JetStream-Lags von 0 bis 10 Replikas skalieren
- Go-Worker + cwebp: Bild normalisieren und WebP erzeugen
- MinIO + PostgreSQL: Ergebnis speichern, Metadaten schreiben, Rohobjekt danach löschen
- Prometheus + Grafana: Verhalten beobachten
Technische Entscheidungen
- Erst nach erfolgreichem Objekt-Upload, Datenbankeintrag und Löschen des Rohobjekts ACK senden.
- KEDA am JetStream-Consumer-Lag ausrichten, nicht an der Zahl der Objekte im Raw-Bucket.
- Scale-to-zero unter Last mit der dauerhaft laufenden HTTP-Baseline vergleichen und Metriken über Prometheus/Grafana beobachten.
Was nicht funktioniert hat
Scale-to-zero ist nicht die ganze Aufgabe. Scale-down, Nachrichtenbestätigung, Worker-Ausfälle und ein fairer Vergleich mit Always-on bestimmen, ob das System verlässlich arbeitet.
Ergebnis
Der Worker normalisiert das Bild, erzeugt WebP, lädt das Ergebnis nach MinIO, schreibt einen Datensatz und löscht das Raw-Objekt. Erst dann bestätigt er die NATS-Nachricht.
Was ich mitgenommen habe
Ein Worker ist nicht fertig, wenn seine Funktion zurückkehrt. Entscheidend ist, ob alle Folgewirkungen abgeschlossen sind, bevor die Nachricht bestätigt wird.