Перейти до вмісту
NimbusNexus

Blue/green-розгортання з плаваючими IP

Класичний патерн blue/green: тримайте поточний продакшн за плаваючим IP, розгорніть нову версію на окремій VM, запустіть на ній smoke-тести, поки на неї ще не йде публічний трафік, а тоді перекиньте плаваючий IP зі старої VM на нову. Трафік переходить за ~2 секунди. Якщо щось піде не так, перекиньте IP назад.

Ця інструкція розрахована на навантаження з однією VM (одна продакшн-VM, одна staging-VM). Для навантажень із кількома VM за балансувальником навантаження див. сторінку Балансувальники навантаження — патерн той самий, але натомість ви перемикаєте цільові пули LB.

Що знадобиться

  • Дві VM в одному регіоні. Назвемо їх blue (зараз обслуговує трафік) і green (наступна версія).
  • Плаваючий IP, зараз підʼєднаний до blue.
  • DNS-запис A, що вказує на плаваючий IP.
  • Встановлений CLI nimbus або curl із заданим $NIMBUS_KEY.
Shell
export NIMBUS_KEY="nn_live_xxxxxxxxxxxxxxxx"
export BLUE_ID="vm_01HG7Y3..."     # currently serving
export GREEN_ID="vm_01HG7Y4..."    # new version
export FLOATING_IP_ID="ip_01HG7..."

1 · Підготуйте VM green

Запустіть нову версію з оновленим кодом/конфігурацією, але без підʼєднаного плаваючого IP. На цьому етапі це окрема VM із публічним IP за замовчуванням; з продакшну на неї нічого не надходить.

Розгорніть на ній застосунок, виконайте міграції бази даних (якщо вони прямо сумісні — див. «міграції схеми» нижче), прогрійте кеші, виконайте всю стартову роботу, яка має відбутися до появи трафіку.

2 · Проведіть smoke-тести на green

Звертайтеся безпосередньо до публічного IP, який green має за замовчуванням:

Shell
GREEN_IP=$(curl -s https://api.nimbusnexus.net/v1/vms/$GREEN_ID \
  -H "Authorization: Bearer $NIMBUS_KEY" | jq -r '.ipv4')

curl -H "Host: app.example.com" "http://$GREEN_IP/healthz"
curl -H "Host: app.example.com" "http://$GREEN_IP/api/critical-endpoint"

Заголовок Host дає змогу перевірити поведінку, що залежить від канонічного імені хоста (напр., маршрутизацію, CORS, усе, що привʼязано до сертифіката), не змінюючи DNS. Якщо ваш сервіс вимагає HTTPS і ви привʼязали сертифікат до app.example.com, заздалегідь налаштуйте сертифікат на green (підійде Let's Encrypt із challenge HTTP-01 на IP green за замовчуванням).

Запустіть усі інші тести, які ви запускали б перед переведенням версії в продакшн:

  • Повний набір smoke-тестів
  • Перевірка підключення до бази даних (особливо якщо green працює з іншою конфігурацією пулера зʼєднань)
  • Перевірка підпису вебхуків (якщо ви ротували секрет)

3 · Перекиньте плаваючий IP

Це і є cutover. Один виклик API:

Shell
curl -X POST https://api.nimbusnexus.net/v1/floating-ips/$FLOATING_IP_ID/attach \
  -H "Authorization: Bearer $NIMBUS_KEY" \
  -H "Content-Type: application/json" \
  -d "{ \"vm_id\": \"$GREEN_ID\" }"

Що відбувається:

  • Плаваючий IP відʼєднується від blue (цей IP був однією з її публічних адрес)
  • Плаваючий IP підʼєднується до green
  • Зміни поширюються мережею за ~2 секунди; запити на IP починає обслуговувати green
  • TCP-зʼєднання з IP старої VM лишаються відкритими, доки не закриються через простій (для HTTP keepalive зазвичай 30–60 секунд); нові зʼєднання потрапляють на green

Для більшості HTTP-навантажень це фактично розгортання без даунтайму. Наявні зʼєднання завершують свої запити на blue; нові запити потрапляють на green. Користувачів із довготривалими зʼєднаннями (SSE, WebSocket) їхні клієнти перепідключають автоматично.

4 · Стежте за green під навантаженням

Переглядайте логи green у реальному часі, стежте за частотою помилок і графіком запитів у дашборді. Тут проявляються аномалії реального трафіку, яких не виявили smoke-тести.

Дешево відкотитися можна протягом перших ~5 хвилин. Після цього blue — це «старий код, що працює без трафіку», і ви за нього платите; тож доведеться вибрати одне з двох:

  • Перевести green у продакшн і зупинити blue (основний сценарій)
  • Зупинити обидві VM і почати спочатку (рідко)

5 · Зупиніть blue

Якщо все зелене (буквально), зупиніть blue, щоб більше за нього не платити:

Shell
curl -X POST https://api.nimbusnexus.net/v1/vms/$BLUE_ID/stop \
  -H "Authorization: Bearer $NIMBUS_KEY"

Не робіть delete одразу. Зупинені VM коштують ~10 % від вартості запущених (лише сховище), і протягом ~24 годин їх можна знову запустити через start для швидкого відкату. Через 24 години видаліть їх.

Шлях відкату

Якщо green поводиться неправильно під навантаженням, відкат симетричний:

Shell
curl -X POST https://api.nimbusnexus.net/v1/floating-ips/$FLOATING_IP_ID/attach \
  -H "Authorization: Bearer $NIMBUS_KEY" \
  -H "Content-Type: application/json" \
  -d "{ \"vm_id\": \"$BLUE_ID\" }"

Ті самі ~2 секунди — і трафік знову на blue. Відкотитися складніше, якщо міграції бази даних не були прямо сумісними — тримайте міграції схеми окремо від розгортань коду, і можливість відкату залишиться.

Міграції схеми

Патерн, завдяки якому blue/green чисто працює зі змінами схеми: відокремте міграцію від розгортання.

Кожна зміна схеми — це два PR з інтервалом в один тиждень:

  1. PR із міграцією. Зворотно сумісна міграція схеми. Нові таблиці, нові стовпці, що допускають NULL, нові індекси. Старий код і далі працює з новою схемою. Розгортайте його звичайним шляхом (blue/green не потрібен — завдяки зворотній сумісності міграцію можна безпечно випустити окремо).
  2. PR із кодом. Код, що використовує нову схему. Розгортайте його через blue/green.

Коли треба видалити стовпець або змінити тип, послідовність зворотна: код перестає використовувати стовпець → розгортання коду → міграція видаляє стовпець. Завжди два PR, рознесені в часі. Між ними завжди можна безпечно зупинитися.

Цей патерн вимагає більше роботи, ніж «завжди розгортати схему й код разом», але зберігає безпечний відкат, а саме для цього blue/green і потрібен.

Наступні кроки