Перейти к основному содержимому

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-pagesspirzen.ru. Диаграмма последовательности и разбор YAML — глава 2112, пошаговый кейс Pages — лаборатория. Скопировать и адаптировать workflow под свой проект — CI/CD рецепты.

Контекст CI/CD:

Состав npm run build (pre-scripts + Docusaurus) — на "О проекте" и в главе про GitHub Actions (полная flowchart после sequence).

Архитектура "Вселенная IT" — CI/CD и деплой


Как организовать 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:

  1. После прохождения CI создаётся Docker-образ с уникальным тегом (например, по хешу коммита);
  2. Образ помещается в registry (Docker Hub, Harbor, ECR и т.п.);
  3. На 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-подходе удаление манифеста из репозитория приводит к автоматическому уничтожению ресурса в кластере.