Далее рассматривается только 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?
|
- С классическим все понятно.
- Если у вас одно приложение, источник метрик находится внутри namespace и он связан с одним из объектов, используйте кастомные Namespace-scoped-метрики.
- Если у вас много приложений используют одинаковую метрику, источник которой находится в namespace приложения и которая связана с одним из объектов, используйте кастомные Cluster-wide-метрики. Подобные метрики предусмотрены на случай необходимости выделения общих инфраструктурных компонентов в отдельный деплой («infra»).
- Если источник метрики не привязан к namespace приложения, используйте внешние метрики. Например, метрики облачного провайдера или внешнего SaaS-сервиса.
|
- The typical use-cases of a classic type are pretty obvious.
- 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.
- 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.
- 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.io metrics (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
|