Как разделял элементы CI/CD в Jenkins
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Отличный вопрос, который напрямую касается философии построения надежных и эффективных конвейеров в Jenkins. Разделение CI (Continuous Integration) и CD (Continuous Delivery/Deployment) — это ключевая практика, которая повышает стабильность, безопасность и управляемость процесса. В Jenkins я реализовывал это разделение несколькими фундаментальными способами, комбинируя их в зависимости от зрелости команды и требований проекта.
1. Основной принцип: Разделение на стадии (Stages) внутри одного Pipeline (Jenkinsfile)
Это самый распространенный и базовый подход. Мы явно разделяем этапы CI и CD в декларативном или скриптовом Pipeline с помощью директив stage. CI-стадии выполняются автоматически, CD-стадии — часто с мануальным одобрением.
pipeline {
agent any
stages {
// ========== CI БЛОК ==========
stage('Checkout') {
steps { git '...' }
}
stage('Build & Unit Test') {
steps { sh 'mvn clean package' }
}
stage('Static Analysis (SonarQube)') {
steps { sh 'mvn sonar:sonar' }
}
stage('Build Docker Image') {
steps { sh 'docker build -t myapp:${BUILD_NUMBER} .' }
}
stage('Push to Registry') {
steps { sh 'docker push myapp:${BUILD_NUMBER}' }
}
// ========== ТОЧКА РАЗДЕЛЕНИЯ CI/CD ==========
// Часто здесь артефакт (образ, пакет) уже сохранен в реестре.
// ========== CD БЛОК ==========
// Эта стадия требует ручного подтверждения (input).
stage('Deploy to Staging') {
input {
message "Развернуть билд ${BUILD_NUMBER} в Staging?"
}
steps {
sh "kubectl set image deployment/myapp myapp=myapp:${BUILD_NUMBER} -n staging"
}
}
stage('Integration Tests (on Staging)') {
steps { sh 'run-integration-tests.sh' }
}
stage('Deploy to Production') {
input {
message "Все тесты пройдены. Развернуть в Production?"
}
steps {
sh "kubectl set image deployment/myapp myapp=myapp:${BUILD_NUMBER} -n production"
// Или использовать Helm, Ansible, Terraform
}
}
}
}
Ключевой момент: Здесь разделение логическое и организационное. Все выполняется в рамках одного задания Jenkins, но ручной input выступает четким барьером между интеграцией и доставкой.
2. Архитектурное разделение: Триггеринг отдельного CD-Pipeline
Более продвинутый и чистый подход. CI-Pipeline заканчивается созданием и публикацией неизменяемого артефакта (например, Docker-образа с тегом) и его промоутом (отметкой как готового к развертыванию). Затем он триггерит или создает задание для отдельного CD-Pipeline.
Как это работает:
- CI-задание (Jenkinsfile.ci): Собирает, тестирует, создает образ
myapp:1.2.3-b123, запускает уязвимости. В конце, если все успешно, он помечает этот конкретный образ как "релизный" (например, делаетdocker tag myapp:1.2.3-b123 myapp:1.2.3-stableи пушит) или записывает метаданные в средство управления артефактами (Nexus) или просто триггерит CD-задание, передавая ему точный тег образа. - CD-задание (Jenkinsfile.cd): Это отдельный Pipeline. Он получает на вход только тег стабильного образа. Его единственная ответственность — развертывание этого конкретного артефакта в различные среды. Он не содержит шагов сборки или тестирования.
Преимущества:
- Повторяемость: Можно запускать развертывание одного и того же артефакта многократно (например, для отката).
- Безопасность: CD-заданию могут быть выданы отдельные, более широкие учетные данные для доступа к production-средам, в то время как CI-задание работает с минимальными привилегиями.
- Гибкость: Можно настроить различные CD-конвейеры для разных сред или типов развертывания (canary, blue-green), все из одной точки входа — стабильного артефакта.
3. Использование "Промоута" или "Релизных" шагов с внешними системами
Иногда само развертывание выносится за пределы Jenkins (в специализированные инструменты вроде Spinnaker, ArgoCD, Flux). Тогда роль Jenkins сводится к CI и промоуту артефакта в цепочке поставок.
- Jenkins создает образ и помещает его в реестр как
myapp:1.2.3-candidate. - После прохождения всех этапов CI Jenkins обновляет конфигурацию для инструмента CD (например, меняет образ в манифесте Kubernetes в Git-репозитории "гитопс" с
...-candidateна...-stableили создает Pull Request). - Инструмент GitOps (ArgoCD) автоматически обнаруживает изменение в репозитории и выполняет синхронизацию, разворачивая новый образ в кластере.
В этом случае разделение абсолютное: Jenkins — это CI-движок, а CD осуществляется другим, более подходящим для этой задачи инструментом. Jenkins лишь "проталкивает" артефакт по конвейеру.
4. Организация через Folders и Shared Libraries
Для управления множеством проектов я разделял CI и CD на уровне организации Jenkins:
- Папка
ci-pipelines: Содержит задания, отвечающие только за сборку, тестирование и создание артефактов. - Папка
cd-pipelines: Содержит задания, отвечающие только за развертывание. Они используют Shared Libraries — общие библиотеки кода на Groovy, где вынесена вся логика развертывания (вызовы kubectl, Terraform, взаимодействие с облачными API). - Shared Library становится единой точкой истины для CD-логики, что обеспечивает согласованность и упрощает обновления.
Резюме и лучшие практики
На практике я чаще всего комбинировал подходы 1 и 2. Основные правила, которые я применял для четкого разделения:
- CI-фаза должна создавать один единственный, неизменяемый, промотируемый артефакт. Если вы разворачиваете что-то иное, чем было протестировано, процесс нарушен.
- Точка перехода от CI к CD — это "релизный артефакт". Его идентификатор (тег, хэш, номер сборки) должен явно передаваться в CD-процесс.
- CD-процесс должен быть идемпотентным и безопасным. Его запуск на одном и том же артефакте должен давать предсказуемый результат, а доступ к production-средам должен быть строго контролируемым (через
input, механизмы одобрения или отдельные учетные данные). - Информация о среде (config) отделяется от артефакта. Образ приложения не содержит паролей или endpoint'ов для конкретного кластера. Они инжектируются во время CD-фазы через ConfigMaps, Secrets или переменные окружения.
Таким образом, разделение в Jenkins — это не просто "этапы в одном файле", а прежде всего архитектурное решение, направленное на создание надежного, управляемого и безопасного конвейера доставки программного обеспечения.