Пара 18: CD: версии, выпуск и откат
90 минут · 3 курс, ML.
Содержание и результат
Выпустить новую версию локального сервиса и безопасно вернуть предыдущую.
План занятия
0–10: контекст и исходная задача. 10–40: устройство и механизмы. 40–55: демонстрация команд. 55–80: лабораторная работа. 80–90: разбор результата и фиксация исправлений.
Практика выполняется в своей учебной папке и на localhost. Подготовка окружения описана в lab/README.md.
Delivery и deployment
Готовность к выпуску и автоматический выпуск — разные договорённости.
Continuous Delivery поддерживает состояние, которое можно выпустить после решения команды. Continuous Deployment автоматически выпускает прошедшие проверки изменения согласно правилам. На курсе делаем учебный ручной выпуск после CI. Пайплайн должен иметь явный артефакт и SHA: нельзя собирать неопределённый latest уже на сервере и считать это проверенной версией. Продвигаем один и тот же образ между средами, конфигурацию передаём отдельно. Production-развёртывание требует подходящих полномочий и проверок, но здесь все аварии происходят на ноутбуке.
Аналогия: партия принята контролем качества, но отправка покупателю — следующий этап.
Идентичность версии
Tag удобен человеку; digest задаёт конкретное содержимое образа.
Используем понятные теги v1 и v2 для обучения, фиксируем image ID или digest как доказательство. Tag может быть переназначен, latest не означает «проверено». В реальном ML-проекте отдельно фиксируются SHA кода и версия/хеш модели: смена модели может изменить ответы без смены кода. Для нашего JSON-артефакта ведём метку MODEL_VERSION и sha256 файла. Метка не доказывает правильность содержимого, поэтому вычисляем контрольную сумму. В журнале выпуска записываем исходную и целевую версии, проверку и план возврата.
Аналогия: название книги и конкретное издание с номером партии — разные идентификаторы.
Откат и данные
Предыдущий образ можно вернуть, но данные требуют совместимости.
Rollback возвращает прежнюю версию приложения или артефакта. Если новая версия необратимо изменила данные, старый код может не работать: план возврата должен учитывать это до выпуска. В курсе формат событий стабилен, поэтому демонстрационный откат не меняет том. Сначала проверяем healthz, затем типичный predict, неверный вход и журнал. Запущенный контейнер — промежуточное наблюдение, окончательное доказательство — ожидаемый пользовательский ответ. Когда ошибка затрагивает данные, backup и восстановление становятся отдельной операцией; это тема декабря.
Аналогия: вернуть старый кассовый аппарат легко, но формат новых чеков должен быть ему понятен.
Команды и наблюдения
Окружение: Ubuntu / Bash, lab.
bash ci/check.sh
docker build -t studypulse:v1 .
APP_IMAGE=studypulse:v1 MODEL_VERSION=v1 docker compose up -d --no-build
bash scripts/smoke.sh
APP_IMAGE=studypulse:v1 MODEL_VERSION=v2 docker compose up -d --no-build
bash scripts/smoke.sh
APP_IMAGE=studypulse:v1 MODEL_VERSION=v1 docker compose up -d --no-build
bash scripts/smoke.sh
Сначала показываем безопасную смену конфигурации на одном образе. Для настоящего изменения кода в лабораторной строим второй образ и фиксируем оба ID.
Ожидаемый результат: healthz показывает смену метки v1 → v2 → v1; данные в томе сохраняются.
Вариант для macOS
Вместо sha256sum используйте shasum -a 256. Release и rollback через Docker одинаковы. Не выдавайте локальный ARM64 image ID за доказательство доступности той же версии для AMD64-сервера.
shasum -a 256 models/model.json
docker image inspect studypulse:v1 --format "{{.Id}}"
bash scripts/smoke.sh
Практика: Мини-релиз с планом возврата
- Зафиксируйте commit, image ID и checksum models/model.json.
- Соберите отдельный v2 с небольшим проверяемым изменением в копии проекта; не подменяйте v1.
- Выпустите v2 локально, выполните smoke и проверьте события.
- Верните v1 без удаления тома; заполните release-report.md.
Результат: Два образа, отчёт о выпуске и проверенный откат.
Проверка: Возврат реально выполнен; image ID и артефакт записаны; данные не удалены.
Неисправность для разбора: latest изменился, и невозможно определить, что именно было выпущено.
Решение и диагностика
Вариант v2: измените коэффициент в отдельной копии на 0.1, обновите соответствующий контракт и тесты осознанно, соберите studypulse:v2. После выпуска ожидаемый score для hours=4 станет 0.4; стандартный smoke базового контракта поймает несовместимость. Верните APP_IMAGE=studypulse:v1 MODEL_VERSION=v1 и выполните базовый smoke: score снова 0.5. Если изменение нежелательно, тесты и контракт не переписывают ради зелёного статуса.
Основные выводы
- Нет, различается автоматизация последнего решения о выпуске.
- Новые данные или миграция могут быть несовместимы со старым кодом.
Самостоятельная работа
Сдать ноябрьский чекпоинт: Git-история, Dockerfile, Compose, CI и журнал проверенного отката.