Куда девается ваша сборка? Недостающее звено между кодом и продакшеном
Вы только что собрали приложение. Сборка прошла успешно, тесты пройдены, и у вас есть блестящий новый артефакт, лежащий в папке на вашем ноутбуке. Что дальше?
Если вы похожи на большинство команд, настраивающих свой первый пайплайн, следующий шаг кажется очевидным: развернуть его. Но есть проблема, которая прячется на виду. Этот артефакт на вашем ноутбуке бесполезен для продакшен-сервера, находящегося в дата-центре или облачном регионе. Он не может залезть в вашу локальную папку и забрать файл. Даже если сборка выполнялась на выделенной CI-машине, целевой сервер развертывания все равно не может получить доступ к файлам, находящимся на локальном диске этой машины.
Именно здесь большинство проектов пайплайнов впервые сталкиваются с реальной проблемой. Вам нужно место, куда можно поместить артефакт, доступное как для процесса сборки, так и для целевого сервера развертывания.
Проблема общего хранилища
Подумайте о том, что происходит, когда вы заканчиваете готовить еду для вечеринки. Вы не оставляете еду на кухне и не ждете, что гости зайдут и сами возьмут ее с плиты. Вы ставите еду на стол, где каждый может до нее дотянуться.
С артефактами та же история. Процесс сборки создает артефакт. Процесс развертывания должен его получить. Эти два процесса могут выполняться на разных машинах, в разных сетях, в разное время. Им нужно общее расположение, доступное обоим по сети.
Это общее расположение называется реестром артефактов (artifact registry) или репозиторием артефактов. Его задача проста: хранить артефакты и предоставлять способ их получения. Каждый раз, когда сборка завершается, она отправляет артефакт в этот реестр. Позже, когда начинается развертывание, целевой сервер забирает артефакт из реестра и запускает его.
Следующая диаграмма показывает базовый поток:
Вот как отправить артефакт после сборки и забрать его на целевом сервере развертывания:
# На сборочной машине: отправка артефакта в реестр
curl -X POST \
-F "file=@myapp-v1.2.3.jar" \
https://registry.example.com/upload
# На целевом сервере развертывания: загрузка артефакта из реестра
curl -O https://registry.example.com/artifacts/myapp-v1.2.3.jar
Больше, чем просто файловый сервер
Реестр делает больше, чем просто хранит файлы. Он также хранит метаданные о каждом артефакте: номер версии, временную метку создания и часто хеш Git-коммита, который его породил. Эти метаданные становятся критически важными, когда что-то идет не так в продакшене.
Представьте, что вы развернули версию 2.3.1, и пользователи начали видеть ошибки. Вам нужно точно знать, какие изменения кода вошли в этот артефакт. Без метаданных, связывающих артефакт с его исходным коммитом, вы гадаете. С ними вы можете проверить diff, определить проблему и решить, откатываться или исправлять вперед.
Некоторые реестры также поддерживают метки (labels) или теги. Вы можете пометить артефакт как "staging-validated" после прохождения интеграционных тестов или "production-ready" после ручного утверждения. Эти теги помогают автоматизировать, какие артефакты развертываются в каком окружении.
Ловушка связности
Вот ошибка, которая подстерегает многие команды: они настраивают реестр в облаке, но их продакшен-серверы работают в частной сети, которая не имеет доступа к публичному интернету. Сборка успешно отправляет артефакты, но когда развертывание пытается их забрать, оно падает с таймаутом соединения.
Реестр должен быть доступен с каждого сервера, которому нужно выполнять развертывание. Если ваше продакшен-окружение изолировано, ваш реестр должен находиться внутри той же сети, или вам нужен механизм синхронизации артефактов через сетевые границы. Некоторые команды запускают локальный прокси или зеркало, которое кэширует артефакты из центрального реестра. Другие используют реестр, поддерживающий конечные точки частной сети.
Это звучит очевидно, когда вы это читаете, но это легко упустить, когда вы сосредоточены на том, чтобы заставить пайплайн работать от начала до конца. Проверьте связность до того, как строить весь процесс развертывания вокруг реестра, до которого ваши серверы не могут дотянуться.
Важность неизменяемости
Хороший реестр предотвращает изменение артефактов после их сохранения. Это свойство называется неизменяемостью (immutability). Это означает, что артефакт, сохраненный сегодня, будет идентичен артефакту, который вы получите через шесть месяцев.
Почему это важно? Без неизменяемости вы не можете доверять тому, что развертываете. Кто-то может изменить артефакт после того, как он прошел тестирование. Ошибка, обнаруженная в стейджинге, может снова появиться в продакшене, потому что артефакт изменился между окружениями. Отладка превращается в кошмар, потому что вы никогда не уверены, соответствует ли артефакт, работающий в продакшене, тому, что тестировался.
Неизменяемость обеспечивает чистый рабочий процесс: каждое изменение порождает новый артефакт с новой версией. Нет "обновления на месте" для артефактов. Если нужно что-то исправить, вы пересобираете и создаете новую версию. Эта дисциплина делает развертывания предсказуемыми, а откаты — простыми.
Разделение сборки и развертывания
С реестром сборка и развертывание становятся двумя отдельными процессами, которые могут выполняться независимо. Сборка завершается, отправляет артефакт и движется дальше. Развертывание может произойти через минуты, часы или дни. Артефакт безопасно хранится в реестре, ожидая, когда его заберут.
Это разделение — мощная вещь. Вы можете собрать и протестировать артефакт утром, дать его на ревью старшему инженеру днем и развернуть в продакшене ночью, когда трафик низкий. Каждый шаг происходит по своему расписанию, но все они ссылаются на один и тот же неизменяемый артефакт.
Это также означает, что вы можете пересобрать и повторно развернуть один и тот же артефакт в нескольких окружениях. Артефакт, прошедший тесты в стейджинге, — это тот же самый артефакт, который идет в продакшен. Никакой перекомпиляции, никаких сборок под конкретное окружение, никаких сюрпризов в стиле "на моей машине работало".
Краткий практический чек-лист
При настройке реестра артефактов проверьте следующие пункты:
- Доступность: Может ли каждый сервер, которому нужно выполнять развертывание, достичь реестра по сети?
- Неизменяемость: Предотвращает ли реестр изменение сохраненных артефактов?
- Метаданные: Содержит ли каждый артефакт информацию о версии, временной метке и исходном коммите?
- Хранение: Как долго вы храните старые артефакты? Есть ли политика очистки?
- Аутентификация: Кто может отправлять артефакты? Кто может их забирать? Ротируются ли учетные данные?
Вывод
Результат вашей сборки нуждается в доме, доступном как для процесса сборки, так и для целевых серверов развертывания. Реестр артефактов предоставляет это общее хранилище, хранит метаданные для отслеживаемости, обеспечивает неизменяемость, чтобы вы могли доверять тому, что развертываете, и разделяет сборку и развертывание, чтобы каждый шаг мог выполняться по своему расписанию. Без него ваш пайплайн — это просто сборка, которая заканчивается файлом, лежащим на машине, до которой никто не может добраться.