KubernetesMiddleSystem design

Что такое KEDA и зачем он нужен, если есть HPA?

KEDA добавляет event-driven autoscaling поверх HPA: масштабирует workload по очередям (Redis, Kafka, SQS), Prometheus-метрикам и cron-расписанию, умеет опускать replicas до нуля, чего стандартный HPA не поддерживает.

Что такое KEDA и чем отличается от HPA

HPA (Horizontal Pod Autoscaler) умеет масштабировать по CPU, памяти и custom metrics через Metrics API. Но он не знает о длине очереди RabbitMQ, Kafka consumer lag, числе сообщений в Azure Service Bus или произвольном Prometheus-запросе как единственном источнике истины. KEDA (Kubernetes Event-Driven Autoscaling) закрывает этот пробел: он добавляет ScaledObject / ScaledJob CRD, набор scalers (встроенных интеграций с внешними источниками) и собственный Metrics Server, который публикует значения через External Metrics API. HPA при этом остаётся исполнителем масштабирования — KEDA просто кормит его нужными метриками.

Архитектура

Оператор KEDA состоит из нескольких компонентов:

  • keda-operator — следит за ScaledObject/ScaledJob, управляет HPA-объектами, реализует scale-to-zero.
  • keda-metrics-apiserver — реализует external.metrics.k8s.io и отдаёт значения scalers в HPA.
  • ScaledObject — привязывает Deployment/StatefulSet к одному или нескольким triggers.
  • ScaledJob — вместо масштабирования Deployment создаёт Job-объекты под каждый event (батчевая обработка).

Цикл работы: scaler читает внешний источник каждые pollingInterval секунд → вычисляет метрику → KEDA обновляет HPA targetAverageValue → HPA меняет replicas. Если все scalers возвращают 0 и minReplicaCount: 0, KEDA удаляет HPA и выставляет replicas=0 напрямую, обходя HPA (тот не умеет в ноль).

Пример ScaledObject для Redis-очереди

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: worker
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: worker
  pollingInterval: 15        # опрос каждые 15 секунд
  cooldownPeriod: 60         # ждать 60 секунд перед scale-to-zero
  minReplicaCount: 0
  maxReplicaCount: 30
  triggers:
    - type: redis
      metadata:
        address: redis-master.default.svc:6379
        listName: job_queue
        listLength: "5"      # 1 реплика на каждые 5 сообщений
      authenticationRef:
        name: redis-secret

Пример ScaledObject для Kafka

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: kafka-consumer
spec:
  scaleTargetRef:
    name: kafka-consumer
  minReplicaCount: 1
  maxReplicaCount: 50
  triggers:
    - type: kafka
      metadata:
        bootstrapServers: kafka.default.svc:9092
        consumerGroup: my-group
        topic: events
        lagThreshold: "100"   # 1 реплика на каждые 100 сообщений лага
        offsetResetPolicy: latest

TriggerAuthentication для секретов

apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: redis-secret
spec:
  secretTargetRef:
    - parameter: password
      name: redis-credentials
      key: password

Когда KEDA необходим, а когда достаточно HPA

HPA с custom metrics адаптера достаточно, если метрика уже есть в Prometheus и Prometheus Adapter настроен. KEDA оправдан когда: нужен scale-to-zero, источник — очередь / event bus, не хочется настраивать Prometheus Adapter вручную, или используются cloud-native источники (SQS, Azure Queue, GCP Pub/Sub).

Подводные камни

  • Scale-to-zero требует внешней точки активации; если scaler не видит источник (network issue, wrong credentials), он может ошибочно вернуть 0 и убрать все реплики.
  • pollingInterval не равен latency реакции: при коротком spike в очереди реплики могут не успеть подняться до начала timeout сообщений.
  • Credentials к внешним системам надо хранить в TriggerAuthentication + Secret, а не в metadata в открытом виде — иначе они попадут в etcd незашифрованными.
  • ScaledJob создаёт новый Job на каждый event batch; без TTL-after-finished контроллера завершённые Jobs копятся и засоряют namespace.
  • При наличии нескольких triggers KEDA берёт максимальное значение из всех — агрегация не настраивается. Это может приводить к неожиданно высокому числу реплик.
  • KEDA управляет HPA-объектом; ручные изменения HPA будут перезаписаны оператором на следующем reconcile-цикле.
  • minReplicaCount: 0 вместе с длинным cooldownPeriod может привести к тому, что реплики уйдут в ноль во время ночного затишья, а утренний burst встретит cold-start задержку контейнеров.
  • После обновления KEDA CRD (upgrade оператора) существующие ScaledObject могут требовать миграции схемы — проверяйте CHANGELOG перед обновлением.

Common mistakes

  • Говорить, что KEDA только для Kafka
  • Не знать ScaledObject
  • Игнорировать auth к scaler

What the interviewer is testing

  • Объясняет event-driven scaling
  • Понимает связь с HPA
  • Приводит внешний metric use case

Sources

Related topics