
Эта статья — способ заглянуть в курс «Ansible: от первых шагов до большого проекта». Всеволод Севостьянов, Lead Engineer в Vene, отвечающий за пайплайны и deployment, показал, как настраивать Jenkins в связке с Ansible.
Первые шаги
Предположим что у нас есть система с установленным Jenkins и мы хотим привязать к ней IaaC в виде Ansible. После изначальной установки Jenkins, необходимо настроить связку с Ansible. Нужно договориться об условиях:
Jenkins установлен со стандартными плагинами;
Все пайплайны запускаются на машине, где установлен Jenkins (стандартный build agent), но для remote-агентов будет то же самое.
После установки Jenkins создаём новую сборочную задачу:

Вы можете создать Freestyle project — шаблон для Jenkins, в котором есть все этапы «Спулить код» → «Запустить работу», они позволяют с помощью шаблонов выбрать готовые пайплайны. Эта опция была добавлена в Jenkins чтобы повысить дружелюбность интерфейса к начинающим администраторам и автоматизаторам. Но мы выберем Pipeline.
Окно со свойствами проекта:

Здесь можно задать описание проекта, настроить как будут вести себя пайплайны. Во вкладке Build Triggers можно поставить параметры для автоматического запуска пайплайна, например запускать раз в день, или запускать, если появился новый коммит в определенной ветке Git.
Обратите внимание на поле ниже — Pipeline:

Jenkins, как и Gitlab, использует скрипт, который умеет выполнять консольные команды для запуска пайплайна по шагам. В отличие от Gitlab, Jenkins использует Groovy — полноценный язык программирования, который дает возможность тоньше кастомизировать работы и позволяет полноценно использовать программные конструкции для автоматизации. Но его сложнее освоить.
Итак, с помощью Pipeline достигнем целей:
Запустим Ansible и выведем его версию;
Скачаем Playbook с Github и запустим его;
Постучимся в другую машину изнутри Jenkins;
Используем специальный плагин Ansible для предыдущих трёх пунктов.
Запускаем Ansible и выводим его версию
Начнем с очень простой задачи — запустим Ansible в пайплайне и выведем его версию в консоль билда.
Пайплайны в Jenkins задаются очень простым путем: пишется Stage, аналогично стейджу в Gitlab, а внутри него перечисляются Steps. Все системы CI/CD основаны на одном принципе, дьявол именно в деталях.
Напишем свой Stage, назовем его Deploy и вызовем там версию Ansible.
|
Сохраняем пайплайн, выходим в главное окно проекта и нажимаем Build Now.
Если у вас на машине уже установлен Ansible, все пройдет успешно. Первый пайплайн готов.

Заглянем ему под капот
Нажмем на #1 внизу в Build history. Каждый пайплайн создает history, которую можно ограничить настройками билда, чтобы предотвратить засорение диска логами и артефактами сборки. По умолчанию ничего не удаляем, я рекомендую на период настройки пайплайнов не удалять билды, чтобы вернуться на любой шаг и посмотреть необходимую информацию.

Жмем на Console Output чтобы посмотреть вывод:

Видим пользователя, активировавшего билд, и настройки его ограничений. Внутри Jenkins по умолчанию вы очень ограничены во взаимодействии с системой, потому что можете убить ноду с Jenkins неправильным пайплайном.
Дальше — шаги пайплайна подсвеченные серым, а вывод консоли черным цветом. После отображения папки, где был запущен пайплайн, выводятся результаты работы нашей sh команды, которая покажет версию Ansible в привычном виде, как если бы мы запустили ее из консоли.
Запускаем Playbook с Github
Для изначального тестирования я создам очень простой плейбук:
| |
| |
| |
| |
| |
|
Он располагается в github по адресу https://github.com/Nortsx/jenkinsansiblebook. Важно: перед началом работы склонируйте его в свой репозиторий, чтобы не зависеть от оригинала.
Модифицируем пайплайн:
|
Я скачиваю плейбук его через ssh, а не http.
Запускаем Pipeline и смотрим на результаты билда:

Jenkins провалился на первом этапе, не смог скачать исходники с Git, потому что не смог установить соединение с Github. Ответ на вопрос «как это пофиксить?» в тексте ошибки. Мы увидим эту ошибку, если соединимся по ssh с локальным ssh-agent, но при этом сервера нет в known_hosts. Добавим сервер Github для Jenkins.
Логинимся на машину с Jenkins, от лица пользователя Jenkins, если вы не переставляли пользователя для Jenkins и запускаем ssh github.com. На вопрос «Do you want to add gihutb.com to known hosts» жмем Y. Первая ошибка больше не будет мешать.
Запускаем пайплайн второй раз:

Ошибка в stderr поменялась на Permission Denied — для подключения по ssh к Github нужен ключ, который Github знает. Добавим этот ключ.
Убеждаемся, что плагин Credentials установлен: Dashboard → Manage Jenkins → Manage Plugins, если нет, то установим его.

Генерируем ключ для Github и добавляем его в аккаунт.
Запустим команду на машине с linux
|
После ответа на вопросы об имени ключа (укажите другое имя кроме id_rsa, если ваш стандартный ключ уже используется, поскольку его можно случайно перезаписать), защита паролем (выбираем «no») вы получите пару приватный/публичный ключ. Публичный ключ имеет расширение .pub после имени, приватный ключ его не имеет.
Важно! Старайтесь не светить свой приватный ключ, особенно если он используется где то для доступа к защищенным репозиториям, это вопрос безопасности.
После генерации ключей идем на github.com, кликаем на иконку профиля справа, Settings→SSH and GPG keys и попадаем на страницу добавления ssh ключей профиля.

Жмякаем New SSH Key

Копируем ПУБЛИЧНУЮ часть ключа и называем его произвольным именем
В Dashboard → Manage Jenkins → Credentials нажимаем на Global и Add Credentials.

В открывшемся окне выбираем SSH Username with private key и заполняем данные.

ID — идентификатор, уникальный для каждого credential, по которому вызывают их из пайплайна. Username — имя для вашего профиля Github. Private key → нажмите Enter Directly → Add и скопируйте значение из сгенерированного Приватного ключа.
После добавления ключ в списке Credentials.

Время использовать ключ в пайплайне:
|
Запускаем пайплайн и смотрим на вывод:

Сработало!
Посмотреть результаты запусков по шагам можно, нажав кнопку Pipeline Steps.

Она покажет аргументы запуска и позволит по клику на мониторчике изолированно посмотреть вывод по конкретному шагу, что может быть удобно для отладки.
Например вывод только запуска нашего Ansible playbook:

Переходим к следующей части.
Стучимся в другую машину изнутри Jenkins
Воспользуемся Ansible, чтобы постучаться в другие хосты.
В плейбук добавим файлы hosts и ansible.cfg
Hosts.ini
|
Я использую Vagrant, поэтому мои адреса принадлежат локальной сети.
|
|
После запуска видим провал на втором шаге:


Ключи не авторизованы на удалённой машине, поэтому с ней нельзя связаться.
Добавим ключи для авторизации на удаленной машине:
Я буду использовать тот же ключ, что для github. Возьмем публичную часть ключа и добавим в ~/.ssh/authorized_keys машины, к которой подключаемся через ansible.
Изменим пайплайн, чтобы Ansible мог использовать ключи авторизации.
|
И вуаля:

Для других переменных, которые не надо скрывать, мы можем использовать секцию variables.
Например:
|
Используем специальный плагин Ansible для всего сделанного выше
Снова идём в список плагинов в Manage Jenkins и ищем Ansible в списке Available плагинов.

Устанавливаем его.
При установке ставим галочку «Restart Jenkins», после установки Jenkins перезагрузится.

Теперь можно переписать пайплайн:
|
Вместо оборачивания в credentials, мы передали строчку в Id и вызвали специальный модуль, делающий за нас работу. Это сравнимо с использованием, например command или shell в Ansible, когда можно использовать специальный модуль, упрощающий и контролирующий работу, вместо «голых» вызовов консоли.
Плагин умеет больше, чем простой запуск плейбука, сильно упрощает пайплайны и саму жизнь.