Порядок деплоя, при котором сайт не отдаёт 502
Zero-downtime не значит «без риска» — значит «без видимого для пользователя перерыва». Это достигается тем, что новая версия поднимается и проверяется рядом со старой, а переключение происходит одной атомарной операцией, которую легко отменить.
- Разверните новую версию приложения на отдельном порту или в отдельном контейнере, не трогая работающую.
- Дождитесь, пока новая версия пройдёт health-check и полностью инициализируется (прогреет кеш, подключится к базе).
- Проверьте новую версию напрямую, минуя основной домен — через прямой порт или служебный заголовок.
- Переключите балансировщик или прокси на новую версию одной командой.
- Держите старую версию запущенной ещё некоторое время — на случай, если понадобится мгновенный откат.
Честно: полностью нулевого простоя не бывает даже при таком порядке — остаётся доля секунды на переключение соединений в момент reload. На практике это означает 0–2 секунды видимой задержки для части запросов, а не полное отсутствие эффекта.
Blue-Green деплой
Поддерживаем два идентичных окружения: Blue (текущий live) и Green (новая версия). После тестирования Green — переключаем трафик.
# Nginx upstream — переключение между blue и green
upstream app {
server 127.0.0.1:8080; # blue
# server 127.0.0.1:8081; # green (раскомментировать при переключении)
}
server {
location / {
proxy_pass http://app;
}
}
Blue-Green с Docker Compose
# Запускаем green окружение
docker-compose -f docker-compose.green.yml up -d
# Проверяем green
curl http://localhost:8081/health
# Переключаем Nginx на green
sed -i 's/8080/8081/' /etc/nginx/conf.d/app.conf
nginx -s reload
# Останавливаем blue
docker-compose -f docker-compose.blue.yml down
Rolling Deployment
Постепенная замена инстансов: обновляем один за другим, не останавливая сервис.
# Пример с Docker Swarm
docker service update --image myapp:v2 --update-parallelism 1 --update-delay 30s myapp_service
Сравнение стратегий деплоя
| Стратегия | Откат | Ресурсы | Сложность |
|---|---|---|---|
| Blue-Green | Мгновенный | 2x | Средняя |
| Rolling | Постепенный | 1x + overhead | Низкая |
| Canary | Постепенный | 1x | Высокая |
Проверка новой версии до переключения трафика
Не полагайтесь на визуальный осмотр — проверяйте health-check эндпоинт и реальный сценарий работы приложения напрямую на новом порту, до того как переключить прокси:
curl -s http://127.0.0.1:8081/health | grep -q '"status":"ok"' && echo "Green готов"
Здоровый эндпоинт должен проверять не только «процесс запущен», но и реальные зависимости: подключение к базе данных, доступность кеша, готовность очереди задач.
Типичные ошибки при переключении
| Симптом | Причина и решение |
|---|---|
| 502 Bad Gateway сразу после reload | Новый апстрим ещё не принимает соединения — добавьте health-check перед переключением Nginx |
| Часть запросов идёт на старую версию после переключения | Keep-alive соединения с воркерами Nginx не сброшены — используйте nginx -s reload, а не restart |
| Ошибки схемы БД после деплоя новой версии | Миграция базы несовместима со старой версией кода, которая ещё работает параллельно |
Откат при неудачном деплое
- Не останавливайте старую версию (blue), пока новая не отработала под реальным трафиком минимум 15–30 минут.
- При проблемах верните upstream на старый порт — команда идентична переключению, только в обратную сторону.
- Разберитесь с причиной сбоя на green-окружении отдельно, не мешая рабочему трафику.
Когда это не подходит
Blue-Green требует вдвое больше ресурсов на время деплоя — для небольших проектов с ограниченным бюджетом это может быть неоправданно. Если приложение хранит состояние в памяти процесса (сессии, WebSocket-соединения) без внешнего хранилища, при переключении эти данные теряются — нужна отдельная схема с sticky-сессиями или внешним хранилищем состояния.
⚠️ При blue-green деплое убедитесь что оба окружения работают с одной базой данных и схема БД совместима с обеими версиями приложения.
Проверка результата после переключения
- Мониторьте частоту ошибок 5xx в логах несколько минут после переключения — всплеск указывает на проблему.
- Проверьте, что старые открытые сессии пользователей не разорвались.
- Убедитесь, что фоновые задачи (очереди, cron) не выполняются дважды на старой и новой версии одновременно.
Настройку серверов через Ansible перед регулярными деплоями удобно автоматизировать — см. статью Ansible: автоматизация настройки серверов, а безопасный откат всей миграции целиком описан в статье план отката миграции.