Немного практики для "пощупать" HPA в кластере, поиграться параметрами масштабирования. Можно было бы быстро перейти от теории к практике, ну или наоборот. В примерах используется масштабирование на основе очереди RabbitMQ. Можно использовать minikube, MicroK8s, или где вам удобно... Для удобства развёртывания примеры k8s-hpa-rabbitmq-demo.

В данном случае тестировать HPA можно тремя способами: с помощью одной KEDA, с помощью Prometheus Adapter и метрик из Prometheus, а также с помощью KEDA и метрик из VictoriaMetrics. Необходимо выбрать один или использовать по очереди. Все способы разворачиваются с минимальными требованиями без "лишних" объектов. Для работы с очередью понадобится агент mrlioncub/rabbitmq-agent в кластере.

Перед разворачиванием подключим репозитории helm:

helm repo add helmforge https://repo.helmforge.dev
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add vm https://victoriametrics.github.io/helm-charts
helm repo add kedacore https://kedacore.github.io/charts
helm repo add k8s-hpa-rabbitmq-demo https://mrlioncub.github.io/k8s-hpa-rabbitmq-demo
helm repo update

Для всех тестов нам понадобится RabbitMQ с включённым /metrics:

charts/rabbitmq/values.yaml:

#это имя сервиса понадобится для обращения 
fullnameOverride: "rabbitmq-server"

auth:
  username: guest
  password: guest

podAnnotations:
  prometheus.io/scrape: "true"

metrics:
  enabled: true

singleNode:
  persistence:
    enabled: false
helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install rabbitmq-server helmforge/rabbitmq -f charts/rabbitmq/values.yaml

Полезные команды, которые могут понадобиться для анализа:

kubectl -n k8-hpa-rabbitmq-demo exec rabbitmq-server-0 -- rabbitmqctl list_queues -s - показать значение очереди

kubectl -n k8-hpa-rabbitmq-demo run curl -it --rm --image=alpine/curl --restart=Never -- curl -s http://rabbitmq-server:15692/metrics | grep 'rabbitmq_queue_messages{vhost="/",queue="task_queue"}' - показать очередь уже в самих метриках сервиса

Способ 1: KEDA

Для этого способа нужна сама KEDA:

helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install keda kedacore/keda

и тот кто будет обрабатывать очередь:

helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install rabbitmq-agent-reciever k8s-hpa-rabbitmq-demo/rabbitmq-agent --set keda.enabled=true

Проверим работу ScaledObject для работы с KEDA, созданного при развёртывании rabbitmq-agent-reciever. Пример, что работает (READY: True):

$ kubectl get scaledobject -n k8-hpa-rabbitmq-demo
NAME                    SCALETARGETKIND      SCALETARGETNAME           MIN   MAX   READY   ACTIVE   FALLBACK   PAUSED   TRIGGERS   AUTHENTICATIONS   AGE
rabbitmq-scaledobject   apps/v1.Deployment   rabbitmq-agent-reciever   1     10    True    False    False      False    rabbitmq                     2m

Способ 2: Prometheus и Prometheus Adapter

Соответственно понадобятся Prometheus и Prometheus Adapter

charts/prometheus/values.yaml (подробнее):

alertmanager:
  enabled: false
prometheus-pushgateway:
  enabled: false
prometheus-node-exporter:
  enabled: false
kube-state-metrics:
  enabled: false

charts/prometheus-adapter/values.yaml (подробнее):

prometheus:
  url: http://prometheus-server
  port: 80

rules:
  default: false
  custom:
  - seriesQuery: 'rabbitmq_queue_messages{namespace!="",pod!="",queue="task_queue"}'
    resources:
      overrides:
        namespace: {resource: "namespace"}
        pod: {resource: "pod"}
    metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>,queue="task_queue"}) by (<<.GroupBy>>)
helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install prometheus prometheus-community/prometheus -f charts/prometheus/values.yaml
helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install prometheus-adapter prometheus-community/prometheus-adapter -f charts/prometheus-adapter/values.yaml

и кто будет обрабатывать очередь:

helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install rabbitmq-agent-reciever k8s-hpa-rabbitmq-demo/rabbitmq-agent --set autoscaling.enabled=true

Проверим, что всё появилось в CustomMetrics, которые создал Prometheus Adapter из Prometheus. Пример, что работает:

$ kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/k8-hpa-rabbitmq-demo/pods/rabbitmq-server-0/rabbitmq_queue_messages | jq .
{
  "kind": "MetricValueList",
  "apiVersion": "custom.metrics.k8s.io/v1beta1",
  "metadata": {},
  "items": [
    {
      "describedObject": {
        "kind": "Pod",
        "namespace": "k8-hpa-rabbitmq-demo",
        "name": "rabbitmq-server-0",
        "apiVersion": "/v1"
      },
      "metricName": "rabbitmq_queue_messages",
      "timestamp": "2026-06-09T08:02:47Z",
      "value": "0",
      "selector": null
    }
  ]
}

Способ 3: VictoriaMetrics и KEDA

charts/victoriametrics/values.yaml (подробнее):

server:
  scrape:
    enabled: true
    config:
      scrape_configs:
      - job_name: rabbitmq
        static_configs:
        - targets:
          - rabbitmq-server:15692
  persistentVolume:
      enabled: false
helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install victoriametrics vm/victoria-metrics-single -f charts/victoriametrics/values.yaml
helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install keda kedacore/keda

Проверим работу ScaledObject можно аналогично как и в первом способе.

Очередь и HPA

Проверить HPA на любом из способов:

kubectl -n k8-hpa-rabbitmq-demo get hpa

Пример работающего HPA, в первом и третьем способе:

NAME                             REFERENCE                            TARGETS      MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   0/30 (avg)   1         10        1          40s

Пример работающего HPA, во втором способе:

$ kubectl -n k8-hpa-rabbitmq-demo get hpa
NAME                  REFERENCE                            TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   0/30      1         10        1          4m47s

При TARGETS: <unknown>/30 значит объект hpa создан, но данные с метрик ещё не поступили.

После уже можно пробовать заполнить очередь и смотреть как работает HPA.
Отправить 50 сообщений в очередь и проверим как меняется hpa:

kubectl --namespace k8-hpa-rabbitmq-demo run sender -it --rm --image=mrlioncub/rabbitmq-agent --restart=Never -- sender 50
kubectl -n k8-hpa-rabbitmq-demo get hpa -w

Как работает HPA для первого и третьего способов:

NAME                             REFERENCE                            TARGETS              MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   <unknown>/30 (avg)   1         10        0          0s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   0/30 (avg)           1         10        1          15s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   48/30 (avg)          1         10        1          60s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   23/30 (avg)          1         10        2          76s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   21500m/30 (avg)      1         10        2          91s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   18500m/30 (avg)      1         10        2          106s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   16/30 (avg)          1         10        2          2m1s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   12500m/30 (avg)      1         10        2          2m16s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   8/30 (avg)           1         10        2          2m31s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   5/30 (avg)           1         10        2          2m46s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   2/30 (avg)           1         10        2          3m1s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   0/30 (avg)           1         10        2          3m16s
keda-hpa-rabbitmq-scaledobject   Deployment/rabbitmq-agent-reciever   0/30 (avg)           1         10        1          7m16s

Как работает HPA для второго способа:

NAME                  REFERENCE                            TARGETS        MINPODS   MAXPODS   REPLICAS   AGE
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   <unknown>/30   1         10        0          4s
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   <unknown>/30   1         10        1          15s
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   0/30           1         10        1          60s
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   41/30          1         10        1          2m
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   41/30          1         10        2          2m15s
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   41/30          1         10        3          2m30s
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   41/30          1         10        5          2m45s
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   5/30           1         10        7          3m
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   0/30           1         10        7          4m1s
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   0/30           1         10        2          8m1s
rabbitmq-server-hpa   Deployment/rabbitmq-agent-reciever   0/30           1         10        1          9m1s

Какая разница

Разберём разницу в вариантах, в одном TARGETS с (avg) в другом REPLICAS поднималась до 7. В ScaledObject тип метрики по умолчанию AverageValue (1,2), а для второго варианта в hpa.yaml у нас указан тип Value.
AverageValue рассчитывается как среднее кол-во сообщений на каждую реплику (т.е. делится на количество подов), а Value - абсолютное значение. У нас 50 сообщений при пороге в 30 (hpa.yaml, keda.yaml, kedavm.yaml): 50/30 = 1.67, что превышает 10% по умолчанию для того, чтобы kubernetes начал масштабирование.

Поиграться не только с вариантами, но и с rabbitmq-agent-reciever настройками для hpa в yaml, скачав репозиторий:

git clone --depth 1 https://github.com/mrlioncub/k8s-hpa-rabbitmq-demo.git
cd k8s-hpa-rabbitmq-demo

Установить helm из директории, если изменился helm (например, для KEDA):

helm upgrade --create-namespace --namespace k8-hpa-rabbitmq-demo --install rabbitmq-agent-reciever charts/rabbitmq-agent --set keda.enabled=true