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 применяет через
scalesubresource..
С точки зрения SRE важны встроенныt свойства безопасности:
- Параллельно с прогнозом считается обычная реактивная оценка, она задаёт нижнюю границу реплик. Ошибка прогноза в сторону занижения не может привести к дефициту мощности, только к избытку.
- Реплики считаются по высокому квантилю распределения прогноза. Чем выше неопределённость модели, тем больше реплик.
- Если не может честно ответить, возвращает ошибку и откатываемся к обычной 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 не вендорен, подтягивается в рантайме с закреплённой ревизии. Для кластеров без доступа к источнику чекпоинта это нужно учесть.
Порядок внедрения
- Погонять Shadow на некритичном сервисе с суточной или недельной периодичностью нагрузки. Две недели.
- Тест на своих метриках до переключения в Enforce.
- Проверить
leadTime: оно должно соответствовать реальному времени от решения до готовности пода (scheduling, pull image, startup probe). - Настроить алерты по метрикам из раздела Operations, включая диагностику «почему выбрано это число».
- Учесть при обновлениях, что может быть изменение в API.
Вывод
Presage закрывает лаг реактивного масштабирования. Два решения, которые снижают риск: реактивный floor (ошибка прогноза вниз не даёт дефицита) и Shadow по умолчанию (сначала наблюдение, потом применение). Бэктест на своих данных встроен в процесс.
GitHub · Apache-2.0 · в docs есть разделы по backtesting, архитектуре, операциям и API reference.