Veröffentlicht am

KEDA Autoscaling: Event-driven Skalierung einrichten

Teilen:
Authors

Kubernetes KEDA: Event-driven Autoscaling fuer Microservices

TL;DR

  • KEDA erweitert den Horizontal Pod Autoscaler um externe Event-Quellen: Kafka Consumer Lag, Queue-Laenge, Prometheus-Metriken, Cron-Schedules und ueber 70 weitere Trigger.
  • Scale-to-Zero ist das Killerfeature: Workloads ohne eingehende Events verbrauchen null Ressourcen. Sobald Events eintreffen, skaliert KEDA innerhalb von Sekunden hoch.
  • KEDA ersetzt den HPA nicht, sondern baut darauf auf. Es erstellt und verwaltet HPA-Objekte automatisch basierend auf ScaledObject-Definitionen.
  • Die Installation per Helm dauert unter 3 Minuten. ScaledObjects sind einfache YAML-Manifeste mit 20-30 Zeilen.
  • In der Praxis reduziert Kubernetes KEDA die Compute-Kosten fuer event-getriebene Workloads um 40-70 Prozent.

Das Problem: HPA kennt keine externen Events

Der Horizontal Pod Autoscaler skaliert Pods basierend auf CPU- und Memory-Auslastung. Fuer synchrone HTTP-Workloads funktioniert das gut: Mehr Requests bedeuten mehr CPU-Last, also mehr Pods.

Fuer asynchrone, event-getriebene Workloads versagt dieses Modell. Ein Kafka Consumer mit wachsender Consumer Lag hat nicht zwingend hohe CPU-Auslastung. Eine Queue-basierte Anwendung braucht bei leerer Queue null Pods -- aber der HPA haelt mindestens minReplicas am Leben.

KEDA macht externe Metriken -- Queue-Laengen, Consumer Lag, Datenbankzeilen, HTTP-Request-Raten, Cron-Schedules -- zu Skalierungsentscheidungen in Kubernetes.

Wer die Grundlagen des Kubernetes Autoscalings vertiefen will: Kubernetes Autoscaling und Kostenoptimierung.

KEDA Architektur

KEDA installiert drei Komponenten: Der KEDA Operator ueberwacht ScaledObject-Ressourcen und erstellt automatisch HPAs. Der Metrics API Server fragt Event-Quellen ab und stellt Metriken dem HPA zur Verfuegung. Admission Webhooks validieren Manifeste.

ScaledObject vs. ScaledJob

EigenschaftScaledObjectScaledJob
ZielDeployment, StatefulSetJob
LebenszyklusPods laufen dauerhaft (oder Scale-to-Zero)Job startet und terminiert
Use CaseDauerhafte Consumer, APIsBatch-Verarbeitung, einmalige Tasks
Scale-to-ZeroJa (minReplicaCount: 0)Nicht anwendbar

Installation per Helm

helm repo add kedacore https://kedacore.github.io/charts
helm repo update

helm install keda kedacore/keda \
  --namespace keda \
  --create-namespace \
  --wait

# Installation pruefen
kubectl get pods -n keda
# NAME                                              READY   STATUS    AGE
# keda-admission-webhooks-8f6d7c4b5-xxxxx           1/1     Running   30s
# keda-operator-6c8d9f5b7-xxxxx                     1/1     Running   30s
# keda-operator-metrics-apiserver-7f8d6c5b4-xxxxx   1/1     Running   30s

Praxis: ScaledObject mit Kafka Trigger

Der haeufigste Use Case fuer KEDA: Ein Kafka Consumer soll basierend auf der Consumer Lag skalieren.

Kafka Consumer Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-processor
  namespace: processing
spec:
  replicas: 1
  selector:
    matchLabels:
      app: order-processor
  template:
    metadata:
      labels:
        app: order-processor
    spec:
      containers:
        - name: processor
          image: myregistry/order-processor:v2.1.0
          env:
            - name: KAFKA_BROKERS
              value: "kafka-bootstrap.kafka:9092"
            - name: KAFKA_TOPIC
              value: "orders"
            - name: KAFKA_GROUP
              value: "order-processor-group"
          resources:
            requests:
              cpu: 250m
              memory: 256Mi
            limits:
              cpu: 500m
              memory: 512Mi

ScaledObject Definition

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: order-processor-scaler
  namespace: processing
spec:
  scaleTargetRef:
    name: order-processor
  pollingInterval: 15
  cooldownPeriod: 120
  minReplicaCount: 0
  maxReplicaCount: 20
  fallback:
    failureThreshold: 3
    replicas: 2
  triggers:
    - type: kafka
      metadata:
        bootstrapServers: "kafka-bootstrap.kafka:9092"
        consumerGroup: "order-processor-group"
        topic: "orders"
        lagThreshold: "50"
        offsetResetPolicy: "latest"
kubectl apply -f order-processor-scaledobject.yaml

kubectl get scaledobject -n processing
# NAME                     SCALETARGETKIND      SCALETARGETNAME   MIN   MAX   TRIGGERS   READY
# order-processor-scaler   apps/v1.Deployment   order-processor   0     20    kafka      True

# HPA wurde automatisch erstellt
kubectl get hpa -n processing
# NAME                             REFERENCE                    TARGETS     MINPODS   MAXPODS   REPLICAS
# keda-hpa-order-processor-scaler  Deployment/order-processor   25/50       1         20        3

Wenn keine Nachrichten im Topic sind, skaliert KEDA auf 0 Pods. Sobald neue Messages eintreffen, startet KEDA innerhalb von Sekunden den ersten Pod.

Weitere Trigger: RabbitMQ, Prometheus, Cron

RabbitMQ Queue Trigger

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: email-sender-scaler
  namespace: notifications
spec:
  scaleTargetRef:
    name: email-sender
  minReplicaCount: 0
  maxReplicaCount: 10
  triggers:
    - type: rabbitmq
      metadata:
        protocol: "amqp"
        queueName: "email-queue"
        mode: "QueueLength"
        value: "20"
      authenticationRef:
        name: rabbitmq-auth

Prometheus Trigger

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: api-gateway-scaler
  namespace: gateway
spec:
  scaleTargetRef:
    name: api-gateway
  minReplicaCount: 2
  maxReplicaCount: 50
  triggers:
    - type: prometheus
      metadata:
        serverAddress: "http://prometheus-server.monitoring:9090"
        metricName: "http_requests_per_second"
        query: "sum(rate(http_requests_total{service='api-gateway'}[2m]))"
        threshold: "100"

Cron Trigger

Vorausschauende Skalierung nach Zeitplan -- ideal fuer bekannte Traffic-Muster:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: frontend-scaler
  namespace: web
spec:
  scaleTargetRef:
    name: frontend
  minReplicaCount: 2
  maxReplicaCount: 30
  triggers:
    - type: cron
      metadata:
        timezone: "Europe/Berlin"
        start: "0 8 * * 1-5"
        end: "0 20 * * 1-5"
        desiredReplicas: "10"
    - type: cron
      metadata:
        timezone: "Europe/Berlin"
        start: "0 20 * * 1-5"
        end: "0 8 * * 2-6"
        desiredReplicas: "3"

Cron-Trigger lassen sich mit anderen Triggern kombinieren. KEDA nimmt immer den hoechsten Wert.

TriggerAuthentication: Sichere Credentials

Viele Event-Quellen erfordern Authentifizierung. KEDA liest Credentials aus Kubernetes Secrets, HashiCorp Vault oder Cloud-Provider-Mechanismen:

apiVersion: v1
kind: Secret
metadata:
  name: rabbitmq-credentials
  namespace: notifications
type: Opaque
stringData:
  host: "amqp://user:password@rabbitmq.messaging:5672/vhost"
---
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: rabbitmq-auth
  namespace: notifications
spec:
  secretTargetRef:
    - parameter: host
      name: rabbitmq-credentials
      key: host

Fuer cluster-weite Credentials gibt es ClusterTriggerAuthentication -- identische Syntax, aber ohne Namespace-Bindung.

ScaledJob: Batch-Verarbeitung

Fuer einmalige Tasks bietet KEDA ScaledJobs. Jedes Event startet einen Kubernetes Job, der die Arbeit erledigt und terminiert:

apiVersion: keda.sh/v1alpha1
kind: ScaledJob
metadata:
  name: image-processor
  namespace: media
spec:
  jobTargetRef:
    parallelism: 1
    completions: 1
    backoffLimit: 3
    template:
      spec:
        containers:
          - name: processor
            image: myregistry/image-processor:v1.3.0
            resources:
              requests:
                cpu: 500m
                memory: 1Gi
        restartPolicy: Never
  pollingInterval: 10
  maxReplicaCount: 30
  successfulJobsHistoryLimit: 5
  failedJobsHistoryLimit: 3
  triggers:
    - type: aws-sqs-queue
      metadata:
        queueURL: "https://sqs.eu-central-1.amazonaws.com/123456789/image-queue"
        queueLength: "5"
        awsRegion: "eu-central-1"

Typische ScaledJob-Szenarien: Bildverarbeitung, PDF-Generierung, Datenimporte und ML-Batch-Inferenz.

KEDA vs. HPA: Komplementaer, nicht konkurrierend

KEDA ersetzt den HPA nicht -- es nutzt ihn als Baustein und erweitert ihn:

FaehigkeitStandard HPAHPA mit KEDA
CPU/Memory SkalierungJaJa
Externe MetrikenNur mit Custom Metrics Adapter70+ Trigger out-of-the-box
Scale-to-ZeroNein (minReplicas mindestens 1)Ja
Cooldown-PeriodeGlobales Cluster-SettingPro ScaledObject konfigurierbar
Fallback bei Metrik-FehlerKeine SkalierungKonfigurierbarer Fallback-Wert

Wer den HPA bereits im Einsatz hat: Kubernetes HPA und VPA.

Monitoring und Debugging

KEDA exponiert Prometheus-Metriken. Die wichtigsten:

# Aktuelle Metrik-Werte pro ScaledObject
keda_scaler_metrics_value

# Fehler beim Abfragen externer Metriken
keda_scaler_errors_total

# Skalierungslatenzen
keda_internal_scale_loop_latency

Bei Problemen:

# ScaledObject-Status
kubectl describe scaledobject order-processor-scaler -n processing

# KEDA Operator Logs
kubectl logs -n keda deployment/keda-operator --tail=100

# HPA-Status (von KEDA erstellt)
kubectl describe hpa keda-hpa-order-processor-scaler -n processing

Kostenoptimierung durch Scale-to-Zero

WorkloadOhne KEDA (min 1 Pod 24/7)Mit KEDA (Scale-to-Zero)Ersparnis
Nacht-Batch (aktiv 2h/Tag)12 CPU-h/Tag1 CPU-h/Tag92%
Wochenend-Reports168 CPU-h/Woche4 CPU-h/Woche98%
Dev-Consumer24/7 aktiv4h/Tag aktiv83%

Bei 20 solcher Workloads summiert sich das auf mehrere tausend Euro pro Monat. Weitere Strategien: Kubernetes Kosten optimieren.

Best Practices

  1. Cooldown sinnvoll setzen: 120-300 Sekunden fuer Kafka-Consumer vermeiden Flapping.
  2. Fallback konfigurieren: Bei unerreichbarer Metrik-Quelle nicht auf 0 skalieren.
  3. Graceful Shutdown: preStop-Hooks und terminationGracePeriodSeconds setzen, damit laufende Arbeit abgeschlossen wird.
  4. Resource Requests akkurat dimensionieren: KEDA skaliert Pod-Anzahl, aber jeder Pod braucht Ressourcen. Mehr dazu unter Kubernetes Resource Management.
  5. Konsistente Benennung: Konvention {deployment-name}-scaler erleichtert Zuordnung in Monitoring.

Verwandte Artikel


Wenn ihr KEDA in eurem Cluster einfuehren und eure Skalierungsstrategie optimieren wollt, meldet euch unter /kontakt -- wir helfen bei der Auswahl der richtigen Trigger, der Konfiguration und dem Monitoring.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen