English translation is not available yet. Showing Russian content.

Реализовать canary analysis с авто-роллбэком для AI-сервиса

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Реализовать canary analysis с авто-роллбэком для AI-сервиса

1. Цель задачи

Получить практический навык настройки канареечного (canary) развёртывания для инференс-сервиса на основе LLM или другого AI-модуля. Необходимо организовать маршрутизацию 5% трафика на новую версию сервиса, настроить мониторинг ключевых метрик (latency, error rate, throughput) в течение 24 часов и реализовать автоматический откат (rollback) при превышении пороговых значений.

Ключевой результат Рабочая конфигурация canary‑деплоя, которая автоматически откатывает новую версию при ухудшении качества обслуживания.

2. Исходные данные

Что нужноОткуда взять
Docker-образ текущей стабильной версии AI-сервисаСобственная сборка или образ из публичного реестра (например, your-registry/llm-server:stable)
Docker-образ новой (canary) версии AI-сервисаСборка с изменением модели или конфигурации (например, your-registry/llm-server:canary)
Инструмент для взвешенной маршрутизации трафикаNginx (reverse proxy) / Traefik / Istio (в данном ТЗ – Nginx)
Система мониторинга и алертингаPrometheus + Alertmanager + Grafana
Тестовый генератор запросовlocust, hey, wrk или простой Python-скрипт
CI/CD (опционально)GitLab CI / GitHub Actions / Jenkins

Если нет реального инструмента — симулируем:

  1. Создать два Docker-образа (stable и canary) с минимальным Flask/FastAPI приложением, которое имитирует инференс (например, случайная задержка + ответ).
  2. Настроить Nginx в Docker‑compose как ingress controller с балансировкой по весу (weight=95 для stable, weight=5 для canary).
  3. Эмулировать нагрузку с помощью hey или locust, отправляющего ~100 rps.
  4. Искусственно внести ошибку в canary (например, добавить random.choices([time.sleep(0.1), 1/0], weights=[0.9, 0.1])), чтобы проверить авто‑роллбэк.

3. Технологический стек

КомпонентИнструментыНазначение
AI-сервис (стабильный и canary)Python, Flask/FastAPI, DockerВыдача ответов на запросы
Маршрутизация трафикаNginxupstream и weights), Docker‑composeНаправление 5% трафика на canary
Мониторинг метрик (latency, errors, throughput)Prometheus (node_exporter + custom metrics) + GrafanaСбор и визуализация
Алертинг и авто‑роллбэкAlertmanager + bash-скрипт (или Python)Автоматический откат при превышении порога ошибок
Генератор нагрузкиhey / locust / abЭмуляция пользовательского трафика
ОркестрацияDocker Compose (опционально Kubernetes)Запуск всех компонентов

4. Этапы выполнения

Этап 1: Настройка окружения и базового сервиса (2 часа)

Действия

  1. Создать репозиторий проекта с файловой структурой:

    canary-demo/
    ├── stable/
    │   ├── app.py
    │   └── Dockerfile
    ├── canary/
    │   ├── app.py
    │   └── Dockerfile
    ├── nginx/
    │   └── nginx.conf
    ├── monitoring/
    │   ├── prometheus.yml
    │   └── alertmanager.yml
    ├── rollback.sh
    ├── docker-compose.yml
    └── README.md
    
  2. Написать stable/app.py – минимальное FastAPI приложение с одним endpoint /predict:

    from fastapi import FastAPI
    import uvicorn
    import time, random
    
    app = FastAPI()
    
    @app.post("/predict")
    async def predict(data: dict):
        # имитация предсказания
        time.sleep(0.05 + random.uniform(0, 0.02))
        return {"result": "stable", "latency_ms": 50}
    
    if __name__ == "__main__":
        uvicorn.run(app, host="0.0.0.0", port=8000)
    
  3. Создать canary/app.py – копия stable, но с искусственным дефектом:

    @app.post("/predict")
    async def predict(data: dict):
        if random.random() < 0.1:  # 10% ошибок
            raise HTTPException(status_code=500, detail="Internal Error")
        time.sleep(0.05 + random.uniform(0, 0.1))  # большая задержка
        return {"result": "canary", "latency_ms": 50}
    
  4. Написать Dockerfile для каждого сервиса (на базе python:3.11-slim).

  5. Настроить nginx.conf

    upstream ai_backend {
        server stable:8000 weight=95;
        server canary:8000 weight=5;
    }
    server {
        listen 80;
        location /predict {
            proxy_pass http://ai_backend;
            proxy_set_header Host $host;
        }
    }
    
  6. Создать docker-compose.yml с сервисами: stable, canary, nginx, prometheus, alertmanager, grafana.

Ожидаемый результат этапа Запущенные контейнеры, Nginx раздаёт трафик: 95% на stable, 5% на canary. При curl-запросах видно распределение.

Этап 2: Настройка мониторинга и метрик (1,5 часа)

Действия

  1. Добавить экспорт метрик в приложения с помощью prometheus_client:

    • REQUESTS_TOTAL (counter) с метками version=stable|canary, status=200|500
    • LATENCY_MS (histogram)
    • Пример:
      from prometheus_client import Counter, Histogram, generate_latest
      requests_total = Counter('requests_total', 'Total requests', ['version', 'status'])
      latency_hist = Histogram('latency_ms', 'Request latency ms', ['version'], buckets=(10, 50, 100, 200, 500))
      app.add_route("/metrics", lambda: Response(generate_latest(), media_type="text/plain"))
      
  2. Создать prometheus.yml для сбора метрик со всех таргетов (stable, canary, nginx).

  3. Создать alertmanager.yml с правилом:

    groups:
      - name: canary_alerts
        rules:
          - alert: CanaryErrorRateHigh
            expr: (rate(requests_total{version="canary",status="500"}[5m]) / rate(requests_total{version="canary"}[5m])) > 0.05
            for: 2m
            labels:
              severity: critical
            annotations:
              summary: "Canary error rate over 5%"
    
  4. Настроить webhook receiver (или использовать alertmanager для вызова скрипта через webhook). Упрощённо: в alertmanager.yml добавить receiver с URL, который триггерит rollback.sh.

Ожидаемый результат этапа Prometheus собирает метрики, в Grafana построен дашборд (latency, error rate, RPS), Alertmanager может отправить оповещение.

Этап 3: Реализация авто‑роллбэка (1 час)

Действия

  1. Создать rollback.sh – скрипт, который:

    • Меняет вес canary с 5 на 0 в конфиге Nginx (команда sed),
    • Отправляет сигнал reload Nginx (nginx -s reload),
    • Останавливает контейнер canary (docker-compose stop canary),
    • Пишет событие в лог.
  2. Организовать вызов скрипта через Alertmanager:

    • В alertmanager.yml определить webhook_config:
      receivers:
        - name: rollback_webhook
          webhook_configs:
            - url: "http://rollback-trigger:5000/rollback"
      
    • Запустить микросервис rollback-trigger (Flask), который принимает POST и выполняет subprocess.run(['/rollback.sh']).
  3. Проверить, что авто‑роллбэк работает – искусственно поднять error rate выше порога и убедиться, что canary отключается.

Ожидаемый результат этапа При превышении 5% ошибок (за 2 минуты) система автоматически убирает canary и возвращает 100% трафика на stable.

Этап 4: Тестирование канареечного анализа в течение 24 часов (симуляция) (1,5 часа)

Действия

  1. Запустить генератор нагрузки на 24 часа (на деле для учебной задачи достаточно 1–2 часов):

    hey -z 2h -c 10 -m POST -d '{"text":"hello"}' http://localhost/predict
    
  2. Убедиться, что canary получает ровно ~5% трафика – проверить в Grafana соотношение requests_total{version="canary"} к общему числу.

  3. Через полчаса внести ошибку (если не была внесена изначально) – например, отредактировать код canary на лету через docker cp или поднять error rate до 20%.

  4. Наблюдать за срабатыванием алерта и авто‑роллбэком – проверить, что трафик на canary упал до 0.

  5. Собрать логи и дашборды для отчёта.

Ожидаемый результат этапа Получены графики распределения трафика и метрик, проверен сценарий успешного отката.

Этап 5: Документирование (0,5 часа)

Действия

  1. Написать README с описанием архитектуры, инструкцией по развёртыванию, параметрами порогов, примером алерта и процедурой восстановления.
  2. Сохранить скриншоты Grafana (latency, error rate, request volume).
  3. Задокументировать условия авто‑роллбэка и команды для ручного отката.

Ожидаемый результат этапа Полный набор артефактов: код, конфиги, скрипты, документация.


5. Критерии приемки (Definition of Done)

  • Развёрнута docker-compose система из 4+ контейнеров (stable, canary, nginx, prometheus, grafana, alertmanager).
  • Nginx корректно разделяет трафик: 95% на stable, 5% на canary (подтверждено метриками за 10 минут).
  • Prometheus собирает custom-метрики (requests_total, latency_ms) с лейблами version и status.
  • Alertmanager настроен на оповещение при превышении error rate canary >5% в течение 2 минут.
  • Автоматический роллбэк реализован: при срабатывании алерта canary отключается (weight=0, контейнер stop).
  • Лог событий авто‑роллбэка записывается в файл или stdout.
  • Написан README с исчерпывающей инструкцией по запуску и тестированию.
  • В Grafana создан дашборд с панелями: общий RPS, error rate по версиям, p95 latency.

6. Ожидаемый результат

Основные артефакты (как файлы в репозитории):

  • docker-compose.yml – полная оркестровка.
  • stable/app.py, canary/app.py – исходный код AI-сервисов.
  • nginx/nginx.conf – конфигурация с весами.
  • monitoring/prometheus.yml, monitoring/alertmanager.yml – конфиги мониторинга.
  • rollback.sh – скрипт автоматического отката.
  • README.md – документация.

Дополнительно: скриншоты Grafana-дашборда и логи отработки роллбэка.


7. Возможные сложности и их решение

СложностьРешение
Alertmanager не вызывает webhookПроверить network (docker-compose network) и правильность URL. Использовать curl внутри контейнера для отладки.
Nginx reload не отрабатывает внутри контейнераНазначить скрипту права на выполнение docker exec nginx nginx -s reload или использовать docker kill -s HUP nginx.
Метрики не появляются в PrometheusПроверить targets в Prometheus UI, правильность портов и путь /metrics.
Авто‑роллбэк срабатывает слишком поздноУменьшить for в алерте, увеличить частоты scrape (scrape_interval: 5s).
Трафик не распределяется 95/5 из‑за keepalive или клиентского кэшированияВ nginx отключить keepalive для upstream (или настроить proxy_http_version 1.1).

8. Бюджет времени (оценка)

ЭтапВремя
Этап 1: Настройка окружения2 ч
Этап 2: Мониторинг и метрики1,5 ч
Этап 3: Авто‑роллбэк1 ч
Этап 4: Тестирование (симуляция 24 ч)1,5 ч
Этап 5: Документирование0,5 ч
Итого6,5 ч

Примечание: для первого выполнения (без готовых шаблонов) заложите 8–10 часов.


9. Связанные вопросы из базы знаний

№ вопросаТема
45Стратегии деплоя (blue‑green, canary, rolling)
112Настройка Prometheus для инференс‑сервисов
138Auto‑rollback и health checks в CI/CD
209Мониторинг latency и error rate LLM-сервисов
315Docker Compose для ML‑пайплайнов
402Nginx как reverse‑proxy с взвешенным upstream
507Alertmanager: конфигурация webhook
618A/B тестирование моделей в production
734Нагрузочное тестирование AI-сервисов (locust, hey)
819Интеграция Grafana с Prometheus

10. Чек-лист самопроверки

  • Я подготовил Docker-образы для stable и canary и убедился, что они запускаются отдельно.
  • Nginx настроен с весами 95/5, и я проверил распределение через несколько curl-запросов.
  • Prometheus успешно собирает метрики с обоих сервисов; в Grafana есть дашборд с latency и error rate.
  • Alertmanager срабатывает при превышении 5% ошибок на canary (я проверил, искусственно увеличив error rate).
  • После срабатывания алерта скрипт rollback.sh выполнился, canary получил вес 0 и контейнер остановлен.
  • Я задокументировал все шаги в README и приложил скриншоты Grafana.