Когда развёртывание решает само: автоматизация отката и продвижения

Вы только что выкатили новую версию API. Через пять минут уровень ошибок подскакивает с 0,1% до 4%. Вы на совещании. К тому моменту, как вы открываете дашборд, проходит пятнадцать минут. Пользователи уже жалуются.

А теперь представьте, что это происходит три раза в неделю. Каждый раз кому-то нужно заметить всплеск, открыть систему мониторинга, интерпретировать цифры, принять решение и вручную запустить откат или остановку. Для команды, которая делает несколько развёртываний в день, такой ручной цикл принятия решений становится изнурительным. Хуже того, он непоследователен. Один инженер может откатить при уровне ошибок 2%. Другой подождёт до 5%. Третий может вообще не заметить, пока кто-то не напишет ему в чат.

Именно эту проблему решают гейты развёртывания (deployment gates). Гейт развёртывания — это автоматизированная контрольная точка, которая решает, может ли новая версия перейти на следующий этап или её нужно остановить. Гейт не гадает. Он следует политике: набору правил, которые гласят: «Если этот сигнал пересекает такой-то порог, сделай такое-то действие».

Как работает гейт развёртывания

Представьте себе гейт как вышибалу на входе в клуб. Вышибала не знает, кто вы. Он просто проверяет: вы в списке? Ваше удостоверение действительно? Если да — проходите. Если нет — ждёте или уходите.

Гейт развёртывания работает так же. После того как новая версия развёрнута на подмножестве пользователей или в staging-окружении, гейт проверяет сигналы observability. Если сигналы в норме, гейт продвигает версию на большее количество пользователей. Если сигналы плохие, гейт запускает откат, удержание или паузу.

На диаграмме ниже показаны три возможных исхода после проверки сигналов observability гейтом.

flowchart TD A[Развернуть новую версию на подмножестве] --> B[Проверить сигналы observability] B --> C{Сигналы в норме?} C -->|Да| D[Продвинуть на больше пользователей] C -->|Нет| E{Серьёзность?} E -->|Незначительная| F[Удержать - оставить живую, остановить продвижение] E -->|Критическая| G[Откатить к предыдущей версии] E -->|Неопределённая| H[Пауза - оставить живую, ручная проверка]

Ключевой момент: решение принимается автоматически на основе правил, которые команда согласовала заранее. Никому не нужно смотреть на дашборд в 2 часа ночи. Никому не нужно принимать решение под давлением. Система следует политике.

Из чего состоит политика

Политика — это не одно правило. Это набор условий, привязанных к типу того, что вы развёртываете. У разных объектов развёртывания разные паттерны отказов, поэтому им нужны разные политики.

Для приложения политика может проверять:

  • Уровень ошибок по сравнению с базовым SLO
  • Задержку на перцентиле p95 или p99
  • Падение пропускной способности, которое указывает на то, что сервис отклоняет запросы

Для миграции базы данных политика может проверять:

  • Задержку репликации между primary и репликами
  • Количество медленных запросов после миграции
  • Истощение пула соединений

Для изменений инфраструктуры политика может проверять:

  • Состояние узлов в кластере
  • Паттерны использования CPU и памяти
  • Количество перезапусков подов

Каждый объект получает свою политику, потому что каждый ломается по-своему. Всплеск задержки в API — это не то же самое, что задержка репликации в базе данных. Политика должна соответствовать типу отказа.

Вот минимальный пример политики как кода, реализующий описанную выше логику:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: api-deployment
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  service:
    port: 8080
  analysis:
    interval: 1m
    threshold: 5
    maxWeight: 50
    stepWeight: 10
    metrics:
    - name: error-rate
      thresholdRange:
        max: 0.05
      interval: 2m
    - name: request-duration
      thresholdRange:
        max: 0.5
      interval: 2m
    webhooks:
    - name: rollback-on-failure
      timeout: 30s
      metadata:
        action: rollback

Эта политика проверяет уровень ошибок и задержку каждые две минуты. Если какой-либо из показателей превышает порог, развёртывание автоматически откатывается. Если все проверки проходят в течение пяти минут, новая версия продвигается на следующий шаг по весу.

Использование error budget как основы политики

Error budget даёт вам практическое число, которое можно подставить в политику. Если ваша команда установила SLO доступности 99,9%, у вас есть около 43 минут допустимого простоя в месяц. Это ваш error budget.

Теперь представьте, что новое развёртывание сжигает 10 минут этого бюджета за первый час. Это сильный сигнал, что что-то не так. Политика может гласить: «Если новая версия потребляет более 5% месячного error budget за первые 30 минут, автоматически откатить».

Такой подход устраняет догадки. Команда согласовала SLO. Политика его обеспечивает. Никому не нужно спорить, много это — 10 минут или нет. Число уже установлено.

Не все решения должны заканчиваться откатом

Распространённая ошибка — делать каждую политику с откатом в конце. Это слишком агрессивно для многих ситуаций. Лучше использовать многоуровневые политики.

Пример:

  • Если уровень ошибок вырос на 0,5%, но остаётся ниже порога SLO, запустить удержание. Новая версия остаётся в работе, но не продвигается на большее количество пользователей. Команда расследует без давления.
  • Если уровень ошибок превышает порог SLO, запустить откат. Система немедленно возвращается к предыдущей версии.
  • Если задержка увеличилась, но уровень ошибок стабилен, запустить паузу. Дальнейшее продвижение не происходит, но текущая версия продолжает работать. Команда вручную решает, продолжать или откатывать.

Такой многоуровневый подход даёт команде пространство для обработки разных уровней серьёзности без излишней реакции или недостаточной реакции.

Что нужно, чтобы это заработало

Гейтинг развёртывания требует интеграции между вашей системой observability и платформой развёртывания. Сигналы из мониторинга должны быть читаемы пайплайном или платформой, которая управляет развёртываниями.

Такие инструменты, как Argo Rollouts, Flagger и Spinnaker, уже поддерживают этот паттерн. Они могут получать метрики из Prometheus, Datadog, New Relic или любого другого источника метрик. Вы настраиваете политику, а инструмент выполняет решение.

Но инструмент — это не самая сложная часть. Самая сложная часть — определение политики. Вам нужно знать:

  • Какие сигналы важны для каждого типа развёртывания
  • Какие пороги указывают на реальную проблему, а какие — на шум
  • Как быстро нужно реагировать при разной серьёзности отказа

Начните с простого. Выберите один сигнал, один порог и одно действие. Запустите на неделю. Посмотрите, сколько ложных срабатываний вы получите. Откорректируйте. Постепенно добавляйте больше сигналов.

Безопасно ли доверять системе принятие решений?

Этот вопрос возникает каждый раз. Ответ: зависит от того, насколько хорошо вы определили политику.

Хорошая политика не заменяет человеческое суждение полностью. Она берёт на себя решения, которые уже предсказуемы. Если команда знает, что уровень ошибок выше 2% в течение пяти минут всегда приводит к откату, зачем ждать, пока это сделает человек? Автоматизируйте это решение.

А как насчёт крайних случаев? У команды всегда должен быть механизм переопределения. Если политика сработала некорректно, кто-то должен иметь возможность остановить откат или выполнить продвижение вручную. Автоматизация обрабатывает рутинные случаи. Люди обрабатывают исключения.

Цель — не убрать человека из цикла. Цель — убрать человека из скучных, повторяющихся, предсказуемых решений, чтобы он мог сосредоточиться на тех, которые действительно требуют контекста и суждения.

Краткий чек-лист для начала

Прежде чем строить свой первый гейт развёртывания, убедитесь, что у вас есть:

  • Один сигнал observability, которому вы доверяете (начните с уровня ошибок или задержки)
  • Чёткий порог на основе вашего SLO или error budget
  • Платформа развёртывания, поддерживающая гейтинг (Argo Rollouts, Flagger, Spinnaker или аналоги)
  • Механизм переопределения для ручного вмешательства
  • Регулярный пересмотр политики каждые две недели для проверки эффективности

Не пытайтесь построить идеальную политику в первый же день. Начните с одного гейта, одного сигнала, одного действия. Учитесь на результатах. Расширяйтесь оттуда.

Реальная ценность — в последовательности

Самое большое преимущество автоматизированных решений о развёртывании — не скорость, хотя она тоже помогает. Это последовательность. Каждое развёртывание проходит через один и тот же гейт, оценивается по одним и тем же стандартам, с одной и той же логикой принятия решений. Никто не получает поблажек, потому что дружит с дежурным инженером. Никого не откатывают несправедливо, потому что у проверяющего было плохое настроение.

Когда ваши решения о развёртывании автоматизированы с помощью политики, ваша команда может развёртывать чаще без выгорания. Система обрабатывает рутинные оценочные суждения. Ваша команда обрабатывает исключения и улучшения. В этом разница между командой, которая развёртывает часто, и командой, которая развёртывает устойчиво.