Автоматический скейлинг Celery с помощью KEDA в Kubernetes на основе RabbitMQ

Kubernetes logo
Kubernetes logo

Современные приложения часто работают с асинхронными задачами для обработки фоновых операций. Celery в сочетании с брокером сообщений (например, RabbitMQ) – одно из популярных решений для таких задач. Однако ручное управление количеством подов для обработки задач в Kubernetes – неэффективно, особенно в условиях переменной нагрузки. На помощь приходит KEDA (Kubernetes Event-Driven Autoscaling), которая позволяет масштабировать поды на основе событий, таких как длина очередей RabbitMQ.

Предположим, у нас есть сервис, который обрабатывает задачи Celery. Задачи публикуются в очереди RabbitMQ, а Celery-воркеры обрабатывают их в Kubernetes. Наша цель:

  • Увеличивать количество воркеров, если длина очереди превышает определенный порог.
  • Уменьшать количество воркеров, когда очередь разгружена.

Как работает скейлинг в KEDA?

  1. Скейлинг вверх:
    • KEDA проверяет длину очереди каждые pollingInterval секунд.
    • Если длина очереди превышает значение в queueLength, KEDA увеличивает количество подов, но не больше значения maxReplicaCount.
  2. Скейлинг вниз:
    • После разгрузки очереди KEDA начинает уменьшать количество подов.
    • Уменьшение происходит через интервал cooldownPeriod.
    • Количество подов не опустится ниже значения minReplicaCount.

Преимущества KEDA для скейлинга Celery

  1. Экономия ресурсов: Поды запускаются только при наличии нагрузки.
  2. Гибкость настройки: Можно задать различные параметры для каждой очереди.
  3. Масштабируемость: Удобно поддерживать различные типы задач Celery, создавая отдельные ScaledObject для каждой очереди.

Deployment Celery в kubernetes для примера:
Само собой обратите и замените на свои значения поля: name, labels, image, args. Это лишь пример обобщенного deployment celery worker’a

apiVersion: apps/v1
kind: Deployment
metadata:
  name: celery-main
  namespace: your-namespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: celery-main
  template:
    metadata:
      labels:
        app: celery-main
    spec:
      containers:
      - name: celery-main
        image: celery.image:latest
        args: ["celery", "-A", "project", "worker", "-n", "celery@images", "-Q", "images_queue", "-E", "--concurrency=1", "--pool=threads", "--time-limit=7200"]
        resources:
          limits:
            cpu: "500m"
            memory: "256Mi"
          requests:
            cpu: "250m"
            memory: "128Mi"

Далее в кластер нам необходимо установить KEDA оператора, сделать это можно с помощью helm:

 helm install keda kedacore/keda --namespace keda --create-namespace

Настройка ScaledObject для KEDA

ScaledObject – это ресурс KEDA, который описывает правила автоматического скейлинга подов. Вот пример настройки:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: celery-main-scaler
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: celery-main        # Имя деплоймента celery
  pollingInterval: 30        # Частота проверки длины очереди (сек.)
  cooldownPeriod: 300        # Задержка перед уменьшением числа подов (сек.)
  minReplicaCount: 1         # Минимальное количество подов
  maxReplicaCount: 10        # Максимальное количество подов
  triggers:
  - type: rabbitmq
    metadata:
      queueName: "images_queue"    # Название очереди RabbitMQ
      hostFromEnv: RABBITMQ_HOST
      queueLength: "10"      # Порог длины очереди для скейлинга
    authenticationRef:
      name: rabbitmq-trigger-auth

Разбор конфигурации:

  1. scaleTargetRef: Указывает на деплоймент Celery, который нужно масштабировать.
  2. pollingInterval: Определяет частоту проверки состояния очереди.
  3. cooldownPeriod: Задает время ожидания перед уменьшением количества подов, чтобы избежать частого переключения.
  4. minReplicaCount и maxReplicaCount: Указывают минимальное и максимальное количество подов.
  5. triggers:
    • Тип триггера (rabbitmq).
    • Название очереди, длину которой нужно мониторить.
    • Переменная окружения (hostFromEnv), которая содержит адрес RabbitMQ.
    • Порог длины очереди (queueLength), превышение которого запускает скейлинг.

Подключение аутентификации

Для связи KEDA с RabbitMQ используется TriggerAuthentication:

apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: rabbitmq-trigger-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

Создаем secret для подключения KEDA к Rabbitmq

apiVersion: v1
kind: Secret
metadata:
  name: rabbitmq-secret
  namespace: default
type: Opaque
data:
  host: cmtvcmJiaXQxLmNvbQ==  # base64-encoded "rabbit1.com" замените на адрес вашего кролика
  username: YWRtaW4=          # base64-encoded "admin" замените на юзернейм
  password: cGFzc3dvcmQ=      # base64-encoded "password"замените на пароль

Частые ошибки и их решение

1. Ошибка: «NOT_FOUND — no queue ‘celery’ in vhost ‘/'»

Причина: Некорректно указан vhost RabbitMQ. По умолчанию используется "/". Решение: Укажите корректный vhost в триггере:

metadata:
  queueName: "celery"
  hostFromEnv: RABBITMQ_HOST
  vhost: "my_vhost"

2. Ошибка подключения к RabbitMQ

Причина: Неверные параметры аутентификации. Решение: Проверьте секрет, используемый в TriggerAuthentication.

3. Поды не уменьшаются при разгрузке очереди

Причина: Неверно задан cooldownPeriod или minReplicaCount. Решение: Убедитесь, что эти параметры соответствуют требованиям, и длина очереди действительно меньше порога.

Оставьте первый комментарий

Отправить ответ

Ваш e-mail не будет опубликован.


*