Intégrer Ansible avec Jenkins : Automatiser votre pipeline CI/CD
Intégrez Ansible avec Jenkins pour exécuter des playbooks depuis des pipelines CI/CD, gérer les identifiants SSH et déployer de manière cohérente.
Intégrer Ansible avec Jenkins : Automatiser votre pipeline CI/CD
Intégrer Ansible avec Jenkins permet à votre pipeline CI/CD de construire un artefact, d'exécuter des tests et de le déployer avec les mêmes playbooks que vous utilisez en dehors de Jenkins. Le principal défi est de connecter les identifiants, l'inventaire et l'exécution des playbooks sans transformer le pipeline en un amas de commandes shell.
Ce guide présente une configuration pratique : Jenkins orchestre le pipeline, tandis qu'Ansible gère le déploiement et la configuration sur les hôtes cibles. Les exemples supposent des déploiements Linux via SSH, mais le même modèle fonctionne avec des inventaires et des rôles spécifiques à l'environnement.
Comment Jenkins et Ansible s'articulent
Avant d'écrire le pipeline, séparez les responsabilités :
- Jenkins : Récupère le code, construit les artefacts, exécute les tests, collecte les journaux et décide quand les étapes de déploiement sont lancées.
- Ansible : Se connecte aux hôtes cibles, copie les artefacts, écrit la configuration, gère les services et maintient les étapes de déploiement idempotentes.
Pourquoi intégrer Jenkins avec Ansible ?
Cette séparation offre à votre équipe une limite claire :
- Jenkins stocke le flux de livraison dans un
Jenkinsfile. - Ansible stocke les actions d'infrastructure dans des playbooks et des rôles.
- Les fichiers d'inventaire déterminent quels hôtes appartiennent à la préproduction, à la production ou à d'autres environnements.
- Les identifiants Jenkins protègent les clés SSH, les mots de passe Vault et les jetons.
Prérequis pour l'intégration
Avant de commencer, assurez-vous d'avoir :
- Un contrôleur Jenkins fonctionnel et au moins un agent capable d'exécuter des tâches de déploiement.
- Ansible installé sur l'agent Jenkins qui exécute
ansible-playbook. - Des machines cibles accessibles depuis cet agent via SSH.
- Une paire de clés SSH dédiée à l'automatisation.
- Le code de l'application, l'inventaire, les playbooks et les rôles dans un système de contrôle de version.
Configuration de Jenkins pour Ansible
Jenkins a besoin de deux choses avant de pouvoir exécuter Ansible en toute sécurité : l'environnement d'exécution Ansible sur un agent et les identifiants pour les hôtes cibles.
1. Installer le plugin Ansible
Vous pouvez appeler ansible-playbook directement depuis une étape shell, mais le plugin Ansible de Jenkins peut faciliter la configuration et la gestion des sorties.
- Accédez à
Manage Jenkins>Manage Plugins. - Allez dans l'onglet
Availableet recherchez "Ansible". - Sélectionnez le plugin "Ansible" et cliquez sur
Install without restartouDownload now and install after restart.
2. Configurer les identifiants SSH
Ansible utilisera SSH pour se connecter aux serveurs cibles. Stockez la clé privée dans les identifiants Jenkins plutôt que dans le dépôt.
- Allez dans
Manage Jenkins>Manage Credentials. - Sélectionnez le magasin d'identifiants utilisé par vos tâches.
- Cliquez sur
Add Credentials. - Choisissez
SSH Username with private key. - Définissez un ID stable, par exemple
ansible-ssh-key. - Saisissez le nom d'utilisateur SSH utilisé sur les machines cibles.
- Ajoutez la clé privée et enregistrez l'identifiant.
Astuce : Bonnes pratiques pour la gestion des clés
- Ne codez jamais en dur les clés privées SSH dans un Jenkinsfile, un inventaire ou un playbook.
- Utilisez des clés d'automatisation dédiées, pas des clés personnelles.
- Renouvelez les clés selon un calendrier correspondant à la politique de sécurité de votre équipe.
Conception de votre pipeline Jenkins avec Ansible
Utilisez un pipeline déclaratif dans un Jenkinsfile afin que la logique de déploiement soit examinée avec le code de l'application.
Structure de base du pipeline
Voici un exemple compact pour une construction, un déploiement en préproduction et un déploiement en production avec validation :
// Jenkinsfile
pipeline {
agent any
environment {
// Définir les variables d'environnement si nécessaire
ANSIBLE_HOST_KEY_CHECKING = 'False' // Soyez prudent en production, préférez known_hosts
}
stages {
stage('Checkout Source') {
steps {
git 'https://your-scm-url/your-repo.git'
}
}
stage('Build Application') {
// Cette étape peut construire un JAR, WAR, image Docker, etc.
// Exemple : construire un JAR Spring Boot
steps {
sh 'mvn clean package'
}
}
stage('Run Unit Tests') {
steps {
sh 'mvn test'
}
}
stage('Deploy to Staging') {
steps {
script {
// Utiliser l'agent SSH pour rendre la clé privée disponible à Ansible
sshagent(credentials: ['ansible-ssh-key']) {
// Exécuter le playbook Ansible
sh 'ansible-playbook -i inventory/staging.ini playbooks/deploy_app.yml \n -e "app_version=$(cat target/VERSION)"'
}
}
}
}
stage('Deploy to Production') {
// Cette étape peut nécessiter une approbation manuelle
input {
message "Procéder au déploiement en Production ?"
ok "Déployer en Production"
}
steps {
script {
sshagent(credentials: ['ansible-ssh-key']) {
sh 'ansible-playbook -i inventory/production.ini playbooks/deploy_app.yml \n -e "app_version=$(cat target/VERSION)"'
}
}
}
}
}
post {
always {
echo 'Pipeline terminé.'
}
success {
echo 'Pipeline réussi !'
// slackSend channel: '#deployments', message: "Déploiement réussi : ${env.BUILD_URL}"
}
failure {
echo 'Pipeline échoué !'
// slackSend channel: '#deployments', message: "Déploiement échoué : ${env.BUILD_URL}"
}
}
}
Détails clés du pipeline
agent anyfonctionne pour une démonstration. En production, utilisez un label d'agent garantissant qu'Ansible est installé.sshagent(credentials: ['ansible-ssh-key'])expose la clé privée uniquement à l'intérieur de ce bloc.ansible-playbook -i inventory/staging.ini playbooks/deploy_app.ymlrend l'environnement cible explicite.- Le bloc
inputde production ajoute une validation manuelle avant un déploiement sensible. - Évitez de désactiver la vérification de la clé d'hôte en production. Gérez plutôt
known_hostssur l'agent Jenkins.
Exemple de playbook Ansible : Déploiement d'une application web
Voici un inventory/staging.ini et un playbooks/deploy_app.yml simplifiés pour une application web Java. Le nom de votre artefact, votre gestionnaire de services et vos chemins peuvent différer.
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: Déployer l'application web
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: S'assurer que le répertoire de l'application existe
ansible.builtin.file:
path: "{{ app_path }}"
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0755'
- name: Copier le JAR de l'application vers la cible
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: redémarrer le service de l'application
- name: S'assurer que le fichier de service systemd existe
ansible.builtin.template:
src: templates/my-webapp.service.j2
dest: /etc/systemd/system/{{ app_name }}.service
owner: root
group: root
mode: '0644'
notify: redémarrer le service de l'application
- name: S'assurer que le service de l'application est démarré et activé
ansible.builtin.systemd:
name: "{{ app_name }}"
state: started
enabled: yes
handlers:
- name: redémarrer le service de l'application
ansible.builtin.systemd:
name: "{{ app_name }}"
state: restarted
daemon_reload: yes
templates/my-webapp.service.j2 (Modèle de service systemd)
[Unit]
Description=Application {{ app_name }}
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
Ce playbook crée le répertoire de l'application, copie le JAR construit, écrit une unité systemd et démarre le service. Le gestionnaire redémarre le service uniquement lorsque l'artefact ou le fichier d'unité change.
Bonnes pratiques et conseils
- Maintenez les playbooks idempotents afin que la réexécution d'un pipeline échoué ne cause pas de dommages supplémentaires.
- Stockez les mots de passe Vault dans les identifiants Jenkins et transmettez-les via un fichier de mot de passe temporaire ou une liaison d'identifiants approuvée.
- Organisez la logique de déploiement en rôles, comme
webserver,databaseetapp_deploy. - Utilisez des inventaires séparés ou des
group_varspour la préproduction et la production. - Exécutez Ansible sur des agents Jenkins dédiés, pas sur le contrôleur.
- Utilisez
-vou-vvuniquement lorsque vous avez besoin de plus de détails ; évitez de divulguer des secrets dans les journaux. - Testez les playbooks avant que Jenkins ne les exécute, en particulier pour les rôles de production.
Quand faire appel à un professionnel
Faites appel à un administrateur Jenkins ou de plateforme lorsque le pipeline déploie en production, gère des identifiants partagés, écrit sur de nombreux hôtes ou nécessite des contrôles d'audit. La gestion des identifiants, la vérification de la clé d'hôte et le comportement de restauration méritent une seconde vérification avant le premier déploiement en production.
À retenir
Utilisez Jenkins pour l'orchestration et Ansible pour l'état du déploiement. Conservez les identifiants dans Jenkins, les playbooks dans le contrôle de version, rendez l'inventaire explicite et testez les mêmes commandes Ansible en dehors du pipeline avant d'automatiser le déploiement en production.