← все статьи
8 мин

Почему zero-downtime деплой сложнее, чем кажется

Rolling update в Kubernetes – три строчки конфигурации. Кажется, что zero-downtime решён. На самом деле это только начало. Настоящие сложности – в слоях ниже контейнера.

Проблема №1: Database migrations

Самый частый источник downtime при "zero-downtime" деплоях. При rolling update одновременно работают старая и новая версия кода. Если миграция добавляет NOT NULL колонку без дефолта – старая версия не может писать в таблицу. Всё упало.

Правило: миграция всегда должна быть совместима со старой версией кода. Это означает многоэтапный подход:

-- Этап 1: добавить колонку nullable (обе версии работают) ALTER TABLE users ADD COLUMN phone VARCHAR(20); -- Деплой новой версии кода (заполняет phone при создании) -- Этап 2: backfill существующих записей UPDATE users SET phone = '' WHERE phone IS NULL; -- Этап 3: добавить NOT NULL после полного деплоя ALTER TABLE users ALTER COLUMN phone SET NOT NULL;

Проблема №2: Переименование колонок

Кажется простым: ALTER TABLE ... RENAME COLUMN. Но при rolling update старая версия кода всё ещё ищет старое имя. Порядок правильного переименования:

  • Добавить новую колонку, скопировать данные
  • Добавить триггер: изменения в старой → новую, и наоборот
  • Деплоить новый код, который пишет в новую колонку
  • Убедиться, что старая версия кода нигде не осталась
  • Удалить триггер, удалить старую колонку

Итого: 4 деплоя вместо одного. Это нормально.

Проблема №3: Backward-incompatible API

Если вы переименовали поле в JSON-ответе API – старые клиенты сломаются сразу после деплоя. Даже если клиент – это ваш же фронтенд в другом сервисе.

// правило двойного деплоя

Никогда не удаляйте поле и не меняйте его тип в одном деплое. Сначала добавьте новое поле (сохраните старое). Убедитесь, что все клиенты перешли на новое. Только потом удалите старое.

Проблема №4: Session affinity

При blue/green деплое пользователи с активными сессиями в "синем" окружении внезапно оказываются в "зелёном". Если сессии хранятся в памяти (не в Redis) – они потеряны. Пользователь разлогинен в середине транзакции.

Решение стандартное: externalized session (Redis, БД), а не in-memory. Но часто это добавляется не с самого начала.

Feature Flags как инструмент деплоя

Feature flags позволяют деплоить код без активации функциональности. Новая логика скрыта за флагом, включается отдельно от деплоя. Это развязывает deploy и release – можно деплоить непрерывно, а включать фичи по расписанию или для отдельных пользователей.

Деплой – технический процесс. Release – бизнес-решение. Смешивать их – источник стресса и ошибок.

Для большинства продуктов достаточно простого решения: флаги в конфиге или базе данных, без сложных платформ. LaunchDarkly и аналоги оправданы при десятках команд и тысячах флагов.


← все статьи Следующая →Кейс: AI-поиск для маркетплейса: +34% конверсии