ADG Оставить заявку
Блог DevOps 6 мин чтения

«А вы не сломаете прод?»: staging, канарейки и zero-downtime

Страх сломать хрупкий продакшн — главный стоппер автоматизации. Разбираем технически: staging как точная копия, канареечные релизы и zero-downtime в согласованном окне с планом отката.

Контекст момента

Страх сломать хрупкий легаси — главный стоппер автоматизации; разбираем, как его снимают технически

Этот вопрос задают почти на каждом первом разговоре. Иногда его произносят прямо, иногда он звучит иначе: «у нас сложная инфраструктура», «наш прод очень специфичный», «последний раз деплой встал на три часа». За всеми формулировками — одна и та же тревога: что если автоматизация сломает то, что сейчас хотя бы как-то работает.

Тревога обоснована. Именно поэтому первое правило нашей работы с продакшном — не трогать его напрямую, пока изменение не прошло проверку в безопасной среде.

Почему выкатывают ночью — и что с этим не так

Типичная картина у клиентов, которые приходят к нам с болью по CI/CD: деплой делается вручную по инструкции из Confluence, а выкатывают всегда ночью или в воскресенье. Логика понятна — меньше пользователей, если что-то пойдёт не так, удар будет тише.

Но ночной деплой — это симптом проблемы, а не решение. Инженеры устали, внимание рассеяно, пул нужных людей для разбора инцидента недоступен. Именно ночью «пропускают» то, что заметили бы днём. В нашем посте про GitLab CI 2017 года мы описывали схожую ситуацию: команда переходила с ручных деплоев на пайплайн не потому что стало веселее, а потому что ручная выкатка на пятнадцати сервисах в 02:00 — это слишком высокий риск ошибки на усталого инженера.

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

Staging: точная копия, а не «похожая среда»

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

На staging мы прогоняем всё, что планируем выкатить в прод: обновления кода, изменения конфигурации, миграции схемы базы данных. Если что-то ломается — ломается здесь, а не в продакшне. Это и есть ценность среды.

Когда в 2014 году мы добавляли Serverspec-тесты в Jenkins-пайплайн для проверки состояния инфраструктуры после деплоя Ansible, в том посте честно написали: staging-окружение тогда ещё не было автоматизировано, и деплой шёл прямо в продакшн. Это была известная точка риска. Staging как обязательный шаг пайплайна появился позже — именно потому, что тестирование непосредственно перед продом недостаточно без предварительной проверки в изолированной среде.

Сейчас в нашем стандартном пайплайне на GitLab это выглядит так: ветка develop автоматически деплоится на staging, прогоняются автотесты, Serverspec-тесты инфраструктуры. Только при успехе этой цепочки открывается деплой в прод — и он уже не ручной, а тоже автоматизированный.

Честный trade-off: staging не бесплатен и не ловит всё

Здесь важно не лукавить.

Staging стоит денег. Полная копия продакшна — это двойная инфраструктура. Для крупных контуров это существенная статья. Оптимизация: тестовые среды не должны работать круглосуточно. В нашем материале по FinOps мы показывали, как ночное гашение dev/staging-окружений дало −12% счёта при том, что функциональность сред не пострадала — разработчики приходили к рабочим средам к 8:00, а платили только за рабочие часы.

Staging не воспроизводит прод на 100%. Данные другие. Трафик другой. Иногда есть внешние интеграции, которые в тестовой среде либо заглушены, либо ведут себя иначе. Это означает, что staging снижает риск, но не устраняет его полностью. Остаточный риск существует, и с ним нужно работать отдельным инструментом.

Этим инструментом служит канареечный деплой.

Канарейки: сначала 5% трафика

Канареечный релиз — это выкатка новой версии на небольшую долю продакшн-трафика до полного переноса. Классический вариант: 5% пользователей получают новую версию, остальные 95% работают со старой. Мы наблюдаем метрики — ошибки, latency, бизнес-события — и только при нормальных показателях расширяем аудиторию.

В Kubernetes это реализуется через управление весами трафика в Ingress или service mesh. В простых случаях — через параллельные деплойменты с ручным управлением весами. Логика одна: новый код встречается с реальными пользователями под контролем, а не сразу полностью.

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

Zero-downtime: перенос без остановки

Zero-downtime deploy — это выкатка, при которой сервис остаётся доступным на всём протяжении деплоя. Пользователи не видят страницы ошибки, запросы не дропаются, балансировщик переключается между старой и новой версией без разрыва.

В Kubernetes это достигается через rolling update: новые поды поднимаются рядом со старыми, трафик переключается по мере готовности, старые поды выводятся из ротации только после того, как новые прошли health-check. PodDisruptionBudget ограничивает количество одновременно недоступных реплик — это тот самый параметр, который в нашем проекте 2017 года потребовал нескольких итераций настройки.

Для zero-downtime нужна готовность приложения: graceful shutdown (сервис принимает SIGTERM и корректно завершает активные запросы), health-check endpoint, правильно настроенные liveness и readiness пробы. Это не всегда есть в легаси-приложениях, и тогда zero-downtime требует предварительной работы с кодом — мы честно говорим об этом до старта.

Согласованное окно и план отката

Даже при наличии staging и zero-downtime мы согласовываем окно для плановых деплоев — не потому что боимся, а потому что это правильная практика. Окно — это не запрет, а договорённость: в это время команда готова к реакции, мониторинг настроен на повышенное внимание, дежурный инженер на связи.

Что ещё важнее окна — заранее определённый план отката. До начала деплоя мы фиксируем:

  • как откатываемся: предыдущий образ задеплоен и готов к kubectl rollout undo или аналогу; миграции схемы — только обратно совместимые, либо откат делается отдельно;
  • критерий откатиться: конкретный порог — например, уровень ошибок выше базового на канареечной группе в течение пяти минут;
  • кто принимает решение: не обсуждается в момент инцидента, а определено заранее.

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

Что это даёт на практике

Когда пайплайн выстроен — staging, автотесты, канарейка, zero-downtime, согласованное окно, план отката — деплой перестаёт быть событием. Это типовая операция, которую инженер запускает в рабочее время, не в 02:00 в воскресенье.

Именно к этому состоянию мы приводим инфраструктуру клиентов: выкладка релиза в один клик, реакция на инцидент от 15 минут силами дежурной смены, а не ваша команда с телефоном под подушкой. Окна работ и RTO/RPO фиксируем в договоре под конкретный контур.

Если ваша команда сейчас деплоит руками и ночью, или если вопрос «а вы не сломаете прод?» возникает каждый раз перед выкаткой — это точка входа для разговора. Подробно о том, что входит в сопровождение, — на странице DevOps-аутсорсинга. Если контур на отечественном стеке или нужен переход на реестровое ПО — смотрите также практику импортозамещения.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.