От коммита до полного развёртывания: создание пайплайна прогрессивной доставки

Вы сливаете код в основную ветку. CI-пайплайн зелёный. Артефакт готов. Что дальше?

В большинстве команд следующий шаг прост: развернуть в production. Но если вы хоть раз видели, как развёртывание идёт не по плану — баг, проявляющийся только под реальной нагрузкой, незаметно подкрадывающаяся деградация производительности, функция, сбивающая пользователей с толку — вы знаете, что «развернуть сразу всем» — это риск, на который необязательно идти.

Прогрессивная доставка меняет это. Вместо одного большого переключения вы раскатываете изменения постепенно, используя маршрутизацию трафика, feature flags и автоматизированный мониторинг, чтобы на каждом шаге решать: продолжать или откатываться. Эта статья показывает, как собрать полноценный пайплайн прогрессивной доставки — от момента слияния кода до полного стабильного запуска функции.

Следующая диаграмма показывает этапы пайплайна в общем виде:

flowchart TD A[Commit / Merge] --> B[Build & Tests] B --> C[Canary Ring<br>1% traffic] C --> D{Monitor Metrics} D -- Pass --> E[Staged Rollout<br>10% → 25% → 50%] D -- Fail --> F[Auto Rollback] E --> G{Monitor & Gate} G -- Pass --> H[Full Rollout<br>100%] G -- Fail --> F H --> I[Flag Cleanup] F --> J[Notify Team]

Сборка и базовые тесты

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

Если всё проходит успешно, пайплайн создаёт развёртываемый артефакт. Здесь прогрессивная доставка начинает отличаться от стандартного пайплайна. Артефакт не отправляется сразу всем пользователям. Он попадает в первое кольцо развёртывания, обычно называемое canary-кольцом.

Canary-кольцо: ваш первый реальный тест

Canary-кольцо получает небольшую долю трафика — скажем, один процент всех запросов. Пайплайн развёртывает новую версию на серверах, обслуживающих это кольцо. Затем он активирует соответствующие feature flags для пользователей, попавших в это кольцо.

Вот пример GitLab CI, определяющий canary-кольцо и этапы поэтапного развёртывания:

stages:
  - canary
  - staged-rollout
  - full-rollout

canary-deploy:
  stage: canary
  script:
    - kubectl set image deployment/my-app canary=my-app:$CI_COMMIT_SHA
    - kubectl scale deployment/my-app --replicas=1
  environment:
    name: production/canary
    url: https://canary.example.com
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

auto-promote:
  stage: staged-rollout
  script:
    - sleep 600  # 10-минутное окно мониторинга
    - ./check-metrics.sh  # проверка частоты ошибок, задержки в рамках SLO
    - kubectl set image deployment/my-app-10pct my-app=my-app:$CI_COMMIT_SHA
    - kubectl scale deployment/my-app-10pct --replicas=2
  needs: ["canary-deploy"]
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

rollout-50pct:
  stage: staged-rollout
  script:
    - ./check-metrics.sh
    - kubectl set image deployment/my-app-50pct my-app=my-app:$CI_COMMIT_SHA
  needs: ["auto-promote"]
  when: manual  # требуется ручное подтверждение

rollout-100pct:
  stage: full-rollout
  script:
    - ./check-metrics.sh
    - kubectl set image deployment/my-app my-app=$CI_COMMIT_SHA
  needs: ["rollout-50pct"]
  when: manual

Feature flags добавляют дополнительный уровень контроля. Даже если новая версия уже запущена, конкретные функции можно включить только для определённых пользователей внутри canary-кольца. Это позволяет тестировать не только стабильность новой версии, но и поведение конкретной функции на реальных пользователях, не раскрывая её всем.

Пока новая версия работает в canary-кольце, включается observability. Пайплайн отслеживает частоту ошибок, задержку и другие метрики, определённые в ваших Service Level Objectives (SLO). Если все метрики остаются в допустимых пределах в течение заданного периода — скажем, десяти минут — пайплайн автоматически переходит к следующему этапу. Если любая метрика нарушает порог, пайплайн запускает автоматический откат: трафик возвращается к старой версии, feature flags отключаются, команда получает уведомление.

Поэтапное развёртывание: расширение аудитории

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

Пайплайн продолжает расширять аудиторию шаг за шагом: от десяти процентов до двадцати пяти, затем до пятидесяти и, наконец, до ста процентов. Каждый раз при переходе к следующему кольцу пайплайн проходит через шлюз продвижения (promotion gate). Этот шлюз может быть автоматической проверкой на основе метрик или ожидать ручного подтверждения от команды. Многие команды используют комбинацию: автоматические шлюзы для быстрых решений и ручное подтверждение для критических этапов, например, перед переходом к ста процентам пользователей.

Очистка feature flags

Когда новая версия обслуживает всех пользователей, пайплайн ещё не завершён. Feature flags, которые теперь активны для всех, необходимо очистить. Пайплайн может запустить задачу, проверяющую, используется ли флаг, а затем создать pull request для удаления кода флага из репозитория. Это предотвращает накопление в кодовой базе мёртвых флагов, о которых никто не помнит.

Что делает этот пайплайн особенным

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

Ключевое отличие от традиционного пайплайна в том, что вы спрашиваете не «прошла ли сборка?», а «безопасно ли показывать это изменение большему числу пользователей?». На этот вопрос нельзя ответить одними модульными тестами. Требуются реальный трафик, реальные пользователи и реальные метрики.

Практический чек-лист для вашего пайплайна

Если вы строите пайплайн прогрессивной доставки, вот компоненты, которые нужно проверить на каждом этапе:

  • Canary-кольцо: Получает ли оно небольшую, измеримую долю трафика? Можно ли направлять пользователей последовательно, чтобы один и тот же пользователь оставался в одном кольце?
  • Feature flags: Ограничены ли флаги конкретными пользователями или группами? Можно ли включать/выключать их независимо от развёртывания?
  • Observability: Отслеживаются ли частота ошибок, задержка и бизнес-метрики? Основаны ли пороги на ваших SLO, а не на произвольных догадках?
  • Шлюзы продвижения: Есть ли у каждого кольца чёткое условие для перехода? Предусмотрен ли шаг ручного подтверждения для критических расширений?
  • Откат: Автоматизирован ли откат при нарушении порогов метрик? Включает ли он как перенаправление трафика, так и деактивацию флагов?
  • Очистка флагов: Есть ли процесс удаления флагов после полного развёртывания? Создаёт ли пайплайн pull request или уведомляет команду?

Вывод

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

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