KEDA: автоматическое масштабирование в Kubernetes
Привет, друзья-разработчики и Kubernetes-энтузиасты! Сегодня мы с вами погрузимся в мир KEDA (Kubernetes-based Event Driven Autoscaling) — инструмента, который позволит вашим приложениям масштабироваться как по волшебству.
KEDA позволяет Kubernetes автоматически масштабировать приложения на основе различных внешних событий: сообщений в очередях, метрик из Prometheus, вебхуков и многого другого. Мастхев для некоторых микросервисов.
Самый простой способ установить KEDA — применить официальный манифест:
kubectl apply -f https://github.com/kedacore/keda/releases/download/v2.10.0/keda-2.10.0.yaml
Проверьте статус подов KEDA:
kubectl get pods -n keda
Вы должны увидеть что-то вроде этого:
NAME READY STATUS RESTARTS AGE
keda-operator-7d9f9f8d9b-abcde 1/1 Running 0 2m
keda-operator-metrics-apiserver-xyz123 1/1 Running 0 2m
Если все поды в статусе Running
, значит, установка прошла успешно. Если нет, загляните в логи:
kubectl logs -n keda
Немного расскажу про сами компоненты KEDA:
ScaledObject — это центральный объект конфигурации KEDA. Он связывает приложение (например, Deployment или StatefulSet) с источниками событий, определяя условия масштабирования. В ScaledObject задаются минимальное и максимальное количество реплик, а также параметры триггеров, по которым будет происходить масштабирование.
Trigger — это источник событий или метрик, на основе которых KEDA принимает решение о масштабировании. Это может быть очередь сообщений, метрика из Prometheus или другой источник. Каждый триггер имеет свои параметры и пороги, при превышении которых инициируется масштабирование.
Scaler — компонент, отвечающий за сбор и анализ метрик из триггера. Он регулярно опрашивает источник событий, сравнивает полученные данные с заданными порогами и сообщает оператору о необходимости изменения количества реплик. Каждый тип триггера имеет свой собственный Scaler, оптимизированный для работы с конкретным источником данных.
TriggerAuthentication — объект, обеспечивающий безопасное хранение и доступ к данным подключения к внешним системам. Он содержит конфиденциальную информацию, такую как имена пользователей и пароли, необходимые для взаимодействия с триггерами. TriggerAuthentication гарантирует, что KEDA может безопасно получать доступ к ресурсам.
KEDA Operator — основной компонент, управляющий жизненным циклом ScaledObject и TriggerAuthentication. Он следит за изменениями в этих объектах, инициализирует соответствующие Scaler и взаимодействует с Kubernetes API для масштабирования приложений.
Metrics Server — агрегатор метрик внутри Kubernetes, который собирает данные о ресурсах, используемых подами и узлами. KEDA использует эти метрики для принятия решений о масштабировании, дополняя информацию от внешних триггеров.
Масштабирование п очереди RabbitMQ
Рассмотрим пошаговый пример настройки KEDA для масштабирования приложения на основе количества сообщений в очереди RabbitMQ.
Создадим простой Deployment для приложения, которое будет обрабатывать задачи из очереди RabbitMQ. Предположим, есть Docker-образ myregistry/task-processor:latest
:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: task-processor
labels:
app: task-processor
spec:
replicas: 1
selector:
matchLabels:
app: task-processor
template:
metadata:
labels:
app: task-processor
spec:
containers:
- name: processor
image: myregistry/task-processor:latest
ports:
- containerPort: 8080
env:
- name: RABBITMQ_HOST
value: "my-rabbitmq"
- name: RABBITMQ_QUEUE
value: "tasks"
Применим манифест:
kubectl apply -f deployment.yaml
Для безопасного хранения данных подключения создадим Kubernetes Secret.
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: rabbitmq-secret
type: Opaque
data:
host: bXktcmFiYmF0bXFoYXN0Cg== # закодировано в base64, например, echo -n 'my-rabbitmq' | base64
username: YWRtaW4= # admin
password: cGFzc3dvcmQ= # password
Применим секрет:
kubectl apply -f secret.yaml
Создадим объект TriggerAuthentication
, который будет использоваться для безопасного подключения к RabbitMQ.
# triggerauth.yaml
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: rabbitmq-auth
namespace: default
spec:
secretTargetRef:
- parameter: host
name: rabbitmq-secret
key: host
- parameter: username
name: rabbitmq-secret
key: username
- parameter: password
name: rabbitmq-secret
key: password
Применим манифест:
kubectl apply -f triggerauth.yaml
Теперь создадим ScaledObject
, который будет отслеживать очередь RabbitMQ и масштабировать наше приложение в зависимости от количества сообщений.
# scaledobject.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: task-processor-scaledobject
namespace: default
spec:
scaleTargetRef:
kind: Deployment
name: task-processor
minReplicaCount: 1
maxReplicaCount: 10
cooldownPeriod: 300 # Время в секундах перед уменьшением числа реплик
pollingInterval: 30 # Интервал проверки метрик
triggers:
- type: rabbitmq
metadata:
queueName: tasks
queueLength: "5" # Порог для масштабирования
authenticationRef:
name: rabbitmq-auth
Применим манифест:
kubectl apply -f scaledobject.yaml
Убедимся, что все работает как надо. Напишем простой скрипт на Питоне для добавления задач в очередь и посмотрим, как KEDA реагирует на рост нагрузки.
# send_tasks.py
import pika
import time
def main():
connection = pika.BlockingConnection(pika.ConnectionParameters('my-rabbitmq'))
channel = connection.channel()
channel.queue_declare(queue='tasks')
for i in range(20):
message = f'Task {i}'
channel.basic_publish(exchange='', routing_key='tasks', body=message)
print(f" [x] Sent {message}")
time.sleep(1) # Пауза, чтобы видеть постепенное масштабирование
connection.close()
if __name__ == "__main__":
main()
Запускаем скрипт:
python send_tasks.py
Открываем другой терминал и выполняем команду:
kubectl get pods -w -l app=task-processor
Можно увидеть, как количество реплик вашего приложения увеличивается по мере добавления задач в очередь:
NAME READY STATUS RESTARTS AGE
task-processor-6d4d5c8c6d-abcde 1/1 Running 0 1m
task-processor-6d4d5c8c6d-fghij 1/1 Running 0 30s
...
Масштабирование по HTTP-запросам с Prometheus
Рассмотрим еще один пример использования KEDA — масштабирование приложения на основе количества HTTP-запросов с Prometheus.
Создадим простой HTTP-сервис, который будет обрабатывать запросы. Предположим, есть Docker-образ myregistry/http-processor:latest
.
# http-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-processor
labels:
app: http-processor
spec:
replicas: 1
selector:
matchLabels:
app: http-processor
template:
metadata:
labels:
app: http-processor
spec:
containers:
- name: processor
image: myregistry/http-processor:latest
ports:
- containerPort: 8080
Применим манифест:
kubectl apply -f http-deployment.yaml
Создадим ScaledObject
, который будет масштабировать HTTP-сервис на основе метрик из Prometheus.
# http-scaledobject.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: http-processor-scaledobject
namespace: default
spec:
scaleTargetRef:
kind: Deployment
name: http-processor
minReplicaCount: 1
maxReplicaCount: 5
cooldownPeriod: 300
pollingInterval: 30
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus-server.default.svc.cluster.local
metricName: http_requests_total
threshold: "100" # Масштабировать при превышении 100 запросов
query: sum(rate(http_requests_total[2m])) by (job) > 100
Применим манифест:
kubectl apply -f http-scaledobject.yaml
Напишем скрипт для генерации HTTP-запросов к сервису.
# send_http_requests.py
import requests
import time
def main():
url = 'http://:8080/process'
for i in range(200):
response = requests.get(url)
print(f" [x] Sent request {i}, Response Code: {response.status_code}")
time.sleep(0.5) # Пауза между запросами
if __name__ == "__main__":
main()
Если вы работаете локально, используйте localhost
или соответствующий сервисный URL в кластере.
Запускаем скрипт:
python send_http_requests.py
Открываем другой терминал и выполняем команду:
kubectl get pods -w -l app=task-processor
В этом примере так же увидим, как количество реплик вашего HTTP-сервиса увеличивается по мере роста числа запросов.
В заключение приглашаем всех желающих на первые открытые уроки в этом году:
14 января — Percona XtraDB Cluster (PXC): знакомство и настройка. Подробнее
15 января — Ansible: быстрый старт. Подробнее
16 января — Улица разбитых кластеров: про бэкапы и реплики в PostgreSQL. Подробнее