превратить сигналы наблюдаемости в надежные действия масштабирования
Автомасштабирование в Kubernetes на основе наблюдаемости: от метрик к действию
14 минут
Масштабирование только по CPU реагирует тогда, когда задержка уже заметна пользователям. Постройте замкнутый контур: Prometheus считает насыщение и давление очереди, KEDA применяет ограниченное поведение HPA, а панели показывают качество масштабирования как отдельный SRE-сигнал.
Почему масштабирование только по ресурсам недостаточно
В каждом продакшен-кластере есть одно и то же противоречие: ёмкость нужна до всплеска спроса, но избыток сжигает бюджет, а нехватка бьет по пользователям. Обычно команды стартуют с HPA по CPU и памяти — это полезно, но реактивно. Пока утилизация пересечет порог и появятся новые реплики, задержка уже вырастет, а очереди уже накопятся. Проблема не в отсутствии данных, а в отсутствии логики управления. Prometheus и Grafana показывают опережающие сигналы — рост частоты запросов, тренд глубины очереди, дрейф p99 — но автомасштабирование часто видит только узкую ресурсную часть. Подход на основе наблюдаемости закрывает этот разрыв: сигналы уровня сервиса становятся ограниченными и проверяемыми решениями по масштабу.
Опорная архитектура: собрать, вычислить, применить, проверить
Смотрите на масштабирование как на замкнутую систему управления. Сначала собирайте телеметрию через OpenTelemetry Collector и Prometheus. Затем вычисляйте сигналы через recording rules, чтобы KEDA не запускала тяжелые сырые запросы при каждом опросе. Применяйте решения через ScaledObject в KEDA, который передает поведение в HPA с отдельными окнами для scale-up и scale-down. Проверяйте качество через панели и алерты: время до масштабирования, перерегулирование, дрожание реплик и влияние на SLO. Такой контур отвязывает масштабирование от одной метрики утилизации и делает его наблюдаемым элементом политики надежности.
Recording rules Prometheus для сигналов масштабирования
Предварительно считайте нормализованные сигналы для каждого сервиса и namespace. Формулы должны быть устойчивы к делению на ноль и к несовпадению меток. Основной сигнал — saturation ratio (текущая частота запросов к проверенной емкости на реплику), дополнительные — давление очереди и задержка. Для глубины очереди используйте gauge-метрику queue_depth и тренд через delta или increase; rate() применяйте только к счетчикам.
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: autoscaling-signals
namespace: monitoring
spec:
groups:
- name: scaling.signals
interval: 30s
rules:
- record: app:request_rps:2m
expr: |
sum by (namespace, service) (
rate(http_requests_total{job="app"}[2m])
)
- record: app:queue_depth_delta:2m
expr: |
sum by (namespace, service) (
delta(queue_depth{job="app"}[2m])
)
- record: app:latency_p99:5m
expr: |
histogram_quantile(
0.99,
sum by (le, namespace, service) (
rate(http_request_duration_seconds_bucket{job="app"}[5m])
)
)
- record: app:saturation_ratio
expr: |
app:request_rps:2m
/
clamp_min(app:capacity_rps, 1)ScaledObject KEDA с защищенным поведением HPA
KEDA может объединять несколько триггеров Prometheus; масштабирование срабатывает, когда любой триггер выше порога. Используйте saturation ratio как основной вход для роста, а queue_depth_delta как ускоритель для всплесков. Настройте поведение HPA на быстрый рост и осторожное снижение, чтобы избежать флаттинга. Явно задавайте minReplicaCount и maxReplicaCount — это защита базовой надежности и бюджета кластера.
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: api-gateway-scaler
namespace: production
spec:
scaleTargetRef:
name: api-gateway
minReplicaCount: 3
maxReplicaCount: 50
pollingInterval: 30
cooldownPeriod: 180
advanced:
horizontalPodAutoscalerConfig:
behavior:
scaleUp:
stabilizationWindowSeconds: 30
selectPolicy: Max
policies:
- type: Percent
value: 100
periodSeconds: 60
- type: Pods
value: 5
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
selectPolicy: Min
policies:
- type: Percent
value: 20
periodSeconds: 60
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
metricName: saturation_ratio
threshold: "0.8"
query: |
app:saturation_ratio{namespace="production",service="api-gateway"}
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
metricName: queue_depth_delta
threshold: "20"
query: |
app:queue_depth_delta:2m{namespace="production",service="api-gateway"}Панель здоровья масштабирования и алертинг
Подход на основе наблюдаемости не работает, если команда не может объяснить, почему изменилось число реплик. Добавьте отдельную панель рядом с SLO: текущие реплики, частота запросов, saturation ratio и изменения реплик. Поднимайте алерты на антипаттерны: длительное высокое насыщение без scale-up или частые изменения реплик при ровном трафике. Так автомасштабирование перестает быть черным ящиком и становится проверяемым контуром управления.
# Текущее число реплик
sum by (namespace, deployment) (
kube_deployment_status_replicas{namespace="production",deployment="api-gateway"}
)
# Изменения реплик за 10 минут
changes(
kube_deployment_status_replicas{namespace="production",deployment="api-gateway"}[10m]
)
# Насыщение относительно порога
app:saturation_ratio{namespace="production",service="api-gateway"}groups:
- name: autoscaling-health
rules:
- alert: ScalingLagUnderHighSaturation
expr: |
app:saturation_ratio{namespace="production",service="api-gateway"} > 0.9
and
avg_over_time(kube_deployment_status_replicas{namespace="production",deployment="api-gateway"}[5m])
==
min_over_time(kube_deployment_status_replicas{namespace="production",deployment="api-gateway"}[5m])
for: 5m
labels:
severity: warning
annotations:
summary: "Насыщение высокое, а реплики не растут"Практика эксплуатации: границы, нагрузочные тесты и безопасность выкатки
Начните с одного сервиса с понятным профилем нагрузки и известной capacity_rps. Прогоняйте нагрузочные тесты в k6, Locust или Vegeta и измеряйте время до масштабирования, пик задержки, перерегулирование по репликам и время стабилизации. Держите отдельные окна для scale-up и scale-down: агрессивное снижение чаще всего рождает дрожание. Ежемесячно пересматривайте min и max реплик по сезонности. Храните recording rules и манифесты масштабирования в том же репозитории, что и конфигурацию сервиса. На рискованных релизах сочетайте политику масштабирования с burn-rate алертами SLO, чтобы выкатка и контроль емкости усиливали друг друга. Цель — не частые события масштабирования, а стабильная пользовательская производительность при меняющемся спросе.
Начните с базовой телеметрии, а затем добавляйте продвинутую логику масштабирования по гайду по observability для небольших платформенных команд.
Единый конвейер сервисных и инфраструктурных сигналов — в гайде по production-пайплайну OpenTelemetry Collector.
