Kubernetes v1.37: Масштабування навантажень до нуля за допомогою HorizontalPodAutoscaler

Kubernetes v1.37 включає підтримку API для горизонтального автоматичного масштабування навантажень до нуля реплік. Ця можливість тепер має статус бета і типово увімкнена. HorizontalPodAutoscaler (HPA), який використовує відповідну метрику обʼєкта або зовнішню метрику, тепер може масштабувати навантаження до нуля реплік, а потім відновлювати його, коли метрика змінюється.

До v1.37 для масштабування від нуля потрібна була надбудова або зовнішній компонент, або увімкнення функціональної можливості Alpha-рівня. Тепер це частина ядра Kubernetes.

Масштабування до нуля призводить до видалення останнього неактивного Podʼа із робочих навантажень, таких як споживачі черг та пакетні процесори. Економія є найбільшою, коли кожен Pod резервує ресурси з високою вартістю, зокрема виділені CPU або GPU.

Компроміс — час холодного запуску: HPA повинен стежити за метрикою, запланувати Pod і запустити застосунок. Це добре працює, коли завдання можуть очікувати у довготривалій черзі.

Service Kubernetes не буферизують запити, поки жоден Pod не є готовим, тому для HTTP та інших робочих навантажень, що базуються на запитах, потрібен окремий рівень буферизації.

Чому масштабування від нуля потребує іншої метрики

HPA часто масштабується на основі використання CPU або памʼяті. Обидві метрики надходять від запущених Podʼів. Коли кількість реплік досягає нуля, не залишається жодного Podʼа для вимірювання та жодного сигналу, який міг би сказати HPA масштабуватися знову вгору.

Обʼєктні та зовнішні метрики не мають цього обмеження. Довжина черги, наприклад, існує незалежно від обробників, які її обробляють. HPA може продовжувати читати довжину черги, коли жоден обробник не запущений.

Наведений нижче приклад масштабує обробників черги від і до нуля, використовуючи зовнішню метрику.

Налаштування зовнішньої метрики

Наведений нижче приклад використовує метрику Prometheus з назвою queue_consumer_lag. Припускається, що Prometheus вже збирає серію, схожу на цю:

queue_consumer_lag{namespace="default",name="worker_tasks"}

Kubernetes потрібен адаптер метрик, щоб зробити це значення доступним через API зовнішніх метрик. Однією з реалізацій є Prometheus Adapter, який може надавати серію, використовуючи запис externalRules:

externalRules:
- seriesQuery: '{__name__="queue_consumer_lag",name!=""}'
  metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (name)
  resources:
    overrides:
      namespace:
        resource: namespace

Точна інсталяція адаптера та правила виявлення залежать від налаштування вашого моніторингу. Дивіться керівництво Prometheus Adapter щодо зовнішніх метрик щоб дізнатися про всі параметри конфігурації.

Перед створенням HPA ви можете перевірити, чи Kubernetes може прочитати метрику:

kubectl get --raw \
  '/apis/external.metrics.k8s.io/v1beta1/namespaces/default/queue_consumer_lag?labelSelector=name%3Dworker_tasks'

Запит має повернути поточне значення для worker_tasks. Якщо це не так, виправте конвеєр метрик перед налаштуванням HPA. HPA не може масштабуватися від нуля, коли його метрика недоступна.

Налаштування HPA

Наведений нижче HPA націлений на Deployment з назвою queue-worker. Він дозволяє мати від нуля до десяти реплік, з однією реплікою, запитуваною на кожні 30 завдань у черзі:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: queue-worker
  annotations:
    kubernetes.io/description: "Scales queue-worker based on the number of queued tasks"
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: queue-worker
  minReplicas: 0
  maxReplicas: 10
  metrics:
  - type: External
    external:
      metric:
        name: queue_consumer_lag
        selector:
          matchLabels:
            name: worker_tasks
      target:
        type: Value
        value: "30"

Коли черга порожня, HPA може зменшити Deployment до нуля реплік. Коли завдання надходять, зовнішня метрика залишається доступною, і HPA розраховує нову кількість реплік, обмежену десятьма maxReplicas.

Запустіть Deployment із щонайменше однією реплікою. Ручне встановлення кількості реплік у Deployment на нуль завжди призупиняло автоматичне масштабування. HPA зберігає цю поведінку і не буде активувати робоче навантаження, яке він не зменшив самостійно.

Звичайна поведінка HPA все ще застосовується. Зокрема, вікно стабілізації зменшення типово становить пʼять хвилин. Вікно запобігає тому, що коротке зменшення довжини черги негайно видаляє всіх обробників. Ви можете налаштувати вікно через spec.behavior.scaleDown, якщо ваше навантаження потребує іншої поведінки.

Як HPA розрізняє нуль від призупинки

Масштабування від нуля створює неоднозначність. Кількість реплік, рівна нулю, може означати, що HPA зменшив навантаження, або що оператор вручну призупинив його.

Контролер вирішує це за допомогою стану ScaledToZero у статусі. Коли HPA масштабує навантаження від однієї або більше реплік до нуля, він записує ScaledToZero=True. Стан повідомляє наступним циклам узгодження, що контролер відповідає за нульовий стан і має продовжувати оцінювати метрики обʼєктів або зовнішні метрики.

Після масштабування навантаження знову вгору, контролер змінює стан на ScaledToZero=False з причиною NotScaledToZero. Навантаження на нулі без стану ScaledToZero=True залишається призупиненим.

Ви можете перевірити стани за допомогою:

kubectl describe hpa queue-worker

Якщо адаптер не може повернути налаштовану метрику, HPA повідомляє ScalingActive=False з причиною, такою як FailedGetExternalMetric. Відновіть метрику або вручну масштабуйте навантаження, щоб відновити потужність.

Перед оновленням або відкочуванням

У Kubernetes v1.37 функціональна можливість HPAScaleToZero типово увімкнена як на kube-apiserver, так і на kube-controller-manager. API-сервер приймає minReplicas: 0; менеджер контролерів виконує масштабування на основі станів.

Під час оновлення панелі управління, коли версії компонентів не збігаються, перед створенням HPA з параметром minReplicas: 0 слід дочекатися, поки обидва компоненти почнуть підтримувати цю можливість та увімкнуть її. Менеджер контролерів з вимкненою можливістю трактує replicas: 0 як ручну паузу і може залишити навантаження на нулі.

Перед вимкненням функціональної можливості або відкочуванням до версії без реалізації на основі станів:

  • Змініть відповідні HPA на minReplicas: 1 або вище.
  • Масштабуйте будь-яке навантаження, що зараз на нулі, принаймні до однієї репліки.

minReplicas: 0 також вимагає принаймні одну метрику обʼєкта або зовнішню метрику. API-сервер відхиляє HPA, який містить лише ресурсні метрики, такі як CPU або памʼять.

Від Alpha до Beta

Перша Alpha реалізація вийшла в Kubernetes v1.16. Kubernetes v1.36 додав стан ScaledToZero та поведінку контролера, необхідну для розрізнення автоматичного масштабування вниз від ручної паузи.

Kubernetes v1.37 типово вмикає цю можливість після додавання інтеграційного та наскрізного покриття для масштабування до нуля та назад з зовнішньої метрики. Наступний крок — збір відгуків про експлуатацію перед розглядом переходу до GA.

Як дізнатися більше?

Як приєднатися

Ця можливість належить SIG Autoscaling. Приєднуйтесь до Kubernetes Slack та каналу #sig-autoscaling, щоб поділитися зворотним звʼязком від використання Beta.

Подяки

Дякуємо учасникам SIG Autoscaling, які допрацювали цю можливість — від початкової реалізації у версії 1.16 до переробки на основі станів та переходу до бета-версії. Дякуємо також Guy Templeton та Adrian Moisey за огляд KEP, а також рецензентам релізу, документації та production-readiness, які допомогли підготувати її для Kubernetes v1.37.