CI/CD. Принципы непрерывной интеграции и доставки
CI. Непрерывная интеграция
Как работает CI
Непрерывная интеграция — это практика разработки программного обеспечения, при которой изменения, вносимые разработчиками в общий репозиторий исходного кода, автоматически и регулярно объединяются (интегрируются) в основную ветвь кодовой базы. Интеграция сопровождается автоматической сборкой системы и выполнением набора тестов, предназначенных для проверки корректности внесённых изменений и сохранения работоспособности всей системы.
Представьте - каждый пишет свою главу книги дома, в своём блокноте. Через месяц вы решаете объединить работу, и "склеить" результаты вместе. И тут выясняется:
- Петя назвал героя "Васей", а Маша - "Василием";
- У Васи синие волосы в одной главе, а зеленые в другой;
- А Коля и вовсе не учёл одну из ключевых глав, которую писала Маша.
Вам нужно несколько дней всё переписывать, стыковать, ругаться. И вот, вы договорились:
- каждый раз, когда кто-то написал хотя бы абзац (или пару строчек кода), он сразу сохраняет результат в облачном хранилище;
- система будет автоматически проверять - не сломал ли Петин абзац Машину главу, не забыл ли Коля поставить точку, и вообще, всё ли склеивается гладко?
- если всё хорошо, то система принимает изменения. Если нет - кричит об ошибке.
Так и работает CI - когда вы несколько раз сливаете свой код с кодом коллег, а специальный бот проверяет автоматически, что ничего не сломалось (собирает проект, запускает тесты).
Какие-то системы используют стандартные решения, кто-то использует механизмы экспорта и импорта с проверкой на входе.
Разработчики обычно работают в своей среде, где создают и изменяют решения. Потом они публикуют изменения, и программа выполняет сборку с учётом общего результата. После успешного прохождения тестов, изменения сохраняются.
Технически процесс CI запускается триггером — чаще всего это push в определённую ветку репозитория (например, в main, develop или feature-ветку). Система CI (например, Jenkins, GitLab CI, GitHub Actions, Azure DevOps) перехватывает этот триггер, клонирует репозиторий, устанавливает необходимые зависимости, компилирует код (если требуется), и последовательно выполняет:
- Сборку (build): преобразование исходного кода в исполняемый артефакт;
- Статический анализ кода: проверка соответствия кода стандартам, поиск потенциальных уязвимостей или антишаблонов;
- Запуск автоматизированных тестов: unit-, интеграционные, иногда end-to-end тесты;
- Формирование отчётов: о покрытии кода тестами, времени выполнения, количестве найденных ошибок.
Если все этапы завершены успешно, интеграция считается пройденной. В противном случае — система CI сигнализирует о сбое и часто блокирует дальнейшее продвижение изменений (например, не позволяет смёрджить pull request).
Как организовать CI
Организация CI требует как инфраструктурных, так и процессных решений:
- Централизованный репозиторий исходного кода с чёткой политикой ветвления;
- Система CI, способная выполнять сборку и тестирование в изолированной среде;
- Единая система зависимостей и воспроизводимая сборка (с помощью lock-файлов, Dockerfile, Makefile и т.п.);
- Минимальный набор автоматизированных тестов, покрывающих критические участки логики;
- Культура частых и небольших коммитов — чтобы уменьшить риск конфликтов и упростить отладку неудачных сборок.
Важно понимать, что CI — это не просто «скрипт, который запускается после коммита». Это дисциплина, в рамках которой каждый коммит рассматривается как кандидат на доставку в production, и, следовательно, должен проходить строгую проверку.
CD. Непрерывная доставка и непрерывное развёртывание
Как работает CD
Непрерывная доставка (Continuous Delivery) — это расширение практики CI, при котором система проверяет изменения и подготавливает их к развёртыванию в рабочую среду. Иными словами, после прохождения CI каждый успешный билд становится готовым к развёртыванию в production — в любой момент и с минимальными усилиями.
Непрерывное развёртывание (Continuous Deployment) — это дальнейшее развитие идеи: каждое изменение, успешно прошедшее CI и все необходимые проверки, автоматически развёртывается в production, без вмешательства человека.
Ребята научились писать книгу, она теперь в идеальном порядке. Но читатели её не видят, ведь она на диске у разработчиков. Поэтому мы создаём систему, которая позволяет в любой момент отправить книгу в типографию и быть уверенными, что её напечатают идеально. Но нажимаем на печать, только когда решает наш руководитель:
- разработчики дописали фичу;
- робот сам собирает приложение, проверяет тестами, прогоняет через проверки, и выкатывает на специальный внутренний сервер, где менеджер может потыкать, проверить и сказать "Ок";
- приложение упаковано, подписано, лежит "на блюдечке";
- чтобы оно попало к пользователям, нужно только нажатие кнопки (или сказать "поехали!").
Это непрерывная доставка (Delivery). А Deployment - более жёсткий вариант. Здесь нет никакой кнопки опубликовать. Как только разработчик закончил код и робот проверил, что всё работает, приложение само, автоматически, улетает к пользователям. Закоммитил код - и через час фича у всех пользователей.
Таким образом, отличие между Delivery и Deployment заключается в наличии или отсутствии ручного подтверждения перед попаданием в production. Continuous Delivery предполагает, что развёртывание может быть выполнено вручную по решению команды; Continuous Deployment делает это решение автоматическим.
Процесс CD включает:
- Создание артефакта (например, Docker-образа, JAR-файла, ZIP-архива), идентифицируемого по хешу коммита;
- Тестирование на staging-среде (предпродакшене), максимально приближённой к production;
- Управление конфигурациями и переменными окружения отдельно от кода;
- Плавное развёртывание (blue-green, canary, rolling update) для минимизации простоя и рисков;
- Механизмы мониторинга и автоматического отката при обнаружении сбоев.
Как организовать CD
Для организации CD требуется более зрелая инфраструктура и культура, чем для CI:
- Единый артефакт, проходящий все стадии без пересборки;
- Идемпотентные скрипты развёртывания, не зависящие от состояния целевой системы;
- Среды, идентичные друг другу по конфигурации (с возможным различием только в данных);
- Автоматизированные проверки качества развёртывания: smoke-тесты, health-check, метрики доступности;
- Политики безопасности: управление секретами, ограничение прав на развёртывание, аудит изменений.
Ключевое правило CD: если что-то нельзя автоматизировать — это узкое место, которое необходимо устранить. CD требует доверия к автоматике, а доверие строится на стабильности и прозрачности.
Среды разработки и эксплуатации
Эффективная реализация CI/CD невозможна без чёткого разграничения и управления средами — изолированными экземплярами системы, предназначенными для разных целей в жизненном цикле разработки.
Локальная разработка
Каждый разработчик работает на собственной машине, используя локально установленные инструменты или контейнеры. Цель — написать и протестировать небольшой функционал в условиях, приближённых к реальным. Однако локальная среда по определению неполна: она не включает зависимости, характерные для распределённой системы (например, очереди сообщений, внешние API, балансировщики).
Тестовая среда (test/staging)
Тестовая среда — это первый интеграционный уровень, где проверяется взаимодействие компонентов системы. Она может быть частично или полностью клонированной из production и используется для:
- Запуска интеграционных и end-to-end тестов;
- Проверки совместимости между сервисами;
- Валидации миграций баз данных.
Важно, чтобы тестовая среда была контролируемой: данные в ней не должны быть критичными, но должны отражать типичные сценарии использования.
Предпродакшен (pre-production)
Предпродакшен — это точное зеркало production, включая конфигурации, версии зависимостей, топологию сети и объёмы данных (или их анонимизированные копии). Его цель — финальная валидация перед выходом в продакшен. Здесь запускаются:
- Performance-тесты;
- Безопасность-сканирования;
- Business-валидация (QA, заказчик, аналитики).
Если система работает корректно в предпроде, она считается готовой к развёртыванию в production.
Продакшен (production)
Продакшен — это реальная эксплуатационная среда, в которой система обслуживает конечных пользователей. Здесь важнейшими критериями становятся:
- Доступность (availability);
- Надёжность (reliability);
- Восстанавливаемость (recoverability).
Любое вмешательство в продакшен должно быть минимальным, контролируемым и обратимым.
Варианты развёртывания
Развёртывание программного обеспечения — это процесс установки, конфигурации и активации системы в целевой среде. Выбор архитектуры развёртывания напрямую влияет на сложность реализации CI/CD, скорость доставки и надёжность эксплуатации.
Физические серверы с прямым доступом
Исторически первым способом размещения ПО были выделенные физические серверы, на которых вручную устанавливались операционная система, зависимости и само приложение. Управление осуществлялось через 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 система оркестрации подтягивает новый образ и запускает его в соответствии с политикой развёртывания.
Такой подход обеспечивает единый артефакт, проходящий все этапы без пересборки, что исключает так называемый «эффект дивана» («работает в тесте — не работает в проде»).
Откат и вывод из эксплуатации
Несмотря на все меры предосторожности, не все изменения оказываются стабильными в production. Поэтому CI/CD-конвейеры должны включать механизмы отката и процедуры вывода из эксплуатации.
Откат (rollback)
Откат — это процесс возвращения системы к предыдущему известному рабочему состоянию. Он может быть:
- Автоматическим: при срабатывании триггеров мониторинга (например, рост ошибок 5xx, падение метрики liveness);
- Ручным: по решению инженера или дежурного.
Для эффективного отката необходимы:
- Хранение предыдущих версий артефактов (образов, пакетов);
- Идемпотентные и обратимые миграции баз данных (или стратегия «только вперёд» с двойной совместимостью);
- Версионирование конфигураций (через GitOps, например);
- Минимальное время восстановления (MTTR).
Важно: откат не всегда возможен. Например, при изменении структуры данных без поддержки обратной совместимости. Поэтому в зрелых системах часто применяются стратегии развёртывания без отката, такие как feature toggles и постепенное включение функционала.
Вывод из эксплуатации (decommissioning)
Вывод из эксплуатации — это процесс полного или частичного прекращения работы компонента системы. Это может быть связано с:
- Заменой сервиса на новый;
- Устареванием функционала;
- Снижением нагрузки до нуля.
Процедура включает:
- Уведомление зависимых систем;
- Миграция или архивирование данных;
- Удаление маршрутов и DNS-записей;
- Остановку и удаление контейнеров/виртуальных машин;
- Документирование и аудит.
В CI/CD-контексте важно, чтобы процесс вывода тоже был автоматизирован и проверяем. Например, в GitOps-подходе удаление манифеста из репозитория приводит к автоматическому уничтожению ресурса в кластере.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Также DevOps практикует ещё и встраивание тестировщиков в процесс с самого начала, когда тесты пишутся параллельно с кодом, что обеспечивает тестирование не в конце, а на каждом этапе, а также… Выбор и применение стратегии развертывания — это не однократное решение, а непрерывный процесс адаптации. По мере роста системы, увеличения пользовательской базы и усложнения архитектуры подходы к… Таким образом, Git становится точкой входа в автоматизированный процесс доставки, а не просто хранилищем. Каждый коммит — это потенциальный шаг к новой версии продукта. В инструментах вроде GitHub Actions или Azure Pipelines такие условия реализуются через environment approvals и deployment gates. Это не бюрократия — это явное разделение зон ответственности и… Пайплайн - это последовательность этапов или процессов, через которые проходит задача. Azure Repos — это модуль Azure DevOps Services (облачная версия) или Azure DevOps Server (локальная установка, ранее известная как Team Foundation Server, TFS). Это означает, что доступ к… Классическое решение для анализа логов — ELK-стек — Elasticsearch — распределённая поисковая система, оптимизированная для полнотекстового поиска и агрегаций, Logstash — конвейер обработки событий —… Для системного администратора отказ — это сбой в работе системы, требующий немедленного вмешательства. Инфраструктура рассматривается как детерминированная машина — при одинаковых входных условиях… Автоматизация представляет собой систематическое применение программных и аппаратных средств для выполнения задач без или с минимальным участием человека. Логирование представляет собой процесс записи структурированных или полуструктурированных событий, происходящих в программном обеспечении, операционной системе или инфраструктуре. В отличие от… Terraform — это программа, которая позволяет описать всю вашу инфраструктуру в текстовых файлах, а потом одной командой создать её в облаке или локально. В Pulumi всё, что создаётся в облаке, является ресурсом. Ресурс — это объект, представляющий сущность в целевой системе — виртуальная машина, база данных, сетевая группа безопасности, DNS-запись и…Основы DevOps
Стратегии развертывания
Использование Git и GitFlow в DevOps-процессах
Особенности настройки и эксплуатации CI/CD-конвейеров
Жизненный цикл пайплайна CI/CD
Azure Repos и Team Foundation Server (TFS)
Инструменты автоматизации и оркестрации
Роль DevOps-инженера и отличия от системного администратора
Автоматизация сборки, тестирования и развёртывания
Логирование, мониторинг и наблюдаемость систем
Terraform
Pulumi