Реализовать canary deployment агента с автооткатом

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Реализовать canary deployment агента с автооткатом

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

Научиться безопасно разворачивать новые версии LLM-агента (RAG, чат-бот и т.п.) на production-подобном окружении, используя canary deployment с прогрессивным увеличением трафика 1% → 5% → 10% → 100%. Реализовать автоматический откат (auto‑rollback) при обнаружении деградации ключевых метрик качества ответов и производительности. Отработать взаимодействие с трафик-менеджментом (Istio/Enovy), мониторингом и автоматизацией.

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

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

Что нужноОткуда взять
Работающий LLM-агент (например, RAG)Собственный пет-проект / готовый образ Docker с версией v1 (стабильная)
Новая версия агента (v2) с заведомо ухудшенным качеством (для теста отката)Модифицировать v1 – например, снизить temperature или отключить filtering
Kubernetes кластер (minikube / kind / реальный)Локально: minikube, kind, k3s; облако: GKE / EKS / AKS
Service Mesh (Istio)Установка через istioctl / Helm (версия ≥1.18)
Мониторинг: Prometheus + GrafanaУстановка через kube-prometheus-stack Helm chart
Инструмент оценки качества ответовПример: RAGAS (для RAG) или LLM-as-Judge (для чатов) через Python
Язык программирования Python + библиотекиrequests, kubernetes, prometheus-api-client, istio-api (k8s custom resources)

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

  1. Разверните два образа агента: my-agent:v1 (стабильный, baselines) и my-agent:v2 (с заведомо ухудшенным качеством: заменить эмбеддинг‑модель на примитивную, снизить top‑k, увеличить вероятность ошибок).
  2. Создайте симулятор трафика (Python‑скрипт с aiohttp или locust), который шлёт запросы к агенту и фиксирует ответы.
  3. Определите метрику качества (например, relevance score от LLM-as-Judge). Реализуйте простого «судью» через OpenAI API (gpt-4o-mini), который ставит оценку 1–5.

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

КомпонентИнструментыНазначение
КонтейнеризацияDocker, Docker Compose (для разработки)Упаковка агента и сервисов
ОркестрацияKubernetes (minikube / kind)Развёртывание агента, canary, откат
Service MeshIstio (VirtualService, DestinationRule, Gateway)Распределение трафика между версиями
МониторингPrometheus + Grafana + kube-state-metricsСбор и визуализация метрик деградации
Качество ответовPython-скрипт (LLM-as-Judge) + Prometheus Pushgateway или direct metrics endpointВычисление score качества и экспорт в Prometheus
Управление canaryCustom Controller / Python-скрипт с вызовом k8s API и Istio APIИзменение весов трафика, проверка метрик, автооткат
Нагрузочное тестированиеLocust / простой Python threadingСимуляция пользовательского трафика

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

Этап 1: Подготовка окружения и сбор базовых метрик (2–3 часа)

Действия

  1. Разверните Kubernetes кластер (minikube с драйвером docker, запуск с minikube start --cpus=4 --memory=8g).
  2. Установите Istio через istioctl install --set profile=demo -y. Включите sidecar injection для namespace canary:
    kubectl create namespace canary
    kubectl label namespace canary istio-injection=enabled
    
  3. Разверните стабильную версию агента (v1):
    • Создайте Deployment agent-v1 (образ my-agent:v1) с меткой version: v1.
    • Создайте Service agent-svc (ClusterIP, порт 80 → 8080).
    • Создайте Gateway и VirtualService для доступа через Ingress Gateway.
  4. Установите Prometheus + Grafana через Helm (kube-prometheus-stack). Убедитесь, что метрики из агента (latency, error rate) поступают.
  5. Реализуйте метрику качества:
    • Напишите Python-скрипт quality_metric.py, который опрашивает логи агента или получает ответы и с помощью LLM-as-Judge вычисляет средний quality_score (0–1). Экспортируйте в Prometheus через Pushgateway или встроенный эндпоинт агента.
    • Запустите скрипт как sidecar-контейнер в подах агента.
  6. Соберите baseline:
    • Запустите симулятор трафика (1000 запросов к агенту v1). Зафиксируйте quality_score, p95 latency, error rate.
    • Сохраните эти значения как пороги для автоотката.

Ожидаемый результат этапа Рабочий кластер с агентом v1, Istio, мониторинг и baseline метрики.

Этап 2: Реализация canary-стратегии с распределением трафика (1–2 часа)

Действия

  1. Создайте DestinationRule для разделения трафика между версиями:
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: agent
    spec:
      host: agent-svc
      subsets:
      - name: stable
        labels:
          version: v1
      - name: canary
        labels:
          version: v2
    
  2. Создайте VirtualService с начальным весом 100% на v1, v2 = 0%:
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: agent
    spec:
      hosts:
      - agent-svc
      http:
      - route:
        - destination:
            host: agent-svc
            subset: stable
          weight: 100
        - destination:
            host: agent-svc
            subset: canary
          weight: 0
    
  3. Разверните canary-версию (v2):
    • Deployment agent-v2 с образом my-agent:v2 и меткой version: v2. Убедитесь, что он подхватывается DestinationRule.
  4. Постепенно увеличивайте вес canary (ручная проверка):
    • Измените VirtualService: weight v2 = 1% (остальное v1). Проверьте через istioctl proxy-status.
    • Проконтролируйте, что трафик распределяется корректно (через логи агентов или дашборд Grafana).

Ожидаемый результат этапа Трафик 1% идёт на canary v2, 99% — на stable v1.

Этап 3: Определение метрик и порогов для auto-rollback (1 час)

Действия

  1. Определите метрики деградации:
    • error_rate_canary: доля ошибок (HTTP 5xx) от всех запросов к canary за последние 5 минут.
    • p95_latency_canary: задержка ответов (ms) p95.
    • avg_quality_score_canary: средняя оценка качества ответов (0–1) за последние 5 минут.
  2. Установите пороги отката (на основе baseline v1):
    • error_rate_canary > 5% (или увеличение в 2 раза от baseline).
    • p95_latency_canary > 150% от baseline p95.
    • avg_quality_score_canary < 0.8 (или падение на 10% от baseline).
  3. Создайте Prometheus Recording Rules (опционально) для удобства запросов:
    groups:
    - name: canary.rules
      rules:
      - record: canary:error_rate:5m
        expr: sum(rate(http_requests_total{version="v2",status=~"5.."}[5m])) / sum(rate(http_requests_total{version="v2"}[5m]))
    
  4. Реализуйте Python-скрипт проверки метрик:
    • Используйте prometheus-api-client для запроса метрик за последние 5 минут.
    • Сравните с порогами.

Ожидаемый результат этапа Чётко определённые метрики, пороги и скрипт проверки.

Этап 4: Разработка auto-rollback (2–3 часа)

Действия

  1. Напишите Python-скрипт canary_controller.py, который:
    • Циклически (каждые 60 секунд) проверяет метрики canary-версии через Prometheus API.
    • Если любая из метрик выходит за порог — выполняет откат:
      1. Выставляет вес canary = 0% через обновление VirtualService.
      2. Масштабирует deployment canary до 0 реплик (опционально).
      3. Отправляет уведомление в Slack / Telegram (через webhook).
    • Если метрики в норме — увеличивает вес canary на следующую ступень: 1% → 5% → 10% → 100% (шаги по таймеру или после стабильной проверки).
  2. Используйте Kubernetes API (через kubernetes Python client) для обновления VirtualService.
    from kubernetes import client, config
    from kubernetes.client.rest import ApiException
    import yaml
    import requests
    
    config.load_kube_config()
    api = client.CustomObjectsApi()
    # Получить текущий VirtualService
    vs = api.get_namespaced_custom_object(
        group="networking.istio.io",
        version="v1beta1",
        namespace="canary",
        plural="virtualservices",
        name="agent"
    )
    # Изменить weight
    vs['spec']['http'][0]['route'] = [
        {'destination': {'host': 'agent-svc', 'subset': 'stable'}, 'weight': 100},
        {'destination': {'host': 'agent-svc', 'subset': 'canary'}, 'weight': 0}
    ]
    api.replace_namespaced_custom_object(...)
    
  3. Реализуйте логику градации (state machine):
    STEPS = [1, 5, 10, 100]
    current_step = 0
    # После успешной проверки в течение N циклов переходим к следующему шагу
    
  4. Добавьте sidecar-контейнер с quality_metric (если не сделано ранее) в оба deployment для автоматического поступления метрик.

Ожидаемый результат этапа Auto-rollback скрипт, способный откатывать canary при деградации.

Этап 5: Тестирование canary и отката (2 часа)

Действия

  1. Убедитесь, что canary-версия v2 действительно хуже v1 (например, замените RAG-ретривер на выдающий нерелевантные документы). Проверьте вручную, что quality_score падает.
  2. Запустите canary_controller.py в отдельном процессе (или в Kubernetes Job).
  3. Запустите симулятор трафика (Locust или скрипт), генерирующий запросы с равномерным распределением между версиями (через Ingress Gateway).
  4. Наблюдайте за метриками в Grafana.
    • При весе canary = 1%, метрики v2 должны быть плохими.
    • После проверки скрипт должен зафиксировать деградацию и откатить: выставить вес canary = 0%.
  5. Проверьте, что stable-версия не пострадала (100% трафика возвращается к v1).
  6. Повторите сценарий с «хорошей» canary (v2 такая же, как v1) – убедитесь, что автооткат не срабатывает и вес постепенно доходит до 100%.

Ожидаемый результат этапа Демонстрация успешного отката при деградации и успешного деплоя при нормальных метриках.

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

  • Canary-версия (v2) развёрнута в Kubernetes без влияния на stable (v1).
  • Трафик распределяется через Istio: 1% → 5% → 10% → 100% (контролируется скриптом).
  • Метрики качества ответов (quality_score), ошибок (error_rate) и задержек (latency) собираются в Prometheus.
  • Auto-rollback скрипт срабатывает, когда хотя бы одна метрика canary превышает порог, и немедленно обнуляет вес canary.
  • После отката 100% трафика идёт на stable-версию (v1).
  • Логика отката корректно восстанавливает VirtualService (вес 100/0) и может быть запущена повторно.
  • При «хорошей» canary вес постепенно достигает 100% без отката.
  • Вся конфигурация и скрипты хранятся в Git-репозитории.

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

Основной артефакт GitHub-репозиторий (или папка) содержащий:

  • agent-v1/Dockerfile и код стабильной версии агента.
  • agent-v2/Dockerfile и код ухудшенной версии (для тестов).
  • canary-controller/ — Python-скрипт controller.py с автооткатом.
  • k8s/ — манифесты: Deployment, Service, DestinationRule, VirtualService, Gateway.
  • monitoring/ — конфигурация Prometheus (recording rules, scrape configs) и дашборд Grafana (JSON export).
  • load-test/ — скрипт симулятора трафика (Locust или Python).
  • README.md — инструкция по развёртыванию, запуску и тестированию.

Дополнительно Запись экрана или лог консоли, демонстрирующий:

  1. Развёртывание.
  2. Постепенное увеличение веса canary.
  3. Срабатывание auto-rollback при деградации.
  4. Восстановление стабильной версии.

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

СложностьРешение
Istio не распределяет трафик корректноПроверьте label version на подах, убедитесь, что sidecar injection включён. Используйте istioctl analyze.
Prometheus не видит метрики кастомного quality_scoreИспользуйте Pushgateway или добавьте в агент экспорт метрик через /metrics на 8080. Настройте scrape_config.
Auto-rollback скрипт не успевает откатить до массового паденияУстановите интервал проверки 30 секунд и пороги с запасом. Можно также добавить alert на срабатывание ручного отката.
Конфликт при одновременной правке VirtualService из нескольких источниковИспользуйте оптимистичную блокировку через resourceVersion; запускайте только один экземпляр controller’а.
Симулятор трафика не достигает canary из-за маршрутизацииУбедитесь, что симулятор шлёт запросы через Istio Ingress Gateway, а не напрямую к Service.

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

ЭтапВремя
1. Подготовка окружения и сбор baseline3 часа
2. Реализация canary через Istio1.5 часа
3. Определение метрик и порогов1 час
4. Разработка auto-rollback3 часа
5. Тестирование сценариев2.5 часа
Итого11 часов

Примечание: Для первого раза заложите +2–3 часа на отладку Istio и мониторинга.

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

ВопросТема
14Как настроить canary deployment в Kubernetes через Istio?
42Метрики для мониторинга LLM-систем
58Реализация A/B тестирования для ML моделей
73Auto‑rollback при ухудшении метрик ML
118Инструменты оценки качества ответов LLM (LLM-as-Judge)
201Kubernetes Custom Resources и Python клиент
245Мониторинг задержек через Prometheus Histogram
308Prometheus Pushgateway — когда и как использовать
375Graceful shutdown подов в Istio
412Нагрузочное тестирование ML-сервисов с Locust

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

  • Я развернул кластер minikube с Istio и Prometheus/Grafana.
  • Я создал два образа агента (стабильный и ухудшенный) и запустил их как Deployment.
  • Я настроил Istio VirtualService с весами 100/0.
  • Я написал скрипт, который увеличивает вес canary по шагам и проверяет метрики.
  • Я удостоверился, что при запуске «плохой» canary скрипт откатывает её вес до 0.
  • Я зафиксировал результаты и сохранил все конфигурации в Git.