Минулого Q4 я переносив revenue-critical платформу між двома тенантами Azure у найгарячіший квартал року — і весь сенс у тому, що ви читаєте про це зараз, а не чули тоді. Zero downtime міграція між тенантами — це не героїчний спринт на вихідних. Це чотири місяці параної, 241 Terraform-модуль і план відкату, якому я довіряв більше, ніж власним рукам.
Ставки
Вісім сервісів. Два тенанти. 500+ активних користувачів. Застосунок крутив бюджети, клієнтські дані, операційні процеси — той випадок, коли кожна хвилина даунтайму — це гроші, що йдуть із компанії. Бізнес видав рівно одне речення по скоупу: «Мігруй, але щоб нічого не зламалося». Без тиску, ага.
Q4 — це пік трафіку. Будь-яка здорова людина призначила б таку міграцію на тихі липневі вихідні. У нас такої розкоші не було — календар казав зараз, а виторг казав не смій упустити жоден запит.
Вісім шарів залежностей не переносяться «в лоб»
Наївна версія цієї задачі — «вивантажити все, завантажити все, перемкнути DNS». Це працює, коли сервіси незалежні. Мої — ні. Залежності йшли на вісім шарів углиб, тому порядок міграції вирішував усе:
- Спершу шар даних — без нього решта не має сенсу
- Другими — сервіси identity: усе спочатку автентифікується, а вже потім щось робить
- Третьою — бізнес-логіка
- Ядро застосунку — в останню чергу
Помились у порядку — отримаєш каскадну відмову: сервіс A чекає на B, B чекає на C, і одне передчасне перемикання роняє всю конструкцію.
IaC-фундамент
Інфраструктура — це 241 Terraform-модуль під керуванням Terragrunt, по модулю на сервіс на оточення, і повторюваність тут навмисна. Нудна інфраструктура — надійна інфраструктура.
Раз уже я все одно був усередині, я виніс усі секрети service principal. Їх замінили OIDC і Workload Identity Federation, тож у фіналі ніде не зберігалося жодного довгоживучого креденшла. Якщо ви й так перезбираєте тенант із коду — це найдешевший момент полагодити свою модель автентифікації. Не тягніть старі секрети через кордон.
Перемикати трафік по-дорослому
Усе виконувалося паралельно: старий і новий тенант жили пліч-о-пліч, безперервна синхронізація даних тримала їх в одному стані. Далі я переводив реальний трафік порціями — 10%, 25%, 50%, 100% — з автоматичними gate-перевірками на кожному кроці.
Будь-який gate спрацьовував «у закриту». Якщо перевірка відхилялася — трафік відкочувався автоматично. Автоматично — не «комусь прилетів пейджер», не «людина о 2 ночі помітила, що дашборд почервонів, і почала щось друкувати». Страхувальна сітка не вимагала, щоб я не спав.
До всього цього я прогнав кожен відкат по три рази. Параноя — це фіча. Відкат, який ти жодного разу не виконував, — це надія, а надія — не стратегія відкату.
Найскладнішим був не Terraform
Ось чого вам ніхто не каже: Terraform не був складним. Конфіг OIDC не був складним. Синхронізація даних не була складною. Складним було тестування.
У кожного сервісу були точки інтеграції — інші внутрішні сервіси, зовнішні API, сторонні вебхуки. Під час переходу кожна з них мала працювати і в старому, і в новому тенанті одночасно. Вебхук, який знає лише старий ендпоінт, — це тиха втрата даних, що просто чекає свого часу. Тому ми тижнями ганяли паралельну валідацію, перш ніж перевести хоч один байт бойового трафіку. Більша частина цих чотирьох місяців пішла саме на це — не на будівництво, не на перемикання, а на доведення, що воно працює в усіх комбінаціях, які ми змогли вигадати.
Результат
Чотири місяці. Вісім сервісів. 241 модуль. Нуль інцидентів. Найбільший комплімент цій роботі — тиша в понеділок вранці: 500 людей роблять свою справу й не підозрюють, що земля під ними зрушила.
Що я сказав би вам перед наступним вікном міграції
Якщо ваш план — «зробимо на вихідних і сподіватимемось на краще», то це не план. Це бажання, а в бажань немає стратегії відкату. Найкраща міграція — та, якої ніхто не помітив. Автоматизуйте страхувальну сітку — або не чіпайте прод.
І залишу вас із тим самим питанням, яке ставлю собі перед кожною зміною на проді: яка у вас стратегія відкату? Якщо не можете відповісти одним реченням — ви ще не готові.