Compare languages | Модуль prometheus-metrics-adapter: примеры конфигурации

Далее рассматривается только HPA с apiVersion: autoscaling/v2, чья поддержка появилась начиная с Kubernetes v1.12.

Below, only HPAs of the apiVersion: autoscaling/v2 type (supported from Kubernetes v1.12 onward) are considered.

В общем виде для настройки HPA требуется:

  • определить, что масштабируем (.spec.scaleTargetRef);
  • определить диапазон масштабирования (.spec.minReplicas, .scale.maxReplicas);
  • зарегистрировать в API Kubernetes и определить метрики, на основе которых будем масштабировать (.spec.metrics).

To configure an HPA, you need to:

  • determine the scaling target (.spec.scaleTargetRef);
  • define the scaling range (.spec.minReplicas, .scale.maxReplicas);
  • define the metrics that will be used for scaling and register them with the Kubernetes API (.spec.metrics).

Метрики с точки зрения HPA бывают трех видов:

  • классические — с типом (.spec.metrics[].type) «Resource», используются для простейшего масштабирования по потреблению процессора и памяти;
  • кастомные — с типами (.spec.metrics[].type) «Pods» или «Object»;
  • внешние — с типом (.spec.metrics[].type) «External».

There are three types of metrics in terms of an HPA:

  • classic — these have the “Resource” type (.spec.metrics[].type) and are used to scale based on memory and CPU consumption;
  • custom — these have the “Pods” or “Object” type (.spec.metrics[].type);
  • external — these have the “External” type (.spec.metrics[].type).

Важно! По умолчанию HPA использует разные подходы при масштабировании в ту или иную сторону:

  • Если метрики говорят о том, что надо масштабировать вверх, это происходит немедленно (spec.behavior.scaleUp.stabilizationWindowSeconds = 0). Единственное ограничение — скорость прироста: за 15 секунд либо поды могут максимум удвоиться, либо, если подов меньше 4, добавятся 4 новых пода.
  • Если метрики говорят о том, что надо масштабировать вниз, это происходит плавно. В течение 5 минут (spec.behavior.scaleUp.stabilizationWindowSeconds = 300) собираются предложения о новом количестве реплик, в результате чего выбирается самое большое значение. Ограничений на количество «уволенных» подов за раз нет.

Caution! During scale, HPA uses different approaches by default:

  • If the metrics indicate that HPA must scale up the target, it happens immediately (spec.behavior.scaleUp.stabilizationWindowSeconds = 0). The only limitation — scale speed. During 15 seconds, the Pods can either double their number or if there are less than 4 Pods now, maximum four new Pods will be added.
  • If the metrics indicate that HPA must scale down the target, it happens smoothly. During 5 minutes (spec.behavior.scaleUp.stabilizationWindowSeconds = 300), HPA collects suggestions about scaling and finally chooses the largest value. There aren’t scale-down speed limitations.

Если есть проблемы с флаппингом метрик и наблюдается взрывной рост ненужных реплик приложения, имеются разные подходы:

  • Обернуть метрику агрегирующей функцией (например, avg_over_time()), если метрика определена PromQL-запросом. Пример…
  • Увеличить spec.behavior.scaleUp.stabilizationWindowSeconds в ресурсе HorizontalPodAutoscaler. В этом случае в течение обозначенного периода будут собираться предложения об увеличении количества реплик, в результате чего будет выбрано самое скромное предложение. Иными словами, это решение тождественно применению агрегирующей функции min_over_time(<stabilizationWindowSeconds>), но только в том случае, если метрика растет и требуется масштабирование вверх. Для масштабирования вниз, как правило, достаточно стандартных настроек. Пример…
  • Сильнее ограничить скорость прироста новых реплик с помощью spec.behavior.scaleUp.policies.

If you have metric flapping problems which lead to unwanted scales, there are options:

  • If your metric is based on a PromQL query, you can use an aggregation function like avg_over_time() to smooth out the fluctuations. Example…
  • You can increase spec.behavior.scaleUp.stabilizationWindowSeconds in HorisontalPodAutoscaler resource. In this case, HPA collects scale suggestions during the period and finally chooses the minimal value. In other words, this solution is identical using the min_over_time(<stabilizationWindowSeconds>) aggregating function only when the metric is growing up, and HPA decides to scale up. For scaling down, it is usually enough standard Stabilisation Window settings. Example…
  • You can also tighten the scale-up speed with spec.behavior.scaleUp.policies settings.

Какой тип масштабирования мне подойдет?

What scaling type should I prefer?

  1. С классическим все понятно.
  2. Если у вас одно приложение, источник метрик находится внутри namespace и он связан с одним из объектов, используйте кастомные Namespace-scoped-метрики.
  3. Если у вас много приложений используют одинаковую метрику, источник которой находится в namespace приложения и которая связана с одним из объектов, используйте кастомные Cluster-wide-метрики. Подобные метрики предусмотрены на случай необходимости выделения общих инфраструктурных компонентов в отдельный деплой («infra»).
  4. Если источник метрики не привязан к namespace приложения, используйте внешние метрики. Например, метрики облачного провайдера или внешнего SaaS-сервиса.
  1. The typical use-cases of a classic type are pretty obvious.
  2. Suppose you have a single application, the source of metrics is located inside the namespace, and it is associated with one of the objects. In this case, we recommend using the custom namespace-scoped metrics.
  3. Use custom Cluster-wide metrics if multiple applications use the same metric associated with one of the objects, and the metric’s source belongs to the application namespace. Such metrics can help you combine common infrastructure components into a separate (“infra”) Deployment.
  4. Use external metrics if the source of the metric does not belong to the application namespace. These can be, for example, cloud provider or SaaS-related metrics.

Важно! Настоятельно рекомендуется пользоваться или вариантом 1 (классическими метриками), или вариантом 2 (кастомными метриками, определяемыми в namespace), так как в этом случае вы можете определить всю конфигурацию приложения, включая логику его автомасштабирования, в репозитарии самого приложения. Варианты 3 и 4 стоит рассматривать, только если у вас большая коллекция идентичных микросервисов.

Caution! We strongly recommend using either Option 1. (classic metrics) or Option 2. (custom metrics defined in the namespace). In this case, you can define the entire configuration of the application (including the autoscaling logic) in the repository of the application. Options 3 and 4 should only be considered if you have a large collection of identical microservices.

Классическое масштабирование по потреблению ресурсов

Classic resource consumption-based scaling

Пример HPA для масштабирования по базовым метрикам из metrics.k8s.io: CPU и памяти подов. Особое внимание на averageUtulization — это значение отражает целевой процент ресурсов, который был реквестирован.

Below is an example of the HPA for scaling based on standard metrics.k8s.iometrics (CPU and memory of the Pods). Please, take special note of the averageUtulization — this value reflects the target percentage of resources that have been requested.

yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: app-hpa namespace: app-prod spec: Указывается контроллер, который нужно масштабировать (ссылка на deployment или statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: app Границы масштабирования контроллера. minReplicas: 1 maxReplicas: 10 Если для приложения характерны кратковременные скачки потребления CPU, можно отложить принятие решения о масштабировании, чтобы убедиться, что оно необходимо. По умолчанию масштабирование вверх происходит немедленно. behavior: scaleUp: stabilizationWindowSeconds: 300 metrics: Масштабирование по CPU и памяти.

  • type: Resource resource: name: cpu target: Масштабирование, когда среднее использование CPU всех подов в scaleTargetRef превышает заданное значение. Для метрики с type: Resource доступен только type: Utilization. type: Utilization Масштабирование, если для всех подов из Deployment запрошено по 1 ядру и в среднем уже используется более 700m. averageUtilization: 70
  • type: Resource resource: name: memory target: Пример масштабирования, когда среднее использование памяти всех подов в scaleTargetRef превышает заданное значение. type: Utilization Масштабирование, если для подов запрошено по 1 ГБ памяти и в среднем использовано уже более 800 МБ. averageUtilization: 80

yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: app-hpa namespace: app-prod spec: The targets of scaling (link to a Deployment or StatefulSet). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: app Min and max values for replication. minReplicas: 1 maxReplicas: 10 behavior: If short-term spikes of CPU usage are regular for the application, you can postpone the scaling decision to be sure if it is necessary. By default, scaling up occurs immediately. scaleUp: stabilizationWindowSeconds: 300 metrics: Scaling based on CPU and Memory consumption.

  • type: Resource resource: name: cpu target: Scale up if the average CPU utilization by all the Pods in scaleTargetRef exceeds the specified value. For type: Resource metrics only the type: Utilization parameter is available. type: Utilization Scale up if all the Deployment’s Pods have requested 1 CPU core and consumed more than 700m on average. averageUtilization: 70
  • type: Resource resource: name: memory target: Scale up if the average Memory utilization by all the Pods in scaleTargetRef exceeds the specified value. type: Utilization Scale up if all the Deployment’s Pods have requested 1GB and consumed more than 800MB on average. averageUtilization: 80

Масштабирование по кастомным метрикам

Custom metrics-based scaling

Регистрируем кастомные метрики в Kubernetes API

Registering custom metrics with the Kubernetes API

Кастомные метрики необходимо регистрировать в API /apis/custom.metrics.k8s.io/, в нашем случае эту регистрацию производит prometheus-metrics-adapter (и он же реализует API). Потом на эти метрики можно будет ссылаться из объекта HorizontalPodAutoscaler. Настройка ванильного prometheus-metrics-adapter — достаточно трудоемкий процесс, но мы его несколько упростили, определив набор Custom Resources с разным Scope:

  • Namespaced:
  • ServiceMetric;
  • IngressMetric;
  • PodMetric;
  • DeploymentMetric;
  • StatefulsetMetric;
  • NamespaceMetric;
  • DaemonSetMetric (недоступен пользователям).
  • Cluster:
  • ClusterServiceMetric (недоступен пользователям);
  • ClusterIngressMetric (недоступен пользователям);
  • ClusterPodMetric (недоступен пользователям);
  • ClusterDeploymentMetric (недоступен пользователям);
  • ClusterStatefulsetMetric (недоступен пользователям);
  • ClusterDaemonSetMetric (недоступен пользователям).

Custom metrics must be registered with the /apis/custom.metrics.k8s.io/ API. In our case, prometheus-metrics-adapter (it also implements the API) performs the registration. The HorizontalPodAutoscaler object can refer to these metrics after the registration is complete. Setting up a vanilla prometheus-metrics-adapter is a time-consuming process. Happily, we have somewhat simplified it by defining a set of Custom Resources with different Scopes:

  • Namespaced:
  • ServiceMetric
  • IngressMetric
  • PodMetric
  • DeploymentMetric
  • StatefulsetMetric
  • NamespaceMetric
  • DaemonSetMetric (not available to users)
  • Cluster:
  • ClusterServiceMetric (not available to users)
  • ClusterIngressMetric (not available to users)
  • ClusterPodMetric (not available to users)
  • ClusterDeploymentMetric (not available to users)
  • ClusterStatefulsetMetric (not available to users)
  • ClusterDaemonSetMetric (not available to users)

С помощью Cluster-scoped-ресурса можно определить метрику глобально, а с помощью Namespaced-ресурса можно ее локально переопределять. Формат у всех custom resource — одинаковый.

You can globally define a metric using the Cluster-scoped resource, while the namespaced resource allows you to redefine it locally. All CRs have the same format.

Применяем кастомные метрики в HPA

Using custom metrics with HPA

После регистрации кастомной метрики на нее можно сослаться. С точки зрения HPA, кастомные метрики бывают двух видов — Pods и Object. С Object все просто — это отсылка к объекту в кластере, который имеет в Prometheus метрики с соответствующими лейблами (namespace=XXX,ingress=YYY). Эти лейблы будут подставляться вместо <<.LabelMatchers>> в вашем кастомном запросе.

After a custom metric is registered, you can refer to it. For the HPA, custom metrics can be of two types — Pods and Object. Object is a reference to a cluster object that has metrics with the appropriate labels (namespace=XXX,ingress=YYY) in Prometheus. These labels will be substituted instead of <<.LabelMatchers>> in your custom request.

yaml apiVersion: deckhouse.io/v1beta1 kind: IngressMetric metadata: name: mymetric namespace: mynamespace spec: query: sum(rate(ingress_nginx_detail_requests_total{«.LabelMatchers»}[2m])) by («.GroupBy») OR on() vector(0) — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: Указывается контроллер, который нужно масштабировать (ссылка на deployment или statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myapp minReplicas: 1 maxReplicas: 2 Метрики, используемые для масштабирования. Пример использования кастомных метрик. metrics:

  • type: Object object: Объект, который обладает метриками в Prometheus. describedObject: apiVersion: networking.k8s.io/v1 kind: Ingress name: myingress metric: Метрика, зарегистрированная с помощью custom resource IngressMetric или ClusterIngressMetric. Можно использовать rps_1m, rps_5m или rps_15m которые поставляются с модулем prometheus-metrics-adapter. name: mymetric target: Для метрик типа Object можно использовать Value или AverageValue. type: AverageValue Масштабирование происходит, если среднее значение кастомной метрики для всех подов в Deployment сильно отличается от 10. averageValue: 10

yaml apiVersion: deckhouse.io/v1beta1 kind: IngressMetric metadata: name: mymetric namespace: mynamespace spec: query: sum(rate(ingress_nginx_detail_requests_total{«.LabelMatchers»}[2m])) by («.GroupBy») OR on() vector(0) — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: The targets of scaling (link to a deployment or statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myapp minReplicas: 1 maxReplicas: 2 What metrics to use for scaling. We use custom metrics of the Object type. metrics:

  • type: Object object: Some object that has metrics in Prometheus. describedObject: apiVersion: networking.k8s.io/v1 kind: Ingress name: myingress metric: The metric registered using IngressMetric or ClusterIngressMetric CRs. Can be used rps_1m, rps_5m or rps_15m which come with the prometheus-metrics-adapter module. name: mymetric target: Value or AverageValue can be used for metrics of the Object type. type: AverageValue Scaling occurs if the average value for all Pods in the Deployment of the custom metric is very different from 10. averageValue: 10

C Pods сложнее — из ресурса, который масштабирует HPA, будут извлечены все поды и по каждому будут собраны метрики с соответствующими лейблами (namespace=XXX,pod=YYY-sadiq,namespace=XXX,pod=YYY-e3adf и т. д.). Из этих метрик HPA посчитает среднее и использует для масштабирования. Пример…

In the case of the Pods metric type, the process is more complex. First, metrics with the appropriate labels (namespace=XXX,pod=YYY-sadiq,namespace=XXX,pod=YYY-e3adf,…) will be collected for all the Pods of the resource to scale. Next, HPA will calculate the average value based on these metrics and will use it for scaling. Example…

Пример использования кастомных метрик с размером очереди RabbitMQ

Example of using RabbitMQ queue size-based custom metrics

Имеем очередь send_forum_message в RabbitMQ, для которого зарегистрирован сервис rmq. Если сообщений в очереди больше 42 — масштабируем.

Suppose there is a send_forum_message queue in RabbitMQ, and this message broker is exposed as an rmq service. Then, suppose, we want to scale up the cluster if there are more than 42 messages in the queue.

yaml apiVersion: deckhouse.io/v1beta1 kind: ServiceMetric metadata: name: rmq-queue-forum-messages namespace: mynamespace spec: query: sum (rabbitmq_queue_messages{«.LabelMatchers»,queue=~”send_forum_message”,vhost=”/”}) by («.GroupBy») — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: Указывается контроллер, который нужно масштабировать (ссылка на deployment или statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myconsumer minReplicas: 1 maxReplicas: 5 metrics:

  • type: Object object: describedObject: apiVersion: v1 kind: Service name: rmq metric: name: rmq-queue-forum-messages target: type: Value value: 42

yaml apiVersion: deckhouse.io/v1beta1 kind: ServiceMetric metadata: name: rmq-queue-forum-messages namespace: mynamespace spec: query: sum (rabbitmq_queue_messages{«.LabelMatchers»,queue=~”send_forum_message”,vhost=”/”}) by («.GroupBy») — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: The targets of scaling (link to a deployment or statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myconsumer minReplicas: 1 maxReplicas: 5 metrics:

  • type: Object object: describedObject: apiVersion: v1 kind: Service name: rmq metric: name: rmq-queue-forum-messages target: type: Value value: 42

Пример использования нестабильной кастомной метрики

Example of using unstable custom metric

Улучшение предыдущего примера.

Improvement for example above.

Имеем очередь send_forum_message в RabbitMQ, для которого зарегистрирован сервис rmq. Если сообщений в очереди больше 42 — масштабируем. При этом мы не хотим реагировать на кратковременные вспышки, для этого усредняем метрику с помощью MQL-функции avg_over_time().

Suppose there is a send_forum_message queue in RabbitMQ, and this message broker is exposed as an rmq service. Then, suppose, we want to scale up the cluster if there are more than 42 messages in the queue. At the same time, we do not want to react to short-term spikes, for this we use MQL-function avg_over_time().

yaml apiVersion: deckhouse.io/v1beta1 kind: ServiceMetric metadata: name: rmq-queue-forum-messages namespace: mynamespace spec: query: sum (avg_over_time(rabbitmq_queue_messages{«.LabelMatchers»,queue=~”send_forum_message”,vhost=”/”}[5m])) by («.GroupBy») — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: Указывается контроллер, который нужно масштабировать (ссылка на deployment или statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myconsumer minReplicas: 1 maxReplicas: 5 metrics:

  • type: Object object: describedObject: apiVersion: v1 kind: Service name: rmq metric: name: rmq-queue-forum-messages target: type: Value value: 42

yaml apiVersion: deckhouse.io/v1beta1 kind: ServiceMetric metadata: name: rmq-queue-forum-messages namespace: mynamespace spec: query: sum (avg_over_time(rabbitmq_queue_messages{«.LabelMatchers»,queue=~”send_forum_message”,vhost=”/”}[5m])) by («.GroupBy») — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: The targets of scaling (link to a deployment or statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myconsumer minReplicas: 1 maxReplicas: 5 metrics:

  • type: Object object: describedObject: apiVersion: v1 kind: Service name: rmq metric: name: rmq-queue-forum-messages target: type: Value value: 42

Примеры с использованием кастомных метрик типа Pods

Examples of using custom metrics of the Pods type

Хотим, чтобы среднее количество php-fpm-воркеров в Deployment mybackend было не больше 5.

Suppose we want the average number of php-fpm workers in the mybackend Deployment to be no more than 5.

yaml apiVersion: deckhouse.io/v1beta1 kind: PodMetric metadata: name: php-fpm-active-workers spec: query: sum (phpfpm_processes_total{state=”active”,«.LabelMatchers»}) by («.GroupBy») — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: Указывается контроллер, который нужно масштабировать (ссылка на deployment или statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: mybackend minReplicas: 1 maxReplicas: 5 metrics: Указание HPA обойти все поды Deployment’а и собрать с них метрики.

  • type: Pods Указывать describedObject в отличие от type: Object не надо. pods: metric: Кастомная метрика, зарегистрированная с помощью custom resource PodMetric. name: php-fpm-active-workers target: Для метрик с type: Pods можно использовать только AverageValue. type: AverageValue Масштабирование, если среднее значение метрики у всех подов Deployment’а больше 5. averageValue: 5

yaml apiVersion: deckhouse.io/v1beta1 kind: PodMetric metadata: name: php-fpm-active-workers spec: query: sum (phpfpm_processes_total{state=”active”,«.LabelMatchers»}) by («.GroupBy») — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: The targets of scaling (link to a deployment or statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: mybackend minReplicas: 1 maxReplicas: 5 metrics: HPA must go through all the Pods in the Deployment and collect metrics from them.

  • type: Pods You do not need to specify descripedObject (in contrast to type: Object). pods: metric: Custom metric, registered using the PodMetric CR. name: php-fpm-active-workers target: For type: Pods metrics, the AverageValue can only be used. type: AverageValue Scale up if the average metric value for all the Pods of the myworker Deployment is greater than 5. averageValue: 5

Масштабируем Deployment по процентному количеству активных php-fpm-воркеров.

The Deployment is scaled based on the percentage of active php-fpm workers.

yaml

apiVersion: deckhouse.io/v1beta1 kind: PodMetric metadata: name: php-fpm-active-worker spec: Процент активных php-fpm-воркеров. Функция round() для того, чтобы не смущаться от миллипроцентов в HPA. query: round(sum by(«.GroupBy») (phpfpm_processes_total{state=”active”,«.LabelMatchers»}) / sum by(«.GroupBy») (phpfpm_processes_total{«.LabelMatchers»}) * 100) — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: {{ .Chart.Name }}-hpa spec: Указывается контроллер, который нужно масштабировать (ссылка на deployment или statefulset). scaleTargetRef: apiVersion: apps/v1beta1 kind: Deployment name: {{ .Chart.Name }} minReplicas: 4 maxReplicas: 8 metrics:

  • type: Pods pods: metric: name: php-fpm-active-worker target: type: AverageValue Масштабирование, если в среднем по Deployment 80% воркеров заняты. averageValue: 80

yaml

apiVersion: deckhouse.io/v1beta1 kind: PodMetric metadata: name: php-fpm-active-worker spec: Percentage of active php-fpm workers. The round() function rounds the percentage. query: round(sum by(«.GroupBy») (phpfpm_processes_total{state=”active”,«.LabelMatchers»}) / sum by(«.GroupBy») (phpfpm_processes_total{«.LabelMatchers»}) * 100) — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: {{ .Chart.Name }}-hpa spec: The targets of scaling (link to a deployment or statefulset). scaleTargetRef: apiVersion: apps/v1beta1 kind: Deployment name: {{ .Chart.Name }} minReplicas: 4 maxReplicas: 8 metrics:

  • type: Pods pods: metric: name: php-fpm-active-worker target: type: AverageValue Scale up if, on average, 80% of workers in the deployment are running at full capacity. averageValue: 80

Регистрируем внешние метрики в Kubernetes API

Registering external metrics with the Kubernetes API

Модуль prometheus-metrics-adapter поддерживает механизм externalRules, с помощью которого можно определять кастомные PromQL-запросы и регистрировать их как метрики.

The prometheus-metrics-adapter module supports the externalRules mechanism. Using it, you can create custom PromQL requests and register them as metrics.

В наших инсталляциях мы добавили универсальное правило, которое позволяет создавать свои метрики без внесения настроек в prometheus-metrics-adapter, — «любая метрика в Prometheus с именем kube_adapter_metric_<name> будет зарегистрирована в API под именем <name>». То есть остается либо написать exporter, который будет экспортировать подобную метрику, либо создать recording rule в Prometheus, которое будет агрегировать вашу метрику на основе других метрик.

In our installations, we have implemented a universal rule that allows you to create your metrics without using prometheus-metrics-adapter — “any Prometheus metric called kube_adapter_metric_<name> will be registered in the API under the <name>”. In other words, all you need is to either write an exporter (to export the metric) or create a recording rule in Prometheus that will aggregate your metric based on other metrics.

Пример CustomPrometheusRules:

An example of CustomPrometheusRules:

yaml apiVersion: deckhouse.io/v1 kind: CustomPrometheusRules metadata: Рекомендованный шаблон для названия ваших CustomPrometheusRules. name: prometheus-metrics-adapter-mymetric spec: groups: Рекомендованный шаблон.

  • name: prometheus-metrics-adapter.mymetric rules: Название вашей новой метрики. Важно! Префикс ‘kube_adapter_metric_’ обязателен.
  • record: kube_adapter_metric_mymetric Запрос, результаты которого попадут в итоговую метрику, нет смысла тащить в нее лишние лейблы. expr: sum(ingress_nginx_detail_sent_bytes_sum) by (namespace,ingress)

yaml apiVersion: deckhouse.io/v1 kind: CustomPrometheusRules metadata: The recommended template for naming your CustomPrometheusRules. name: prometheus-metrics-adapter-mymetric spec: groups: Recommended template for the name key.

  • name: prometheus-metrics-adapter.mymetric rules: The name of the new metric. Pay attention! The ‘kube_adapter_metric_’ prefix is required.
  • record: kube_adapter_metric_mymetric The results of this request will be passed to the final metric; there is no reason to include excess labels into it. expr: sum(ingress_nginx_detail_sent_bytes_sum) by (namespace,ingress)

Применяем внешние метрики в HPA

Using external metrics with HPA

После регистрации внешней метрики на нее можно сослаться.

You can refer to a metric after it is registered.

yaml kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: Указывается контроллер, который нужно масштабировать (ссылка на deployment или statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myapp minReplicas: 1 maxReplicas: 2 metrics: Используем внешние метрики для масштабирования.

  • type: External external: metric: Метрика, которую мы зарегистрировали с помощью создания метрики в Prometheus kube_adapter_metric_mymetric, но без префикса ‘kube_adapter_metric_’. name: mymetric selector: Для внешних метрик можно и нужно уточнять запрос с помощью лейблов. matchLabels: namespace: mynamespace ingress: myingress target: Для метрик типа External можно использовать только type: Value. type: Value Масштабирование, если значение нашей метрики больше 10. value: 10

yaml kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: The targets of scaling (link to a deployment or statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myapp minReplicas: 1 maxReplicas: 2 Use external metrics for scaling. metrics:

  • type: External external: metric: The metric that we registered by creating a metric in Prometheus’s kube_adapter_metric_mymetric but without ‘kube_adapter_metric_’ prefix. name: mymetric selector: For external metrics, you can and should specify matching labels. matchLabels: namespace: mynamespace ingress: myingress target: Only type: Value can be used for metrics of the External type. type: Value Scale up if the value of our metric is greater than 10. value: 10

Пример с размером очереди в Amazon SQS

Example of scaling based on the Amazon SQS queue size

Для интеграции с SQS вам понадобится установка экспортера. Для этого нужно завести отдельный «служебный» Git-репозитарий (или, например, использовать «инфраструктурный» репозитарий) и разместить в нем установку этого экспортера, а также скрипт для создания необходимого CustomPrometheusRules, таким образом интегрировав кластер. Если же вам нужно настроить автомасштабирование только для одного приложения (особенно живущего в одном пространстве имен), лучше ставить экспортер вместе с этим приложением и воспользоваться NamespaceMetrics.

Note that an exporter is required to integrate with SQS. For this, create a separate “service” git repository (or you can use an “infrastructure” repository) and put the installation of this exporter as well as the script to create the necessary CustomPrometheusRules into this repository. If you need to configure autoscaling for a single application (especially if it runs in a single namespace), we recommend putting the exporter together with the application and using NamespaceMetrics.

В следующем примере подразумевается, что в Amazon SQS работает очередь send_forum_message. Если сообщений в очереди больше 42 — масштабируем. Для получения метрик из Amazon SQS понадобится exporter (например, sqs-exporter).

Suppose there is a send_forum_message queue in Amazon SQS. Then, suppose, we want to scale up the cluster if there are more than 42 messages in the queue. Also, you will need an exporter to collect Amazon SQS metrics (say, sqs-exporter).

yaml apiVersion: deckhouse.io/v1 kind: CustomPrometheusRules metadata: Рекомендованное название — prometheus-metrics-adapter-. name: prometheus-metrics-adapter-sqs-messages-visible spec: groups: Рекомендованный шаблон названия.

  • name: prometheus-metrics-adapter.sqs_messages_visible rules: Важно! Префикс ‘kube_adapter_metric_’ обязателен.
  • record: kube_adapter_metric_sqs_messages_visible expr: sum (sqs_messages_visible) by (queue) — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: Указывается контроллер, который нужно масштабировать (ссылка на deployment или statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myconsumer minReplicas: 1 maxReplicas: 5 metrics:
  • type: External external: metric: name должен совпадать с CustomPrometheusRules record без префикса ‘kube_adapter_metric_’. name: sqs_messages_visible selector: matchLabels: queue: send_forum_messages target: type: Value value: 42

yaml apiVersion: deckhouse.io/v1 kind: CustomPrometheusRules metadata: The recommended name — prometheus-metrics-adapter-. name: prometheus-metrics-adapter-sqs-messages-visible Pay attention! namespace: d8-monitoring labels: Pay attention! prometheus: main Pay attention! component: rules spec: groups:

  • name: prometheus-metrics-adapter.sqs_messages_visible # the recommended template rules:
  • record: kube_adapter_metric_sqs_messages_visible # Pay attention! The ‘kube_adapter_metric_’ prefix is required. expr: sum (sqs_messages_visible) by (queue) — kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: myhpa namespace: mynamespace spec: The targets of scaling (link to a deployment or statefulset). scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myconsumer minReplicas: 1 maxReplicas: 5 metrics:
  • type: External external: metric: Must match CustomPrometheusRules record name without ‘kube_adapter_metric_’ prefix. name: sqs_messages_visible selector: matchLabels: queue: send_forum_messages target: type: Value value: 42

Способы отладки

Debugging

Как получить список кастомных метрик?

How do I get a list of custom metrics?

shell kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/

shell kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/

Как получить значение метрики, привязанной к объекту?

How do I get the value of a metric associated with an object?

shell kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-namespace/services//my-service-metric kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-namespace/ingresses//rps_1m kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-namespace/ingresses/*/mymetric

shell kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-namespace/services//my-service-metric kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-namespace/ingresses//rps_1m kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-namespace/ingresses/*/mymetric

Как получить значение метрики, созданной через NamespaceMetric?

How do I get the value of a metric created via NamespaceMetric?

shell kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-namespace/metrics/my-ns-metric

shell kubectl get –raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-namespace/metrics/my-ns-metric

Как получить external-метрики?

How do I get external metrics?

shell kubectl get –raw /apis/external.metrics.k8s.io/v1beta1 kubectl get –raw /apis/external.metrics.k8s.io/v1beta1/namespaces/d8-ingress-nginx/d8_ingress_nginx_ds_cpu_utilization

shell kubectl get –raw /apis/external.metrics.k8s.io/v1beta1 kubectl get –raw /apis/external.metrics.k8s.io/v1beta1/namespaces/d8-ingress-nginx/d8_ingress_nginx_ds_cpu_utilization