Порядок деплою, при якому сайт не віддає 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: автоматизація налаштування серверів, а безпечний відкат усієї міграції цілком описано у статті план відкату міграції.