DarkRiDDeR21 мин

План миграции без прыжка: карта фаз, ворот и обратимого состояния

АрхитектураИнженерная практика

Проблема плана миграции в том, что он часто начинается с красивой целевой схемы и заканчивается словом «cutover». Между ними исчезают инвентарь, владелец маршрута, перевод трафика, состояние записей и решение об откате. Цена такого пропуска не абстрактный риск: в момент сбоя нельзя быстро ответить, что именно вернуть, кто принимает решение и какие новые записи уже нельзя трактовать как прежние. Архитектура остаётся на доске, а переход превращается в спор о памяти участников.

Рабочая альтернатива — не общий список шагов, а маленькая decision-gated карточка. Каждая фаза принимает named fixed synthetic literal, добавляет один проверяемый факт и либо отдаёт точный stop reason, либо делает возможным только synthetic-migration-review-hand-off. Это не разрешение начать, продолжить или завершить миграцию. Это дисциплина описания: следующий вопрос нельзя открыть, пока текущая граница не названа.

Начать не с цели, а с карты того, что переходит

Целевая архитектура отвечает «куда». Migration card обязана сначала ответить «что сейчас связано». В учебном literal есть один route route-ledger-read, один owner, один record и две зависимые границы. Такой масштаб намеренно мал. Он не представляет репозиторий или сервис. Зато на нём видно правило: route без владельца и dependency — это не неполная таблица, а невозможность ответственно определить последствия перехода.

Инвентарь не должен изображать каталог файлов. Для перехода достаточно четырёх типов связей: входной route, запись или ресурс, читатель и писатель, внешняя зависимость. Если route обращается к record, но не известно, кто формирует запись, план не умеет описать data transition. Если известна запись, но нет читателя, нельзя формулировать evidence о совместимости. Стоп здесь экономит самый дорогой вид работы: позднее обнаружение обязательной связи внутри окна изменений.

Четыре карточки migration playbook: inventory, data state, traffic slice и review evidence. Красные ветки ведут к stop для отсутствующего инвентаря, необратимых данных и неназванного триггера rollback.
Фазу открывает связанное доказательство. Зелёная карточка означает только synthetic review hand-off; она не является разрешением на действие.
Минимальная карточка фазы
ФазаВходПроверяемое условиеТочный отказ
inventoryroute, owner, record, dependencyвсе имена связаныstop-missing-inventory
data statecopy, reconciliation, restore stateсостояние обратимо в моделиstop-irreversible-data-state
traffic slicecontrol, candidate, windowмаршрут и сравнение названыstop-unbounded-traffic-slice
rollbacktrigger, owner, traffic/data returnрешение воспроизводимоstop-unnamed-rollback-trigger
reviewполная карточкавывод ограничен hand-offstop-disallowed-positive-result

Фаза data не равна слову «копия»

Запись copy-complete говорит только о том, что в модели есть копия. Она не говорит, как вернуть дальнейшие записи, чем сверять границы и куда должен вернуться write state. Поэтому accepted literal требует copy-verified-reversible, named reconciliation и named restore state. Это не рецепт для конкретной базы данных. Это минимальная форма вопроса, который не позволяет выдать перенос байтов за обратимый переход данных.

Особенно опасна подмена: «трафик можно направить назад, значит rollback есть». Для read-only примера она может выглядеть правдоподобно, но в модели записи трафик и данные — разные оси. Возврат control route не отменяет новых записей и не создаёт их обратного преобразования. Kubernetes Documentation о Deployment полезна здесь именно как граница: rollback его revision относится к Pod template. Из этого не следует, что он отменяет эффект данных, внешний контракт или любой иной transition.

Срез трафика требует контрольной стороны

Десять процентов candidate без control boundary — это число без вопроса. Нельзя понять, с чем его сопоставлять, какой маршрут остался прежним и одинаково ли определены условия наблюдения. В fixed record control и candidate имеют один и тот же route id, разные shares и один named observation window. Эти числа не изображают настоящий балансировщик и не выражают совет о долях. Они делают сравнение типизированным: у наблюдения есть две стороны, а не только интересный новый путь.

Наблюдаемость в карточке тоже не телеметрия. fixed-error-ratio и fixed-contract-mismatch — имена полей literal, не метрики системы. Их задача — не доказать здоровье, а не позволить написать «посмотрим внимательно». Когда окно и критерий не названы, проверка возвращает stop-unbounded-traffic-slice. Такой отказ полезнее зелёной галочки: он указывает ровно на отсутствующую control boundary.

Исполняемая карточка фаз

import { createFixedMigrationRecord, reviewFixedMigrationPlaybook } from './upgrade-2026-07.mjs';

const record = createFixedMigrationRecord('fixed-migration-ready-v1');
const result = reviewFixedMigrationPlaybook(record);
console.log({ status: result.status, route: result.transition.inventory.routeId, recovery: result.transition.data.restoreState });
// { status: 'synthetic-migration-review-hand-off', route: 'route-ledger-read', recovery: 'fixed-source-write-resume-v1' }

Пример буквально читает immutable teaching object в памяти Node. Он не делает DNS change, не открывает соединение, не копирует record и не запрашивает метрики. Даже положительный status несёт effect: no-system-change. Это важнее красивого имени функции: reader должен видеть в данных тот же запрет, который сформулирован в тексте. Code проверяет полноту модели, а не готовность среды.

Rollback — отдельное решение, не хвост списка

У rollback есть четыре собственных имени: trigger, условие, return state трафика и return state данных; рядом стоит decision owner. Формулировка «при проблеме вернём назад» не содержит ни одной из них. Она не определяет, какая проблема достаточна, что именно возвращается и кто может различить fix-forward от возврата. Fixed trigger fixed-contract-mismatch-is-present-in-window узок специально: он не притворяется универсальным сигналом.

Google SRE Book описывает каскадный отказ как рост сбоя из положительной обратной связи. Из этого текста здесь берётся не production-вывод и не порог для команды, а инженерская осторожность: поздняя, расплывчатая реакция усиливает неопределённость. В учебной карте named trigger обрывает риторику «подождём ещё немного». Он позволяет фиксировать, что именно отсутствует или что именно переводится в stop state, не назначая действие в реальной среде.

Последовательность, которую можно рецензировать

  1. Выбрать один named route и связать с ним owner, record, reader, writer и dependency; при пустом звене завершить review статусом stop-missing-inventory.
  2. Назвать data transition, reconciliation и restore state; не считать copy достаточным доказательством обратимости.
  3. Сформировать control и candidate с одинаковым route boundary, а затем назвать observation window и его поля.
  4. Записать trigger, condition, owner и оба return states; определить только форму stop, не действие в окружении.
  5. Проверить, что positive status остаётся synthetic hand-off, а открытый вопрос и effect остаются видимы.

Язык ворот должен быть точнее цели

RFC 2119 различает обязательность словом MUST и возможность словом MAY. В migration card это полезно не для игры в нормативность, а для редакторской проверки. «Нужно иметь rollback» слишком расплывчато. «Для hand-off MUST быть named trigger» можно проверить на поле literal. В то же время нельзя писать «система обязана перейти»: package не видит систему. Требование относится только к данным учебной карточки и должно завершаться механически видимым reason.

У каждой фазы своя ответственность. Автор карточки не подтверждает фактическое состояние сервисов; он отвечает, что имена не скрывают разные сущности. Рецензент инвентаря ищет отсутствующую связь. Рецензент перехода смотрит на control/candidate и data recovery. Рецензент решения следит, чтобы сильный глагол не вылез за evidence. Разделение ролей не создаёт бюрократию: оно не даёт одному «готово» заменить три разных вопроса.

Пределы модели и следующий шаг

Этот playbook не измеряет задержку, не знает фактические схемы, не моделирует конкурентные записи и не валидирует deployment. Он не предлагает процент rollout, способ репликации или protocol rollback. Даже source о Kubernetes не делает package Kubernetes migration plan. Ограничение честное: fixed literals учат сохранять связи между решением и evidence, но не заменяют discovery, rehearsal или инженерное согласование в реальном контексте.

Следующий безопасный шаг — добавить один новый fixed counterexample, например route с двумя records или recovery state, который не соответствует transition. Затем снова выполнить public export и проверить точный stop reason. Не расширять accepted result до разрешения, не придумывать реальные показатели и не достраивать скрытый inventory. Хороший migration plan растёт по наблюдаемым связям, а не по объёму диаграммы.

Проверяемые источники

  • Kubernetes Documentation: Deployments — версия: Kubernetes v1.33 versioned documentation snapshot, 23 April 2025. Использован только узкий факт: revision и rollback Deployment относятся к Pod template, поэтому они не являются доказательством обратимости данных. Граница: Не доказывает поведение конкретного кластера, rollout, data transition или rollback.
  • Google SRE Book: Addressing Cascading Failures — версия: Wayback immutable capture, 23 January 2025 16:42:19 UTC. Использована только идея положительной обратной связи у каскадного отказа как аргумент называть stop condition заранее. Граница: Не задаёт пороги, SLO, нагрузку или свойства учебного literal.
  • RFC 2119: Key words for use in RFCs to Indicate Requirement Levels — версия: RFC 2119, March 1997, immutable RFC text. Использовано определение требований MUST/MAY для различения проверяемого gate и необоснованного приказа среде. Граница: Не превращает synthetic правила в внешний стандарт миграции.