Presage: прогнозное автомасштабирование для Kubernetes

TL;DR: Presage это in-cluster автомасштабировщик, который прогнозирует нагрузку на момент, когда новые поды будут готовы, а не реагирует на текущую (не ждет, когда поплохеет, а заранее готовится). Использует TimesFM (открытая модель для прогнозирования временных рядов от Google), не требует обучения и не выносит данные за пределы кластера. Работает с любым ресурсом, у которого есть subresource scale.

Проблема, которую он решает

Реактивный автомасштабировщик всегда опаздывает. Он замечает рост нагрузки в момент, когда она уже выросла, и запускает под, который готов через N секунд. Эти N секунд нагрузка обслуживается недостаточной мощностью. Presage прогнозирует значение сигнала на горизонт leadTime вперёд и считает реплики по этому прогнозу, а не по текущему значению.

Как это работает

  • Сигнал: запрос к Prometheus (например, sum(rate(http_requests_total{app="api"}[5m]))). Поддерживается несколько сигналов на один scaler.
  • Прогноз: TimesFM предсказывает значение сигнала на горизонте leadTime (в примере — 90 секунд).
  • Расчёт реплик: прогноз переводится в количество реплик с учётом capacity.perReplica.
  • Решение: в режиме Shadow публикует рекомендацию в статус, в режиме Enforce применяет через scale subresource..

С точки зрения SRE важны встроенныt свойства безопасности:

  1. Параллельно с прогнозом считается обычная реактивная оценка, она задаёт нижнюю границу реплик. Ошибка прогноза в сторону занижения не может привести к дефициту мощности, только к избытку.
  2. Реплики считаются по высокому квантилю распределения прогноза. Чем выше неопределённость модели, тем больше реплик.
  3. Если не может честно ответить, возвращает ошибку и откатываемся к обычной buffer-политике.

Режимы

Каждый scaler стартует в Shadow: рекомендации пишутся в статус, целевой workload не меняется. После сравнения рекомендаций с фактической нагрузкой переключаете на Enforce.

Манифест:

apiVersion: scaling.presage.sh/v1alpha1
kind: PredictiveScaler
metadata:
  name: api
spec:
  mode: Shadow
  scaleTargetRef: {apiVersion: apps/v1, kind: Deployment, name: api}
  signal:
    prometheus:
      address: http://prometheus-operated.monitoring:9090
      query: sum(rate(http_requests_total{app="api"}[5m]))
  leadTime: {source: Static, static: 90s}
  capacity: {perReplica: "250"}
  policy: {minReplicas: 2, maxReplicas: 50}

Статус:

NAME   MODE     TARGET   CURRENT   RECOMMENDED   READY
api    Shadow   api      4         7             True

Установка:

helm install presage oci://ghcr.io/breezycourses/charts/presage \
  --namespace presage-system --create-namespace

Ограничения

  • Нет ковариат: запланированные события и релизы в модель не подаются. Авторы называют это основным оставшимся источником прироста точности.
  • В продакшене не эксплуатировался. Масштабирование реального workload в CI на реальном кластере есть, продакшен-истории нет.
  • Нет адаптеров KEDA/HPA. Subresource scale покрывает большинство случаев, но не все.
  • Чекпоинт TimesFM не вендорен, подтягивается в рантайме с закреплённой ревизии. Для кластеров без доступа к источнику чекпоинта это нужно учесть.

Порядок внедрения

  1. Погонять Shadow на некритичном сервисе с суточной или недельной периодичностью нагрузки. Две недели.
  2. Тест на своих метриках до переключения в Enforce.
  3. Проверить leadTime: оно должно соответствовать реальному времени от решения до готовности пода (scheduling, pull image, startup probe).
  4. Настроить алерты по метрикам из раздела Operations, включая диагностику «почему выбрано это число».
  5. Учесть при обновлениях, что может быть изменение в API.

Вывод

Presage закрывает лаг реактивного масштабирования. Два решения, которые снижают риск: реактивный floor (ошибка прогноза вниз не даёт дефицита) и Shadow по умолчанию (сначала наблюдение, потом применение). Бэктест на своих данных встроен в процесс.

GitHub · Apache-2.0 · в docs есть разделы по backtesting, архитектуре, операциям и API reference.

Похожие записи