Все знают этот момент: нажимаешь «деплой» и буквально задерживаешь дыхание. Ждёшь, не упадёт ли прод. Не выскочит ли 500-я ошибка. Не позвонит ли клиент через три минуты с криком «сайт не работает».
Хорошая новость: это решаемая проблема. Blue-green и canary — два подхода, которые превращают деплой из лотереи в управляемый процесс. И нет, это не только для Netflix и Яндекса. Небольшой проект тоже может себе это позволить.
Почему обычный деплой — это рулетка
Классический сценарий: остановил приложение, залил новый код, запустил. В лучшем случае — всё ок. В худшем — даунтайм от нескольких секунд до «иди смотри логи в два часа ночи».
Даже если деплоишь через git pull и nginx reload, всё равно есть момент, когда старый код уже не работает, а новый ещё не поднялся. Плюс — если что-то сломалось, откат занимает время. А за это время пользователи видят ошибки.
Для проекта с сотнями тысяч пользователей это катастрофа. Для небольшого интернет-магазина с 50 заказами в день — тоже неприятно, потому что каждый потерянный заказ — это деньги.
Blue-green: два окружения, один переключатель
Суть идеи простая до элегантности. У тебя два идентичных окружения — условно «синее» и «зелёное». В каждый момент одно из них работает на проде, второе — в резерве.
Когда нужно задеплоить новую версию:
- Берёшь неактивное окружение (скажем, зелёное).
- Деплоишь туда новый код.
- Прогоняешь smoke-тесты — убеждаешься, что всё живо.
- Переключаешь трафик с синего на зелёное — это занимает секунды через nginx или балансировщик.
- Синее окружение остаётся стоять — на случай отката.
Если что-то пошло не так — одна команда переключает трафик обратно. Откат занимает 30 секунд, а не «сейчас найду бэкап и пересоберу».
Как это выглядит на практике
Допустим, у тебя VPS с nginx и Node.js-приложением. Простейшая реализация:
/apps/blue/ — порт 3000
/apps/green/ — порт 3001
В nginx:
upstream app {
server 127.0.0.1:3000; # blue активен
}
Деплоишь в /apps/green, поднимаешь на порту 3001, проверяешь. Потом меняешь конфиг:
upstream app {
server 127.0.0.1:3001; # переключились на green
}
И делаешь nginx -s reload. Это атомарно — nginx заканчивает обрабатывать текущие запросы на старом бэкенде и переключается на новый. Даунтайм — ноль.
Что нужно учесть
Базы данных — главная сложность. Если новая версия меняет схему БД, старая версия может не работать с новой схемой и наоборот. Решение: применяй миграции, которые обратно совместимы. Сначала добавь новые поля (nullable или с дефолтом), задеплой новый код, потом убери старые поля.
Состояние сессий. Если хранишь сессии в памяти приложения, при переключении пользователи разлогинятся. Используй Redis — он стоит снаружи обоих окружений и не зависит от переключения.
Стоимость ресурсов. Два окружения — это примерно в полтора раза больше RAM и CPU. На небольшом VPS это заметно. Лайфхак: неактивное окружение можно держать «спящим» — поднимать только перед деплоем и не нагружать постоянно.
Canary: выкатываем для 5% пользователей
Blue-green — это всё или ничего. Canary-деплой — про постепенность. Ты выкатываешь новую версию для маленькой доли трафика, смотришь, как она себя ведёт, и только потом раскатываешь на всех.
Название — отсылка к старой горнодобывающей практике. Шахтёры брали с собой канарейку: если птица падала — в воздухе газ, пора уходить. Новая версия приложения — это твоя канарейка. Если 5% пользователей видят ошибки, ты останавливаешь раскатку, а не роняешь прод для всех.
Как настроить canary на nginx
upstream app_stable {
server 127.0.0.1:3000;
}
upstream app_canary {
server 127.0.0.1:3001;
}
split_clients "${remote_addr}${http_user_agent}" $upstream_pool {
5% app_canary;
* app_stable;
}
server {
location / {
proxy_pass http://$upstream_pool;
}
}
Модуль split_clients хешит строку (IP + user-agent) и детерминировано отправляет 5% запросов на canary. Один и тот же пользователь всегда попадает в одну группу — это важно для UX.
Когда убедился, что всё нормально — меняешь 5% на 20%, потом на 50%, потом на 100%. Или откатываешь обратно на 0%.
Что мониторить во время раскатки
Просто смотреть «не падает ли» — недостаточно. Смотри на:
- Частоту ошибок: процент 5xx ответов от canary vs stable. Норма — примерно одинакова.
- Время ответа: если canary отвечает вдвое медленнее — что-то не так.
- Бизнес-метрики: конверсия, добавления в корзину, завершённые заказы. Технически всё может быть ок, но из-за UX-изменения конверсия упала.
Для небольшого проекта достаточно Grafana + Prometheus или даже Uptime Kuma — он покажет аномалии во времени ответа без сложной настройки.
Когда что использовать
Это не конкуренты — это разные инструменты для разных ситуаций.
Blue-green подходит, когда:
- Хочешь простой и быстрый откат.
- Релизы редкие, но важные — крупное обновление с кучей изменений.
- Важен нулевой даунтайм, но нет смысла тестировать на реальных пользователях постепенно.
Canary подходит, когда:
- Хочешь проверить гипотезу на реальном трафике.
- Изменения затрагивают критичные части: оплата, регистрация, поиск.
- Достаточно трафика, чтобы 5% дали статистически значимую выборку — хотя бы 100–200 запросов в день на canary.
На практике часто комбинируют: деплоишь через blue-green для нулевого даунтайма, а после переключения используешь canary-логику для постепенного раскрытия фичи через feature flags.
Feature flags — бонусный уровень
Пока говорим о canary — нельзя не упомянуть feature flags. Новый код уже задеплоен, но включается для конкретных пользователей через конфиг, а не через переключение трафика.
Простейший вариант — переменная в Redis:
const isNewCheckoutEnabled = await redis.get('feature:new_checkout') === '1';
if (isNewCheckoutEnabled) {
// новый флоу
} else {
// старый флоу
}
Можно включать для конкретных user_id, для процента пользователей, для определённых регионов. Это даёт полный контроль без перезапуска приложения.
Из готовых решений — Unleash (open source, разворачивается у себя) или GrowthBook. Для небольшого проекта хватит своей реализации на Redis — это пара часов работы.
Что нужно, чтобы это заработало
Несколько условий, без которых blue-green и canary не имеют смысла.
CI/CD пайплайн. Если деплоишь руками через SSH, blue-green превращается в квест. Автоматизируй хотя бы базовый флоу: push в main → сборка → тесты → деплой в неактивное окружение. GitHub Actions, GitLab CI — для небольшого проекта бесплатно.
Smoke-тесты. Хотя бы 5–10 проверок ключевых эндпоинтов: главная страница возвращает 200, API логина работает, корзина доступна. Без этого не поймёшь, работает ли canary нормально, пока пользователи не начнут жаловаться.
Централизованные логи. Когда логи лежат на двух разных серверах — отлаживать неудобно. Направь всё в один стек: ELK, Loki+Grafana или хотя бы Papertrail.
Health check эндпоинт. /health или /ping — возвращает 200, если приложение живо. Балансировщик должен проверять это перед переключением трафика.
Реальный пример: небольшой интернет-магазин
Возьмём конкретный кейс. Интернет-магазин на Laravel, VPS с 4 ГБ RAM, nginx как фронтенд. Деплои раз в неделю.
Было: git pull на проде, php artisan migrate, php artisan config:cache, supervisor restart. Даунтайм 5–15 секунд. Несколько раз падали прямо во время деплоя из-за несовместимых миграций.
Стало:
- Два Laravel-приложения:
/var/www/app-blue и /var/www/app-green. Один symlink /var/www/app-current указывает на активное.
- Деплой идёт в неактивное окружение: rsync, миграции, кэши.
- Тест через curl на
/health неактивного окружения.
- Переключение: перезаписываем symlink,
nginx reload.
- Старое окружение живёт ещё 30 минут — на случай если что-то всплывёт.
Время переключения — 2–3 секунды. Откат — одна команда.
Этот же подход работает для сайта-визитки, корпоративного сайта, лендинга — везде, где есть хотя бы минимальный трафик и требования к доступности.
Инструменты, которые упрощают жизнь
Deployer (PHP) — специализированный инструмент для деплоя PHP-приложений. Из коробки умеет zero-downtime через symlink-стратегию, хранит несколько последних релизов для отката.
Kamal (бывший MRSK) — от создателей Rails. Деплоит Docker-контейнеры с поддержкой zero-downtime. Хорошо подходит для небольших проектов, которые не хотят тащить Kubernetes.
Kubernetes — если проект вырос. Встроенные rolling updates, canary через Argo Rollouts или Flagger. Но это уже другой уровень сложности и стоимости инфраструктуры.
Ansible — если несколько серверов и хочется единый инструмент для конфигурации и деплоя.
Для большинства небольших проектов хватит Deployer или Kamal — простые, хорошо документированные, не требуют отдельной инфраструктуры.
Как начать, если сейчас деплой — это git pull
Не нужно переписывать всё за один раз. Разумная последовательность:
- Добавь health check эндпоинт. 30 минут работы, сразу польза.
- Настрой CI/CD — хотя бы автоматический прогон тестов на push.
- Введи symlink-стратегию. Деплоишь в новую папку, переключаешь symlink. Это уже даёт быстрый откат.
- Добавь второе окружение под blue-green — если VPS позволяет по ресурсам.
- Попробуй canary на следующем значимом изменении.
Каждый шаг — уже улучшение. Не обязательно делать всё сразу.
Если заказываешь разработку сайта или интернет-магазина — стоит сразу обсудить с подрядчиком, как будет устроен деплой. В REEXY при разработке корпоративных сайтов и магазинов мы закладываем CI/CD и нормальную стратегию деплоя в архитектуру с самого начала — это дешевле, чем переделывать потом. Поддержка сайта от 10 000 ₽/мес включает в себя сопровождение деплоев и мониторинг.
Деплой не должен быть страшным. Это просто ещё один технический процесс, который можно и нужно сделать предсказуемым.