Одна сборка, продвижение по digest: пайплайн поставки с откатом
Эталонный путь поставки, где артефакт, проверенный в staging, — ровно тот же, что в продакшене, а откат — это повторный деплой предыдущего digest.
Примеры обобщённые и иллюстративные. Они не взяты из среды какого-либо клиента: подстройте пороги и параметры под свою систему.
Проблема пересборки под каждое окружение
Пайплайны, которые пересобирают приложение для каждого окружения, тестируют один артефакт, а выкатывают другой. Зависимости разрешаются иначе, базовый образ меняется, флаг сборки отличается — и версия в продакшене нигде не тестировалась. Собирайте один раз, дайте артефакту неизменяемый идентификатор и продвигайте именно его.
Эталонный путь
Обобщённый путь от коммита до продакшена. Каждый этап либо передаёт тот же артефакт дальше, либо останавливает его.
- 01КоммитPull request с ревью и обязательными проверками.
- 02СборкаОдна сборка на коммит; образ публикуется, его digest фиксируется.
- 03ПроверкаТесты, сканирование зависимостей и образа, подпись.
- 04StagingДеплой digest; smoke- и интеграционные тесты.
- 05ПродакшенТот же digest, постепенная выкатка.
- 06НаблюдениеБюджет ошибок и алерты решают: продолжать или откатывать.
Digest, а не теги
Теги вроде latest или v2 — изменяемые ярлыки; digest (sha256:…) — это хеш содержимого образа. Манифесты деплоя должны ссылаться на digest, а пайплайн продвигает окружение, меняя это единственное значение, — в идеале коммитом в репозиторий деплоя, чтобы каждый релиз был проверенным и обратимым изменением.
# build once and record the digest
docker buildx build --push --metadata-file meta.json \
-t registry.example.com/api:"$GIT_SHA" .
DIGEST=$(jq -r '."containerimage.digest"' meta.json)
# promote: every environment receives the same digest
kustomize edit set image api=registry.example.com/api@"$DIGEST"
Изменения базы данных: расширить, затем сузить
Откатить код легко, только если схема по-прежнему подходит предыдущей версии. Разбейте несовместимые миграции на шаги, каждый из которых совместим с работающим кодом: добавьте новую колонку или таблицу, выкатите код, который пишет в обе, заполните данные, переключите чтение и лишь в одном из следующих релизов удалите старую структуру.
Постепенная поставка и откат
- Сначала выкатывайте на часть трафика или реплик и сравнивайте долю ошибок и задержку с текущей версией.
- Привяжите решение к SLO: высокий burn rate во время выкатки автоматически останавливает продвижение.
- Откат — это повторный деплой предыдущего digest по тому же, уже проверенному пути, а не хотфикс, написанный под давлением.
- Держите конфигурацию и секреты вне образа, чтобы один и тот же артефакт работал во всех окружениях.