Управление задачами в Jenkins CI
Jenkins сейчас используется, пожалуй, практически в любой компании, где есть необходимость в автоматическом деплое приложений и инфраструктуры, а также в удобном управлении различного рода задач. На рынке сейчас представлено много других инструментов (как платных, так и бесплатных), позволяющих построить процесс непрерывной интеграции максимально комфортно. Jenkins является бесплатным инструментом, обладающим огромными возможностями в виде тысяч плагинов, […]
Jenkins сейчас используется, пожалуй, практически в любой компании, где есть необходимость в автоматическом деплое приложений и инфраструктуры, а также в удобном управлении различного рода задач.
На рынке сейчас представлено много других инструментов (как платных, так и бесплатных), позволяющих построить процесс непрерывной интеграции максимально комфортно.
Jenkins является бесплатным инструментом, обладающим огромными возможностями в виде тысяч плагинов, которые постоянно добавляются и обновляются.
Базовый подход к управлению задачами предлагается нам через веб-интерфейс самого Jenkins, где мы можем что угодно сконфигурировать, но поддерживать это при большом количестве задач и их разнотипности становится сложнее.
Ниже мы рассмотрим, как упростить и ускорить создание задач в Jenkins.
Инструменты, которые будем использовать
Jenkins job builder
Это python-утилита, позволяющая описывать задачи в YAML- или JSON форматах, которые через HTTP API загружаются на сервер. Для работы достаточно установить ее на локальной машине, написать конфигурацию с подключением и описать требуемые задачи.
Актуальная документация проекта
DSL Plugin
Это плагин для Jenkins, с помощью которого мы сможем описывать задачи на специальном языке (DSL, Domain Specific Language) и создавать их на основе этих описаний. Работает локально на самом Jenkins-сервере.
Страница плагина
Jenkins Pipeline
Это тип задачи в Jenkins, с помощью которого мы можем описать необходимый нам процесс деплоя или сборки приложения по стадиям. Описывать pipeline мы будем в специальном Jenkinsfile, который будет храниться в репозитории проекта.
Gitlab и Gitlab CI
Наиболее популярный и развивающийся сейчас selfhosted проект, который также используется во многих компаниях. Он включает в себя версию для сообщества и энтерпрайз-решение.
Внутри имеется собственный CI, написанный на Go, который через специальные подключаемые агенты (runners) позволяет нам проводить различные стадии сборки и деплоя.
Для начала использования достаточно в репозитории проекта создать файл .gitlab-ci.yml, в котором описать необходимую нам последовательность. Для работы отлично может использовать Docker.
Итак, начнем
Для начала поставим необходимые инструменты.
Jenkins-job-builder в нашем случае необходимо установить как на локальную машину, так и на машину, где будет работать агент gitlab. Можно обойтись просто локальной машиной gitlab.
Локально на linux и mac установим последнюю доступную версию:
pip install jenkins-job-builder brew install jenkins-job-builder
Локально для описания нашего seed job мы сможем протестировать его работоспособность.
Добавлю, что seed job в терминологии DSL Plugin является задача типа Free-style project, которая создает остальные задачи из DSL-скриптов.
На gitlab-сервере установка будет ничем не отличаться от локальной установки на linux-машину:
pip install jenkins-job-builder
На всякий случай запустим утилиту и проверим, что она работает:
➜ ~ jenkins-jobs usage: jenkins-jobs [-h] [--conf CONF] [-l LOG_LEVEL] [--ignore-cache] [--flush-cache] [--version] [--allow-empty-variables] [--user USER] [--password PASSWORD] {update,test,delete,delete-all} ...
Установка плагина
Теперь установим плагин в Jenkins. Для установки можно воспользоваться как классическим UpdateCenter в разделе Manage Jenkins → Manage Plugins → Available, так и используя установку с помощью curl/wget, скачав плагин с официальной страницы плагина:
- Версия gitlab — 9.4.4-ce.0
- Версия gitlab-ci-multi-runner — 9.4.2
Создание репозитория
Создадим репозитории под код с описанием задач.
Для начала подготовим наш seed job — так называется задача, которая генерирует из себя все остальные. Репозиторий будет состоять из следующих файлов:
jenkins.ini
[job_builder] ignore_cache=True keep_descriptions=False include_path=. recursive=False allow_duplicates=False [jenkins] user=username password=secret-pass url=http://example-ci.org
job-generator.yml
--- - job: name: job-generator description: 'Do not edit this job through the web!' scm: - git: url: git@gitlab-selfhosted.org:group/repo-dsl.git branches: - origin/master credentials-id: some-credentials-id timeout: 20 basedir: dsl triggers: - gitlab: trigger-push: true trigger-merge-request: false trigger-open-merge-request-push: both ci-skip: false set-build-description: false add-note-merge-request: false add-vote-merge-request: false add-ci-message: true allow-all-branches: true branch-filter-type: RegexBasedFilter target-branch-regex: '.*master*.' builders: - dsl: target: "dsl/*.groovy" ignore-existing: "false" removed-job-action: "DISABLE" removed-view-action: "DELETE" lookup-strategy: "SEED_JOB"
.gitlab-ci.yml
job: script: 'jenkins-jobs --conf jenkins.ini update job-generator.yml'
Подключим gitlab-runner к нашему проекту. Поскольку интерфейс gitlab последнее время часто меняется, то рекомендуем обращаться к официальной документации.
После подключения он будет выглядеть примерно так:
Теперь закоммитим изменения и в разделе Jobs у нашего проекта увидим следующее:
Вся схема выглядит следующим образом:
Подготовим репозиторий с описанием задач. Создадим его с названием repo-dsl и плоской структурой. Все файлы располагаются как есть.
Положим в него файл с нашим pipeline:
pipelineJob('testpipeline-build') { description('Build test docker image, test and push it to local registry') definition { cpsScm { scm { git { branch('origin/master') remote { url('git@gitlab-selfhosted.org:test-group/sample-project.git') credentials('gitlab-creds') } } } scriptPath('Jenkinsfile') } } }
И настроим webhook по запуску seed-job, который мы создали ранее.
В данной версии gitlab webhooks располагаются в проекте в разделе Settings → Integrations.
Создаем webhook на push (gitlab:pass@ci.org/project/job-generator). Схематично это выглядит вот так:
Теперь в нашем Jenkins есть две задачи:
- Задача-генератор seed-job
- Задача типа pipeline с названием testpipeline-build.
В тестовом pipeline мы будем собирать docker-образ, который после будет загружаться в локальный docker registry. Файл с образом будет браться с другого проекта.
В проекте с названием sample-project создадим Jenkinsfile следующего содержания:
node { def app stage('Clone repository') { checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab-repo-creds', url: 'git@gitlab-selfhosted.org:test-group/docker-image-file.git']]]) } stage('Build image') { app = docker.build("docker-image") } stage('Test image') { sh ''' if ! docker inspect docker-image &> /dev/null; then echo 'docker-image does not exist!' exit 1 fi ''' } stage('Push image') { echo 'Push image' docker.withRegistry('https://local-registry:9666', 'registry-creds') { app.push("${env.BUILD_NUMBER}") app.push("latest") } } stage('Clean existing image') { sh "docker rmi docker-image" } }
В итоге готовый pipeline будет выглядеть следующим образом в интерфейсе blueocean в Jenkins:
Или так в классическом интерфейсе:
Для запуска этой задачи автоматически мы можем добавить webhook в проекте с docker-image, где после отправки изменений в репозиторий будет запускаться эта задача.
В заключении отметим, что данная статья описывает лишь один из множества подходов управления задачами в jenkins. За счет гибкости и функционала вы можете использовать разные подходы, которые позволят именно вам управлять задачами максимально просто и удобно исходя из ваших требований и требований инфраструктуры.