CI/CD. Принципы непрерывной интеграции и доставки
Статья продолжает основы DevOps: там — зачем делить тест и прод; здесь — как именно код из Git превращается в выкат на стенды. Сквозная карта восьми этапов (планирование, код, сборка, тесты, релиз, деплой, эксплуатация, мониторинг) с примерами Jira, Gradle, Playwright, Argo CD и Prometheus — в жизненном цикле пайплайна. Если термины CI, CD, staging звучат абстрактно, сначала пролистайте блок с аналогией про "книгу" ниже, затем возвращайтесь к формальным определениям.
Связанные материалы: стратегии выката · жизненный цикл пайплайна · Git и ветки · настройка конвейеров · стек инструментов · GitHub Actions — CI/CD рецепты · система контроля версий · контейнеризация.
Play ITЗагрузка интерактивного демо…
CI. Непрерывная интеграция
Как работает CI
Непрерывная интеграция (CI) — практика, при которой изменения в общем репозитории регулярно сливаются в основную ветку и сразу проверяются автоматической сборкой и тестами. Цель — поймать поломку, пока автор ещё помнит, что менял, а не за неделю до релиза на сотнях чужих коммитов.
Представьте - каждый пишет свою главу книги дома, в своём блокноте. Через месяц вы решаете объединить работу, и "склеить" результаты вместе. И тут выясняется:
- Петя назвал героя "Васей", а Маша - "Василием";
- У Васи синие волосы в одной главе, а зеленые в другой;
- А Коля и вовсе не учёл одну из ключевых глав, которую писала Маша.
Вам нужно несколько дней всё переписывать, стыковать, ругаться. И вот, вы договорились:
- каждый раз, когда кто-то написал хотя бы абзац (или пару строчек кода), он сразу сохраняет результат в облачном хранилище;
- система будет автоматически проверять - не сломал ли Петин абзац Машину главу, не забыл ли Коля поставить точку, и вообще, всё ли склеивается гладко?
- если всё хорошо, то система принимает изменения. Если нет - кричит об ошибке.
Так и работает CI - когда вы несколько раз сливаете свой код с кодом коллег, а специальный бот проверяет автоматически, что ничего не сломалось (собирает проект, запускает тесты).
Какие-то системы используют стандартные решения, кто-то использует механизмы экспорта и импорта с проверкой на входе.
Разработчики обычно работают в своей среде, где создают и изменяют решения. Потом они публикуют изменения, и программа выполняет сборку с учётом общего результата. После успешного прохождения тестов, изменения сохраняются.
Технически CI запускается триггером — чаще всего git push или обновление pull request в ветку main, develop или feature/*. Система CI (Jenkins, GitLab CI, GitHub Actions, Azure Pipelines — см. обзор платформ и Azure Repos) клонирует репозиторий в чистое окружение и выполняет шаги по порядку:
- Сборка (build) — из исходников получают артефакт — JAR,
dist/, Docker-образ. Зависимости берут из lock-файла (package-lock.json,poetry.lock), чтобы сборка на CI совпадала с продом. - Статический анализ — линтеры (ESLint, Pylint) и сканеры (SonarQube, Bandit) ищут стиль, мёртвый код и типовые уязвимости без запуска приложения.
- Автотесты — unit (быстро, изолированно), integration (с БД или API в контейнере), при необходимости E2E (Playwright, Cypress) на тестовом стенде.
- Отчёты — coverage, время прогона, список упавших тестов; результат виден в PR и в почте/чате команды.
Если любой шаг красный — интеграция провалена: merge в main блокируют, автор чинит и пушит снова. Так CI превращает "у меня локально работает" в проверяемый факт для всей команды.
Живой пример — пайплайн "Вселенной IT"
В репозитории it-knowledge-base при push в main запускается .github/workflows/deploy.yml: checkout → Node 20 → npm ci → очистка кэша → npm run build (включая скрипты индексов) → публикация каталога build/ в ветку gh-pages → spirzen.ru. Диаграмма последовательности и разбор YAML — глава 2112, пошаговый кейс Pages — лаборатория. Скопировать и адаптировать workflow под свой проект — CI/CD рецепты.
Контекст CI/CD:
Состав npm run build (pre-scripts + Docusaurus) — на "О проекте" и в главе про GitHub Actions (полная flowchart после sequence).

Как организовать CI
Организация CI требует и инфраструктуры, и договорённостей в команде:
- Один главный репозиторий (или монорепо с понятными границами) и согласованная модель веток — Git Flow, GitHub Flow или trunk-based. Без этого "каждый пушет куда хочет" и CI не спасёт.
- Сервер или облачный CI с изолированными runner'ами: каждая сборка в чистом контейнере/ВМ, без "остатков" прошлого job.
- Воспроизводимая сборка — lock-файлы, версии SDK в Docker-образе,
Dockerfileв репозитории; иначе "на CI упало, у меня нет" будет нормой. - Минимальный, но обязательный набор тестов на критичные пути (оплата, авторизация, сохранение данных). Лучше 50 стабильных unit-тестов, чем ноль и надежда на ручную проверку.
- Частые маленькие коммиты — проще найти виновный коммит (
git bisect) и быстрее чинить красный пайплайн.
CI — это дисциплина: каждый merge в общую ветку трактуется как потенциальный релиз и обязан быть зелёным. Подробнее про этапы сборки и тестов в жизненном цикле пайплайна.
CD. Непрерывная доставка и непрерывное развёртывание
Как работает CD
Непрерывная доставка (Continuous Delivery) — это расширение практики CI, при котором система проверяет изменения и подготавливает их к развёртыванию в рабочую среду. Иными словами, после прохождения CI каждый успешный билд становится готовым к развёртыванию в production — в любой момент и с минимальными усилиями.
Непрерывное развёртывание (Continuous Deployment) — это дальнейшее развитие идеи — каждое изменение, успешно прошедшее CI и все необходимые проверки, автоматически развёртывается в production, без вмешательства человека.
Ребята научились писать книгу, она теперь в идеальном порядке. Но читатели её не видят, ведь она на диске у разработчиков. Поэтому мы создаём систему, которая позволяет в любой момент отправить книгу в типографию и быть уверенными, что её напечатают идеально. Но нажимаем на печать, только когда решает наш руководитель:
- разработчики дописали фичу;
- робот сам собирает приложение, проверяет тестами, прогоняет через проверки и выкатывает на внутренний сервер, где менеджер может потыкать и сказать "Ок";
- приложение упаковано, подписано, лежит "на блюдечке" в registry артефактов;
- чтобы оно попало к пользователям, нужно только нажатие кнопки (или команда "поехали!" в чате).
Это непрерывная доставка (Delivery). А Deployment - более жёсткий вариант. Здесь нет никакой кнопки опубликовать. Как только разработчик закончил код и робот проверил, что всё работает, приложение само, автоматически, улетает к пользователям. Закоммитил код - и через час фича у всех пользователей.
Таким образом, отличие между Delivery и Deployment заключается в наличии или отсутствии ручного подтверждения перед попаданием в production. Continuous Delivery предполагает, что развёртывание может быть выполнено вручную по решению команды; Continuous Deployment делает это решение автоматическим.
Процесс CD включает:
- Создание артефакта (Docker-образ, JAR, ZIP) с тегом по хешу коммита или SemVer (
v2.4.1). Один и тот же артефакт едет на staging и prod — пересборка на проде запрещена (см. immutable artifact). - Тестирование на staging — предпрод, близкий к production по версиям БД, балансировщикам и секретам (часто с обезличенными данными).
- Конфиг отдельно от кода — URL API, ключи, лимиты в переменных окружения, Vault или ConfigMap; в Git хранят только шаблоны, не пароли (забота о коде и данных).
- Плавный выкат — blue/green, canary, rolling, чтобы не ронять всех пользователей сразу.
- Мониторинг и откат — алерты по error rate и latency; при пороге — автоматический или ручной rollback на предыдущий тег образа.
Как организовать CD
Для CD нужна более зрелая инфраструктура и культура, чем для CI:
- Единый артефакт проходит все стадии без пересборки — иначе "работало на test" не гарантирует "то же на prod".
- Идемпотентные скрипты деплоя — повторный запуск не ломает систему (Ansible, Helm,
kubectl apply); см. IaC и оркестрацию. - Паритет сред — одинаковые версии ОС, runtime и зависимостей; отличаются в основном данные и масштаб.
- Проверки после выката — HTTP health (
/healthz), smoke-тест критичных API, сравнение метрик с baseline (наблюдаемость). - Безопасность — секреты в Vault, деплой в prod только через approval, аудит "кто нажал кнопку" (gates).
Ключевое правило CD — узкое место — всё, что делается только руками (копирование jar, правка nginx на сервере). Доверие к автоматике растёт из стабильных зелёных пайплайнов и прозрачных логов, а не из "у нас и так всё работает".
Среды разработки и эксплуатации
Эффективная реализация CI/CD невозможна без чёткого разграничения и управления средами — изолированными экземплярами системы, предназначенными для разных целей в жизненном цикле разработки.
Локальная разработка
Каждый разработчик работает на своей машине — IDE, локальный Git, иногда docker compose up для БД и брокера. Цель — быстро проверить логику до push. Локально удобно гонять unit-тесты и линтер; полный продовый контур (Kafka, пять микросервисов, реальный платёжный шлюз) обычно не поднимают — для этого есть общий test/staging. Поэтому фраза "у меня на ноутбуке всё ок" не отменяет красный CI. Шаблоны compose.yaml (Postgres, Redis, app+db) с разбором — Docker Compose — готовые стеки; образ приложения для build: . — Dockerfile — 10 типовых образов.
Тестовая среда (test/staging)
Тестовая среда — первый общий стенд команды: сюда CI выкатывает сборку после merge. Проверяется взаимодействие сервисов, миграции БД, интеграции. Она может быть упрощённой копией production и используется для:
- Запуска интеграционных и end-to-end тестов;
- Проверки совместимости между сервисами;
- Валидации миграций баз данных.
Важно, чтобы тестовая среда была контролируемой: данные в ней не должны быть критичными, но должны отражать типичные сценарии использования.
Предпродакшен (pre-production)
Предпродакшен — это точное зеркало production, включая конфигурации, версии зависимостей, топологию сети и объёмы данных (или их анонимизированные копии). Его цель — финальная валидация перед выходом в продакшен. Здесь запускаются:
- Performance-тесты;
- Безопасность-сканирования;
- Business-валидация (QA, заказчик, аналитики).
Если система работает корректно в предпроде, она считается готовой к развёртыванию в production.
Продакшен (production)
Продакшен — это реальная эксплуатационная среда, в которой система обслуживает конечных пользователей. Здесь важнейшими критериями становятся:
- Доступность (availability);
- Надёжность (reliability);
- Восстанавливаемость (recoverability).
Любое вмешательство в продакшен должно быть минимальным, контролируемым и обратимым.
Варианты развёртывания
Развёртывание программного обеспечения — это процесс установки, конфигурации и активации системы в целевой среде. Выбор архитектуры развёртывания напрямую влияет на сложность реализации CI/CD, скорость доставки и надёжность эксплуатации.
Общая картина уровней (bare metal, гипервизор и ВМ, контейнеры, контейнеры в облачных ВМ) — четыре модели развёртывания.
Физические серверы с прямым доступом
Исторически первым способом размещения ПО были выделенные физические серверы, на которых вручную устанавливались операционная система, зависимости и само приложение. Управление осуществлялось через SSH или консольные сессии.
Преимущества
- Полный контроль над "железом" и сетью без гипервизора.
- Минимальные накладные расходы на виртуализацию.
Недостатки
- Сложно быстро добавить десяток одинаковых серверов под пик нагрузки.
- Слабая воспроизводимость: ручная настройка ОС и пакетов расходится между машинами.
- Длительное время развёртывания;
- Сложность автоматизации без использования систем конфигурации (Ansible, Puppet, Chef).
В контексте CI/CD физические серверы требуют тщательной автоматизации доставки кода и настройки среды. Без этого практики непрерывной доставки становятся нестабильными и подвержены человеческим ошибкам.
Виртуальные машины (ВМ)
Виртуализация позволила изолировать приложения на уровне операционной системы, создавая воспроизводимые образы с предустановленными зависимостями. Каждое приложение может работать в собственной виртуальной машине, что упрощает управление версиями и изоляцию.
Преимущества:
- Полная изоляция окружения;
- Возможность клонирования и быстрого восстановления;
- Поддержка мультиплатформенности (Linux/Windows на одном хосте).
Недостатки:
- Значительные накладные расходы на память и CPU;
- Длительное время запуска по сравнению с контейнерами;
- Сложность оркестрации при большом числе ВМ.
В CI/CD-конвейерах виртуальные машины часто используются как тестовые или staging-среды, однако в production-развёртываниях их постепенно вытесняют более лёгкие и гибкие решения.
Контейнеризация
Контейнеризация — это парадигма, при которой приложение и все его зависимости упаковываются в изолированный, переносимый образ, выполняемый в общей ОС хоста с использованием механизмов ядра (cgroups, namespaces). Наиболее распространённая реализация — Docker.
Контейнеры стали де-факто стандартом в CI/CD благодаря следующим свойствам:
- Иммутабельность: образ создаётся один раз и используется на всех стадиях;
- Идемпотентность: запуск одного и того же образа всегда даёт одинаковый результат;
- Лёгкость: контейнеры запускаются за секунды и потребляют минимальные ресурсы;
- Переносимость — один и тот же образ может работать локально, в облаке, на bare metal.
В сочетании с системами оркестрации (Kubernetes, Docker Swarm) контейнеризация позволяет реализовать масштабируемые, самовосстанавливающиеся и легко управляемые платформы. Именно с контейнерами наиболее органично сочетаются практики CI/CD:
- После прохождения CI создаётся Docker-образ с уникальным тегом (например, по хешу коммита);
- Образ помещается в registry (Docker Hub, Harbor, ECR и т.п.);
- На staging или production система оркестрации подтягивает новый образ и запускает его в соответствии с политикой развёртывания.
Такой подход обеспечивает единый артефакт, проходящий все этапы без пересборки — исчезает "эффект дивана": "в тесте собрали с одними флагами, на проде пересобрали с другими".
Стратегии безопасного выката — статья про blue/green, canary и feature flags.
Пошаговый пайплайн от планирования до мониторинга — жизненный цикл.
Gates, секреты и IaC в CI — особенности эксплуатации конвейеров.
Откат и вывод из эксплуатации
Несмотря на все меры предосторожности, не все изменения оказываются стабильными в production. Поэтому CI/CD-конвейеры должны включать механизмы отката и процедуры вывода из эксплуатации.
Откат (rollback)
Откат — это процесс возвращения системы к предыдущему известному рабочему состоянию. Он может быть:
- Автоматическим — при срабатывании триггеров мониторинга (например, рост ошибок 5xx, падение метрики liveness);
- Ручным: по решению инженера или дежурного.
Для эффективного отката необходимы:
- Хранение предыдущих версий артефактов (образов, пакетов);
- Идемпотентные и обратимые миграции баз данных (или стратегия "только вперёд" с двойной совместимостью);
- Версионирование конфигураций (через GitOps, например);
- Минимальное время восстановления (MTTR).
Важно: откат не всегда возможен. Например, при изменении структуры данных без поддержки обратной совместимости. Поэтому в зрелых системах часто применяются стратегии развёртывания без отката, такие как feature toggles и постепенное включение функционала.
Вывод из эксплуатации (decommissioning)
Вывод из эксплуатации — это процесс полного или частичного прекращения работы компонента системы. Это может быть связано с:
- Заменой сервиса на новый;
- Устареванием функционала;
- Снижением нагрузки до нуля.
Процедура включает:
- Уведомление зависимых систем;
- Миграция или архивирование данных;
- Удаление маршрутов и DNS-записей;
- Остановку и удаление контейнеров/виртуальных машин;
- Документирование и аудит.
В CI/CD-контексте важно, чтобы процесс вывода тоже был автоматизирован и проверяем. Например, в GitOps-подходе удаление манифеста из репозитория приводит к автоматическому уничтожению ресурса в кластере.