Эта статья — способ заглянуть в курс «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 в пайплайне и выведем его версию в консоль билда.  Пайплайны в Jenkins задаются очень простым путем: пишется Stage, аналогично стейджу в Gitlab, а внутри него перечисляются Steps. Все системы CI/CD основаны на одном принципе, дьявол именно в деталях.  Напишем свой Stage, назовем его Deploy и вызовем там версию Ansible. pipeline { // задаем тон groovy, даем понять что здесь у нас шаги пайплайна    agent any // если у нас есть какие то jenkins агенты специально для Ansible мы можем их указать здесь, у меня только один агент, поэтому я поставлю any        stages { // здесь определяем какие шаги в пайплайне        stage('Deploy') { // наш деплой            steps { // определяем шаги уже самого стейджа                sh 'ansible --version' // выводим версию Ansible, команда sh просто выполнит скрипт из консоли            }        }    }} Сохраняем пайплайн, выходим в главное окно проекта и нажимаем Build Now. Если у вас на машине уже установлен Ansible, все пройдет успешно. Первый пайплайн готов.  Нажмем на #1 внизу в Build history. Каждый пайплайн создает history, которую можно ограничить настройками билда, чтобы предотвратить засорение диска логами и артефактами сборки. По умолчанию ничего не удаляем, я рекомендую на период настройки пайплайнов не удалять билды, чтобы вернуться на любой шаг и посмотреть необходимую информацию. Жмем на Console Output чтобы посмотреть вывод: Видим пользователя, активировавшего билд, и настройки его ограничений. Внутри Jenkins по умолчанию вы очень ограничены во взаимодействии с системой, потому что можете убить ноду с Jenkins неправильным пайплайном. Дальше — шаги пайплайна подсвеченные серым, а вывод консоли черным цветом. После отображения папки, где был запущен пайплайн, выводятся  результаты работы нашей sh команды, которая покажет версию Ansible в привычном  виде, как если бы мы запустили ее из консоли.  Для изначального тестирования я создам очень простой плейбук:   - name: "Test playbook run"   hosts: localhost   tasks:     - name: "Debug"       ansible.builtin.debug:         msg: "Test debug" Он располагается в github по адресу https://github.com/Nortsx/jenkinsansiblebook. Важно: перед началом работы склонируйте его в свой репозиторий, чтобы не зависеть от оригинала. Модифицируем пайплайн: pipeline {    agent any    stages {        stage('Checkout') { // добавим новый Stage            steps {                git branch: 'main', url: "git@github.com:Nortsx/jenkinsansiblebook.git" // используем встроенный в Jenkins плагин Git для скачивания проекта из бранча main            }        }        stage('Deploy') {            steps {                sh 'ansible-playbook playbook.yml' // поскольку скрипты работают в одной папке, на втором шаге мы можем просто запустить плейбук            }        }    }} Я скачиваю плейбук его через 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  Ssh-keygen -t rsa. После ответа на вопросы об имени ключа (укажите другое имя кроме 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 {    agent any    stages {        stage('Checkout') {             steps {                git branch: 'main', url: "git@github.com:Nortsx/jenkinsansiblebook.git", credentialsId: 'github_key' // здесь добавляем credentialsId и указываем наш ID.             }        }        stage('Deploy') {            steps {                sh 'ansible-playbook playbook.yml'             }        }    }} Запускаем пайплайн и смотрим на вывод: Сработало! Посмотреть результаты запусков по шагам можно, нажав кнопку Pipeline Steps. Она покажет аргументы запуска и позволит по клику на мониторчике изолированно посмотреть вывод по конкретному шагу, что может быть удобно для отладки. Например вывод только запуска нашего Ansible playbook: Переходим к следующей части.  Воспользуемся Ansible, чтобы постучаться в другие хосты. В плейбук добавим файлы hosts и ansible.cfg Hosts.ini testmachine ansible_host=192.168.60.55 ansible_user=vagrant Я использую Vagrant, поэтому мои адреса принадлежат локальной сети.  Ansible.cfghost_key_checking=false Playbook.yml---- name: "Test playbook run"  hosts: all # теперь запускаем скрипты на удаленных хостах  tasks:    - name: "Debug"      ansible.builtin.debug:        msg: "Test debug"После изменений в своем гите, нам необходимо изменить пайплайн, для использования файла hosts.ini.pipeline {    agent any    stages {        stage('Checkout') { // добавим новый Stage            steps {                git branch: 'main', url: "git@github.com:Nortsx/jenkinsansiblebook.git", credentialsId: 'github_key'            }        }        stage('Deploy') {            steps {                sh 'ansible-playbook playbook.yml -i hosts.ini' // добавляем новый аргумент            }        }    }} После запуска видим провал на втором шаге: Ключи не авторизованы на удалённой машине, поэтому с ней нельзя связаться.  Добавим ключи для авторизации на удаленной машине: Я буду использовать тот же ключ, что для github. Возьмем публичную часть ключа и добавим в ~/.ssh/authorized_keys машины, к которой подключаемся через ansible.  Изменим пайплайн, чтобы Ansible мог использовать ключи авторизации.  pipeline {    agent any    stages {        stage('Checkout') {            steps {                git branch: 'main', url: "git@github.com:Nortsx/jenkinsansiblebook.git", credentialsId: 'github_key'            }        }        stage('Deploy') {            steps {                withCredentials([sshUserPrivateKey(credentialsId: 'github_key', keyFileVariable: 'PRIVATE')]) { // используем credentials и записываем их содержание во временный файл доступный по пути PRIVATE                   sh 'ansible-playbook playbook.yml -i hosts.ini --private-key $PRIVATE' //используем переменную с помощью Ansible                }            }        }    }} И вуаля: Для других переменных, которые не надо скрывать, мы можем использовать секцию variables.  Например: pipeline {    agent any        environment {        GIT_BRANCH = 'main'    }    stages {        stage('Checkout') {            steps {                git branch: $GIT_BRANCH, url: "git@github.com:Nortsx/jenkinsansiblebook.git", credentialsId: 'github_key'            }        } Снова идём в список плагинов в Manage Jenkins и ищем Ansible в списке Available плагинов.  Устанавливаем его.  При установке ставим галочку «Restart Jenkins», после установки Jenkins перезагрузится.  Теперь можно переписать пайплайн: pipeline {    agent any    stages {        stage('Checkout') {            steps {                git branch: 'main', url: "git@github.com:Nortsx/jenkinsansiblebook.git", credentialsId: 'github_key'            }        }        stage('Deploy') {            steps {                ansiblePlaybook playbook: 'playbook.yml', inventory: 'hosts.ini', credentialsId: 'github_key'            }        }    }} Вместо оборачивания в credentials, мы передали строчку в Id и вызвали специальный модуль, делающий за нас работу. Это сравнимо с использованием, например command или shell в Ansible, когда можно использовать специальный модуль, упрощающий и контролирующий работу, вместо «голых» вызовов консоли.  Плагин умеет больше, чем простой запуск плейбука, сильно упрощает пайплайны и саму жизнь.  Редактор