Всем привет. В данной статье хочу поделиться знаниями, полученными в процессе автоматизации развертывания наших сервисов на различные серверы в разных дата-центрах.
Задача была следующей: есть определенный набор скриптов для развертывания сервисов, которые нужно запускать на каждом сервере каждого дата-центра. Скрипты выполняют серию операций: проверка статуса, вывод из-под load balancer’а, выпуск версии, развертывание, проверка статуса, отправка уведомлений через email и Slack и т.д. Это просто и удобно, но с ростом числа дата-центров и сервисов процесс выкатки новой версии может занять целый день. Кроме того, за некоторые действия отвечают отдельные команды, например, настройка load balancer’а. Также хотелось, чтобы управляющий процессом код хранился в общедоступном репозитории, дабы каждый член команды мог его поддерживать.
Решить задачу удалось с помощью Jenkins Pipeline Shared Libraries: этапы процесса разделились визуально на логические части, код хранится в репозитории, а осуществить доставку на 20 серверов стало возможно в один клик. Ниже приведен пример подобного тестового проекта:

Сейчас я расскажу и покажу примеры как этого достичь. Надеюсь эта статья поможет сохранить время другим разработчикам, а также буду рад дельным комментариям.
Первое что необходимо сделать, создать собственную библиотеку, в которой будут храниться наши функции.
Создаем новый репозиторий, который должен иметь следующую структуру:

Директория src используется для Groovy классов, которые добавляются в classpath при выполнении Pipeline.
Директория vars используется в скриптах, которые определяют глобальные переменные, доступные из Pipeline.
Ниже приведен пример Groovy класса
В классах можно использовать любые возможности языка: создавать потоки, соединяться по FTP и т.д.
Важно:
— чтобы выводить в лог консоли из Pipeline, нужно передавать Script;
— для импорта библиотек просто используем
Ниже пример скрипта:
В скриптах можно использовать любые возможности языка и также получить переменные сборки и параметры Jenkins.
Важно:
— Чтобы остановить выполнение достаточно установить значение
— Получить параметры параметризованной сборки можно через переменную
Вот пример репозитория с другими примерами.
Следующий шаг — добавить наш репозиторий как глобальную библиотеку Pipeline.
Для этого в Jenkins нужно перейти: Manage Jenkins → Configure System (Настроить Jenkins → Конфигурирование системы). В блоке Global Pipeline Libraries, добавить наш репозиторий, как на картинке ниже:

Последний шаг — создать Pipeline.
Наш Pipeline будет выглядеть следующим образом:
Т.е. мы просто добавляем
Наш Pipeline готов.
В следующий раз я покажу, как я настраивал параметризованную сборку, чтобы элегантно получить зависимые параметры из REST сервиса.
Спасибо за внимание!
Задача была следующей: есть определенный набор скриптов для развертывания сервисов, которые нужно запускать на каждом сервере каждого дата-центра. Скрипты выполняют серию операций: проверка статуса, вывод из-под load balancer’а, выпуск версии, развертывание, проверка статуса, отправка уведомлений через email и Slack и т.д. Это просто и удобно, но с ростом числа дата-центров и сервисов процесс выкатки новой версии может занять целый день. Кроме того, за некоторые действия отвечают отдельные команды, например, настройка load balancer’а. Также хотелось, чтобы управляющий процессом код хранился в общедоступном репозитории, дабы каждый член команды мог его поддерживать.
Решить задачу удалось с помощью Jenkins Pipeline Shared Libraries: этапы процесса разделились визуально на логические части, код хранится в репозитории, а осуществить доставку на 20 серверов стало возможно в один клик. Ниже приведен пример подобного тестового проекта:

Сейчас я расскажу и покажу примеры как этого достичь. Надеюсь эта статья поможет сохранить время другим разработчикам, а также буду рад дельным комментариям.
Создание библиотеки
Первое что необходимо сделать, создать собственную библиотеку, в которой будут храниться наши функции.
Создаем новый репозиторий, который должен иметь следующую структуру:

Директория src используется для Groovy классов, которые добавляются в classpath при выполнении Pipeline.
Директория vars используется в скриптах, которые определяют глобальные переменные, доступные из Pipeline.
Ниже приведен пример Groovy класса
@Grab(group = 'org.apache.commons', module = 'commons-lang3', version = '3.6') import org.apache.commons.lang3.StringUtils class Deployer { int tries = 0 Script script def run() { while (tries < 10) { Thread.sleep(1000) tries++ script.echo("tries is numeric: " + StringUtils.isAlphanumeric("" + tries)) } } }
В классах можно использовать любые возможности языка: создавать потоки, соединяться по FTP и т.д.
Важно:
— чтобы выводить в лог консоли из Pipeline, нужно передавать Script;
— для импорта библиотек просто используем
@Grab.Ниже пример скрипта:
#!/usr/bin/env groovy def call(body) { echo "Start Deploy" new Deployer(script:this).run() echo "Deployed" currentBuild.result = 'SUCCESS' //FAILURE to fail return this }
В скриптах можно использовать любые возможности языка и также получить переменные сборки и параметры Jenkins.
Важно:
— Чтобы остановить выполнение достаточно установить значение
currentBuild.result = 'FAILURE';— Получить параметры параметризованной сборки можно через переменную
env. Например, env.param1.Вот пример репозитория с другими примерами.
Подключение репозитория
Следующий шаг — добавить наш репозиторий как глобальную библиотеку Pipeline.
Для этого в Jenkins нужно перейти: Manage Jenkins → Configure System (Настроить Jenkins → Конфигурирование системы). В блоке Global Pipeline Libraries, добавить наш репозиторий, как на картинке ниже:

Создание Pipeline
Последний шаг — создать Pipeline.
Наш Pipeline будет выглядеть следующим образом:
@Library('jenkins-pipeline-shared-lib-sample')_ stage('Print Build Info') { printBuildinfo { name = "Sample Name" } } stage('Disable balancer') { disableBalancerUtils() } stage('Deploy') { deploy() } stage('Enable balancer') { enableBalancerUtils() } stage('Check Status') { checkStatus() }
Т.е. мы просто добавляем
@Library('jenkins-pipeline-shared-lib-sample')_ (не забываем добавить _ в конце) и вызываем наши функции по имени скриптов, например deploy.Наш Pipeline готов.
В следующий раз я покажу, как я настраивал параметризованную сборку, чтобы элегантно получить зависимые параметры из REST сервиса.
Спасибо за внимание!
