Привет, Хабр!
Сегодня микросервисы требуют постоянного стремления к автоматизации и оптимизации. В этой статье рассмотрим такой инструмент в Kubernetes, как Horizontal Pod Autoscaler или сокращенно HPA.
Развертывание микросервиса
Развернем простое приложение в Kubernetes. Будем использовать стандартный подход через Deployment и Service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-microservice
spec:
replicas: 1 # Начинаем с одного пода
selector:
matchLabels:
app: my-microservice
template:
metadata:
labels:
app: my-microservice
spec:
containers:
- name: my-microservice
image: nginx:latest # Используем NGINX для простоты
resources:
requests:
cpu: 100m # Ресурсы по умолчанию
memory: 256Mi
limits:
cpu: 200m
memory: 512Mi
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-microservice-service
spec:
selector:
app: my-microservice
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIPМанифест описывает простое приложение NGINX, которое будем использовать для тестирования HPA. Создаем Deployment с одним подом и устанавливаем базовые требования к ресурсам.
kubectl apply -f my-microservice.yamlТеперь есть базовый микросервис, готовый к автоскейлингу.
Теперь настроим HPA. Он автоматически увеличивает или уменьшает количество подов в зависимости от нагрузки на CPU.
kubectl autoscale deployment my-microservice --cpu-percent=50 --min=1 --max=10Команда создаёт HPA, который будет отслеживать загрузку CPU и масштабировать Deployment в пределах от 1 до 10 подов, пытаясь поддерживать среднюю загрузку CPU на уровне 50%.
Что здесь важно:
--cpu-percent=50: цель автоскейлинга — поддерживать загрузку CPU на уровне 50%.
--min=1 и --max=10: минимум один под, максимум десять. Эти параметры зависят от приложения и ресурсов кластера.
Для более детальной настройки HPA можно использовать YAML-манифест:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-microservice-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-microservice
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # Цель по CPUЭтот манифест можно применить командой:
kubectl apply -f my-microservice-hpa.yamlПосле настройки HPA убедимся, что он работает корректно. Для этого можно использовать несколько команд, например:
kubectl get hpaМожно увидеть что-то вроде:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
my-microservice-hpa Deployment/my-microservice 30%/50% 1 10 2 5mЭтот вывод показывает:
TARGETS: текущая загрузка CPU (в нашем случае 30%) относительно цели (50%).
REPLICAS: Текущее количество подов (в данном примере 2).
Чтобы протестировать, как работает автоскейлер, можно сгенерировать нагрузку на приложение. Один из способов — запустить контейнер, который будет постоянно отправлять запросы на микросервис:
kubectl run -i --tty load-generator --image=busybox --restart=Never -- /bin/sh
while true; do wget -q -O- http://my-microservice-service; doneЧерез некоторое время, можно снова проверить статус HPA:
kubectl get hpaМожно увидеть, как количество подов увеличивается по мере роста загрузки CPU.
Для остановки нагрузки, можно нажать Ctrl + C в терминале, где запущен load-generator.
Кастомные метрики
Для настройки ��астомных метрик потребуется интеграция с системой мониторинга, например, Prometheus, которая будет собирать данные метрик и предоставлять их для HPA через API.
Допустим, нужно масштабировать приложение на основе количества HTTP-запросов в секунду. Для этого сначала необходимо экспортировать соответствующие метрики из приложения в Prometheus. Пример метрики:
httpRequestsTotal := prometheus.NewCounter(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests processed.",
},
)Код на Go экспортирует метрику http_requests_total, которую можно собрать и использовать для автоскейлинга.
Теперь нужно настроить Prometheus Adapter для работы с этой метрикой. Например, можно добавить следующую конфигурацию в values.yaml для Prometheus Adapter:
rules:
custom:
- seriesQuery: 'http_requests_total{namespace="default"}'
resources:
overrides:
namespace:
resource: namespace
pod:
resource: pod
name:
matches: "^(.*)_total"
as: "${1}_per_second"
metricsQuery: 'rate(http_requests_total{<<.LabelMatchers>>}[2m])'Этот конфиг преобразует метрику http_requests_total в http_requests_per_second, которую можно использовать для автоскейлинга.
Теперь создадим манифест HPA, который будет масштабировать поды на основе количества запросов в секунду:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-microservice-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-microservice
minReplicas: 2
maxReplicas: 10
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"Этот манифест говорит Kubernetes масштабировать микросервис, если среднее количество HTTP-запросов превышает 100 запросов в секунду на под.
Настройка HPA с кастомными метриками — это тонкий процесс. Вот несколько советов, которые помогут вам избежать подводных камней и оптимизировать производительность автоскейлера.
Избегание частого масштабирования
Thrashing — это ситуация, когда автоскейлер часто меняет количество подов из-за слишком агрессивных или неправильно настроенных порогов. Чтобы этого избежать:
Установите адекватные пороговые значения и периоды ожидания. Например, можно настроить задержку между скейлингом с помощью параметра
--horizontal-pod-autoscaler-sync-period.Еще можно использовать плавные метрики, такие как
rate()для запросов, которые вычисляют средние значения за определённый интервал времени, чтобы избежать резких изменений.
HPA по умолч��нию синхронизируется каждые 15 секунд. Этот интервал можно изменить, чтобы снизить нагрузку на систему или ускорить реакцию на изменения нагрузки:
httpRequestsTotal := prometheus.NewCounter(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests processed.",
},
)Увеличение периода синхронизации может снизить частоту изменений, но может задерживать реакцию на резкие скачки нагрузки.
Для более точного контроля за автоскейлингом можно использовать комбинацию метрик, например, CPU и кастомные метрики одновременно:
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"Здесь HPA будет одновременно учитывать загрузку CPU и количество запросов в секунду при масштабировании.
Больше актуальных навыков по инфраструктуре, архитектуре и разработке приложений вы можете получить в рамках практических онлайн-курсов от экспертов отрасли.
