Интеграция Ansible с Jenkins: Автоматизация вашего CI/CD конвейера
Интегрируйте Ansible с Jenkins для запуска плейбуков из CI/CD конвейеров, управления SSH-учетными данными и последовательного развертывания.
Интеграция Ansible с Jenkins: автоматизация CI/CD конвейера
Интеграция Ansible с Jenkins позволяет вашему CI/CD конвейеру собирать артефакты, запускать тесты и развертывать их с помощью тех же плейбуков, которые вы используете вне Jenkins. Основная задача — настроить учетные данные, инвентаризацию и выполнение плейбуков, не превращая конвейер в набор shell-команд.
Это руководство показывает практическую настройку: Jenkins оркестрирует конвейер, а Ansible отвечает за развертывание и настройку на целевых хостах. Примеры предполагают развертывание на Linux через SSH, но тот же подход работает с инвентаризациями и ролями для разных сред.
Как Jenkins и Ansible работают вместе
Прежде чем писать конвейер, разделите обязанности:
- Jenkins: Проверяет код, собирает артефакты, запускает тесты, собирает логи и решает, когда запускать этапы развертывания.
- Ansible: Подключается к целевым хостам, копирует артефакты, записывает конфигурацию, управляет сервисами и делает шаги развертывания идемпотентными.
Зачем интегрировать Jenkins с Ansible?
Такое разделение дает вашей команде четкие границы:
- Jenkins хранит процесс релиза в
Jenkinsfile. - Ansible хранит действия с инфраструктурой в плейбуках и ролях.
- Файлы инвентаризации определяют, какие хосты относятся к staging, production или другим средам.
- Учетные данные Jenkins защищают SSH-ключи, пароли Vault и токены.
Предварительные требования для интеграции
Перед началом убедитесь, что у вас есть:
- Работающий контроллер Jenkins и хотя бы один агент, способный выполнять задачи развертывания.
- Ansible, установленный на агенте Jenkins, который будет запускать
ansible-playbook. - Целевые машины, доступные с этого агента по SSH.
- Выделенная пара SSH-ключей для автоматизации.
- Код приложения, инвентаризация, плейбуки и роли в системе контроля версий.
Настройка Jenkins для работы с Ansible
Jenkins нужно две вещи, прежде чем он сможет безопасно запускать Ansible: среда выполнения Ansible на агенте и учетные данные для целевых хостов.
1. Установка плагина Ansible
Вы можете вызывать ansible-playbook напрямую из шага shell, но плагин Ansible для Jenkins упрощает управление конфигурацией и выводом.
- Перейдите в
Manage Jenkins>Manage Plugins. - Перейдите на вкладку
Availableи найдите "Ansible". - Выберите плагин "Ansible" и нажмите
Install without restartилиDownload now and install after restart.
2. Настройка SSH-учетных данных
Ansible будет использовать SSH для подключения к целевым серверам. Храните закрытый ключ в учетных данных Jenkins, а не в репозитории.
- Перейдите в
Manage Jenkins>Manage Credentials. - Выберите хранилище учетных данных, используемое вашими задачами.
- Нажмите
Add Credentials. - Выберите
SSH Username with private key. - Установите стабильный ID, например
ansible-ssh-key. - Введите имя пользователя SSH, используемое на целевых машинах.
- Добавьте закрытый ключ и сохраните учетные данные.
Совет: Лучшие практики управления ключами
- Никогда не жестко кодируйте SSH-ключи в Jenkinsfile, инвентаризации или плейбуке.
- Используйте выделенные ключи для автоматизации, а не личные ключи.
- Регулярно меняйте ключи в соответствии с политикой безопасности вашей команды.
Разработка конвейера Jenkins с Ansible
Используйте декларативный конвейер в Jenkinsfile, чтобы логика развертывания проверялась вместе с кодом приложения.
Базовая структура конвейера
Вот компактный пример для сборки, развертывания на staging и развертывания на production с проверкой:
// Jenkinsfile
pipeline {
agent any
environment {
// Определите переменные окружения при необходимости
ANSIBLE_HOST_KEY_CHECKING = 'False' // Будьте осторожны в production, предпочитайте known_hosts
}
stages {
stage('Checkout Source') {
steps {
git 'https://your-scm-url/your-repo.git'
}
}
stage('Build Application') {
// Этот этап может собирать JAR, WAR, Docker-образ и т.д.
// Пример: сборка Spring Boot JAR
steps {
sh 'mvn clean package'
}
}
stage('Run Unit Tests') {
steps {
sh 'mvn test'
}
}
stage('Deploy to Staging') {
steps {
script {
// Используйте SSH-агент, чтобы сделать закрытый ключ доступным для Ansible
sshagent(credentials: ['ansible-ssh-key']) {
// Выполнение плейбука Ansible
sh 'ansible-playbook -i inventory/staging.ini playbooks/deploy_app.yml \
-e "app_version=$(cat target/VERSION)"'
}
}
}
}
stage('Deploy to Production') {
// Этот этап может требовать ручного подтверждения
input {
message "Продолжить развертывание на Production?"
ok "Развернуть на Production"
}
steps {
script {
sshagent(credentials: ['ansible-ssh-key']) {
sh 'ansible-playbook -i inventory/production.ini playbooks/deploy_app.yml \
-e "app_version=$(cat target/VERSION)"'
}
}
}
}
}
post {
always {
echo 'Конвейер завершен.'
}
success {
echo 'Конвейер выполнен успешно!'
// slackSend channel: '#deployments', message: "Развертывание успешно: ${env.BUILD_URL}"
}
failure {
echo 'Конвейер завершился ошибкой!'
// slackSend channel: '#deployments', message: "Развертывание не удалось: ${env.BUILD_URL}"
}
}
}
Ключевые детали конвейера
agent anyподходит для демонстрации. В production используйте метку агента, гарантирующую установку Ansible.sshagent(credentials: ['ansible-ssh-key'])делает закрытый ключ доступным только внутри этого блока.ansible-playbook -i inventory/staging.ini playbooks/deploy_app.ymlявно указывает целевую среду.- Блок
inputдля production добавляет ручной шлюз перед чувствительным развертыванием. - Избегайте отключения проверки ключа хоста в production. Вместо этого управляйте
known_hostsна агенте Jenkins.
Пример плейбука Ansible: развертывание веб-приложения
Вот упрощенные inventory/staging.ini и playbooks/deploy_app.yml для Java-веб-приложения. Имя вашего артефакта, менеджер сервисов и пути могут отличаться.
inventory/staging.ini
[web_servers]
web1.example.com
web2.example.com
[database_servers]
db1.example.com
[all:vars]
ansible_user=ubuntu
playbooks/deploy_app.yml
---
- name: Развертывание веб-приложения
hosts: web_servers
become: yes
vars:
app_name: my-webapp
app_path: /opt/{{ app_name }}
app_port: 8080
app_version: "{{ app_version | default('1.0.0') }}"
tasks:
- name: Убедиться, что директория приложения существует
ansible.builtin.file:
path: "{{ app_path }}"
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0755'
- name: Скопировать JAR-файл приложения на целевой хост
ansible.builtin.copy:
src: "target/{{ app_name }}-{{ app_version }}.jar"
dest: "{{ app_path }}/{{ app_name }}.jar"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0644'
notify: restart app service
- name: Убедиться, что файл сервиса systemd существует
ansible.builtin.template:
src: templates/my-webapp.service.j2
dest: /etc/systemd/system/{{ app_name }}.service
owner: root
group: root
mode: '0644'
notify: restart app service
- name: Убедиться, что сервис приложения запущен и включен
ansible.builtin.systemd:
name: "{{ app_name }}"
state: started
enabled: yes
handlers:
- name: restart app service
ansible.builtin.systemd:
name: "{{ app_name }}"
state: restarted
daemon_reload: yes
templates/my-webapp.service.j2 (шаблон systemd-сервиса)
[Unit]
Description={{ app_name }} Application
After=network.target
[Service]
User={{ ansible_user }}
ExecStart=/usr/bin/java -jar {{ app_path }}/{{ app_name }}.jar --server.port={{ app_port }}
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
Этот плейбук создает директорию приложения, копирует собранный JAR, записывает systemd-юнит и запускает сервис. Обработчик перезапускает сервис только при изменении артефакта или файла юнита.
Лучшие практики и советы
- Делайте плейбуки идемпотентными, чтобы повторный запуск неудачного конвейера не нанес дополнительного ущерба.
- Храните пароли Vault в учетных данных Jenkins и передавайте их через временный файл паролей или одобренную привязку учетных данных.
- Организуйте логику развертывания в роли, такие как
webserver,databaseиapp_deploy. - Используйте отдельные инвентаризации или
group_varsдля staging и production. - Запускайте Ansible на выделенных агентах Jenkins, а не на контроллере.
- Используйте
-vили-vvтолько при необходимости; избегайте утечки секретов в логи. - Тестируйте плейбуки до того, как Jenkins их запустит, особенно для ролей production.
Когда обращаться к профессионалу
Привлекайте администратора Jenkins или платформы, когда конвейер развертывает на production, управляет общими учетными данными, записывает на множество хостов или требует контроля аудита. Обработка учетных данных, проверка ключа хоста и поведение отката заслуживают повторной проверки перед первым запуском в production.
Вывод
Используйте Jenkins для оркестрации и Ansible для состояния развертывания. Храните учетные данные в Jenkins, плейбуки — в системе контроля версий, делайте инвентаризацию явной и тестируйте те же команды Ansible вне конвейера, прежде чем автоматизировать развертывание в production.