Blog d'Obi Madu
Retour à tous les articles
InfrastructureDevOpsProjects

Déploiement automatique de Jenkins sur un serveur distant (avec SSL gratuit) via Ansible (Tutoriel)

Apprenez à déployer automatiquement un serveur Jenkins auto-hébergé avec des certificats SSL gratuits à renouvellement automatique à l'aide d'Ansible.

Déploiement automatique de Jenkins sur un serveur distant (avec SSL gratuit) via Ansible (Tutoriel)

Jenkins est l'un des outils de CI/CD (Intégration Continue et Déploiement Continu) les plus populaires. Il est très apprécié dans la communauté Tech car il est gratuit, open source et auto-hébergé. Il y a de nombreuses raisons pour lesquelles vous pourriez vouloir déployer un serveur Jenkins : pour construire des projets personnels, vous entraîner à utiliser le logiciel, pour une utilisation en production en entreprise, etc. Quelle que soit votre raison, une chose est sûre, déployer votre serveur avec Ansible rendra le processus automatique, reproductible, réutilisable, versionnable et partageable. Aujourd'hui, nous allons voir comment créer un playbook Ansible qui déploie Jenkins sur un serveur distant, avec un certificat SSL Let's Encrypt gratuit (qui se renouvelle automatiquement).

J'ai mis en ligne l'intégralité du code de ce projet ici sur Github.

C'est parti 🚀

1. Acquérir un Serveur Distant

La première étape pour déployer Jenkins sur un serveur consiste à acquérir le serveur lui-même. Un serveur distant peut être provisionné à partir de nombreux endroits différents. Les fournisseurs cloud tels que DigitalOcean, Google Cloud, AWS, etc., proposent certains des forfaits VPS (serveur privé virtuel) les plus rentables du marché. Selon vos besoins, vous pouvez provisionner un serveur manuellement ou via IaC (Infrastructure as Code) à partir de l'un de ces fournisseurs.

Pour les besoins de ce tutoriel, assurez-vous de provisionner votre instance de serveur avec un accès à l'internet public (et donc avec une adresse IPv4 publique).

Il est considéré comme une bonne pratique d'exécuter les commandes ansible sur un nœud via un utilisateur dédié. Pour accélérer le processus de création d'un utilisateur dédié avec les permissions appropriées pour Ansible, utilisez le script de démarrage userdata suivant pour lancer votre VPS.

#cloud-config
ssh_pwauth: false

users:
  - name: ansible
    gecos: Ansible User
    groups: users,admin,wheel
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    lock_passwd: true
    ssh_authorized_keys:
      - "ssh-public-key"

Remplacez "ssh-public-key" par la clé publique SSH appropriée pour la connexion à votre serveur.

2. Configuration pour Ansible

Avant de nous plonger dans la création de notre Playbook, nous devons configurer quelques éléments pour nous assurer que notre workflow réussira.

2.1 Vérifier la connectivité SSH au serveur distant

Ansible se connecte aux serveurs nœuds via SSH. Étant donné que nous traitons avec un seul serveur pour ce tutoriel, nous devrons nous y connecter initialement, manuellement, pour vérifier la connectivité.

Une partie du processus de déploiement d'un VPS consiste à configurer l'accès SSH vers celui-ci. Où que vous déployiez votre VPS, vous devriez avoir accès au fichier de clé privée pour la connexion SSH à votre serveur.
Initiez une connexion SSH à votre serveur en utilisant

ssh -i location/to/keyfile username@server_ip 

Assurez-vous de stocker votre clé privée SSH en toute sécurité sur votre hôte Ansible, et de garder une trace de son emplacement car elle sera utilisée à une étape suivante pour accorder à Ansible l'accès à votre VPS.

2.2 Configurer les enregistrements DNS pour notre domaine Jenkins

Afin d'assurer l'accès à votre serveur Jenkins depuis le domaine approprié, vous devez faire pointer votre nom de domaine vers l'adresse IP de votre Serveur. Cela sera accompli en créant un A record DNS. Cela peut être fait de différentes manières (via une variété d'interfaces) selon le Service de Noms de Domaine en charge de votre domaine. Les spécificités sortent du cadre de ce tutoriel.

Sans l'enregistrement DNS correctement défini, votre Playbook échouera à émettre un SSL pour votre serveur Jenkins car Certbot (le client utilisé pour émettre les certificats) sera incapable de vérifier que vous contrôlez le domaine pour lequel le certificat SSL sera émis. Cela provoquera l'échec de votre déploiement, alors assurez-vous de configurer l'enregistrement DNS approprié.

2.3 Créer un fichier de configuration Ansible

Pour fonctionner correctement, Ansible a besoin de quelques éléments importants configurés. Nous le faisons dans le fichier ansible.cfg. Ansible regarde ce fichier automatiquement avant l'exécution, pour trouver les choses importantes dont il a besoin pour fonctionner. Notre fichier ansible.cfg aura le contenu suivant.

[defaults]
inventory = inventory.txt
private_key_file = key.txt
remote_user = ansible

Ce fichier configure les éléments importants suivants :

  • Il indique à Ansible que notre fichier d'inventaire, le fichier qui liste les adresses de tous les serveurs que nous aimerions qu'Ansible gère, est un fichier nommé inventory.txt et se trouve dans le répertoire courant.
  • Il indique à Ansible que le fichier de clé privée pour la connectivité SSH à l'hôte est un fichier nommé key.txt, situé également dans le répertoire courant.
  • Il configure le nom d'utilisateur ansible pour la connexion SSH au serveur. Ce sera le cas si vous avez configuré votre serveur avec le script cloud-init fourni précédemment, sinon, n'hésitez pas à changer cette valeur pour ce qu'est votre username.

Conformément à cette configuration, vous devriez stocker le fichier de clé privée SSH pour la connexion au serveur dans un fichier appelé key.txt dans le répertoire courant, afin qu'Ansible puisse le trouver.

N'oubliez pas de NE PAS commiter votre fichier key.txt dans le contrôle de version. Surtout sur un dépôt public sur Github.

Une fois que vous avez vérifié la connectivité SSH à votre serveur, configuré l'enregistrement DNS approprié et créé un fichier de configuration, vous êtes prêt à créer votre Playbook.

3. Créer le Playbook

Il est temps de créer votre Playbook Ansible. Pour garder notre solution simple et modulaire, nous allons utiliser les rôles (roles) d'Ansible. Voici un résumé des étapes qui mènent à notre résultat souhaité :

  • Configurer un proxy Nginx pour Jenkins
  • Acquérir un certificat SSL pour notre serveur
  • Installer Jenkins


Maintenant en code :

---
- hosts: all
  become: true
  roles:
    - nginx-proxy

- hosts: all
  become: true
  roles:
    - certbot

- hosts: all
  become: true
  roles:
    - jenkins

4. Créer les Rôles associés

Ensuite, vous devez créer les rôles pour les différents aspects du workflow. La structure du répertoire pour vos rôles devrait ressembler à ceci :

tree

4.1 Dans le rôle nginx-proxy

Créer un fichier tasks/mail.yml

Avec le contenu suivant :

- name: Install NginX
  tags: nginx,install
  ansible.builtin.apt:
    name: nginx
    state: latest
    update_cache: true

- name: Enable NginX
  ansible.builtin.service:
    name: nginx
    enabled: true

- name: Config Jenkins Proxy
  ansible.builtin.template:
    src: "jenkins-proxy.j2"
    dest: /etc/nginx/sites-available/jenkins-proxy.conf
    owner: root
    group: root
    mode: 0644
  notify: restart_nginx

- name: Enable Proxy
  ansible.builtin.file:
    src: /etc/nginx/sites-available/jenkins-proxy.conf 
    dest: /etc/nginx/sites-enabled/jenkins-proxy.conf
    state: link
  notify: restart_nginx

Créer un fichier handlers/mail.yml

Avec le contenu suivant :

- name: restart_nginx
  ansible.builtin.service:
    name: nginx
    state: restarted

Créer un fichier templates/jenkins-proxy.j2

Avec le contenu suivant :

server { 

    listen 80; # Port for incoming traffic (e.g., 80 for HTTP, 443 for HTTPS)
    server_name {{ server_name }}; # Your domain name or IP address

    # Location block for handling proxied requests

    location / {
        proxy_pass {{ jenkins_localhost }}; # Upstream server address (e.g., http://127.0.0.1:8080)
        
        # Optional settings:
        
        proxy_set_header Host $host; # Preserve host header for upstream server
        proxy_set_header X-Real-IP $remote_addr; # Forward client IP address
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Forward proxy chain

        # Additional settings as needed (e.g., caching, rewrites)
    }

}

4.2 Dans le rôle certbot

Créer un fichier tasks/mail.yml

Avec le contenu suivant :

- name: Install Snapd
  ansible.builtin.apt:
    name: snapd
    state: latest

- name: Install Certbot
  community.general.snap:
    name: certbot
    classic: true
    state: present

- name: Create symlink    
  ansible.builtin.file:
    src: /snap/bin/certbot 
    dest: /usr/bin/certbot
    state: link

- name: Run certbot
  ansible.builtin.shell: 
    cmd: certbot --nginx -n --agree-tos --email {{ server_email }} --domains {{ server_name }}

4.3 Dans le rôle jenkins

Créer un fichier tasks/mail.yml

Avec le contenu suivant :

- name: Install JDK
  ansible.builtin.apt:
    pkg:
      - fontconfig
      - openjdk-17-jre

- name: Get Jenkins Repo Key
  ansible.builtin.get_url:
    url: https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
    dest: /usr/share/keyrings/jenkins-keyring.asc

- name: Set Jenkins Source
  ansible.builtin.lineinfile:
    path: /etc/apt/sources.list.d/jenkins.list
    line: deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/
    create: yes

- name: Install Jenkins
  ansible.builtin.apt:
    name: jenkins
    state: present
    update_cache: true

- name: Enable Jenkins
  ansible.builtin.service:
    name: jenkins
    enabled: true

5. Configurer les sorties de débogage de Jenkins

La toute première fois que vous configurez votre serveur Jenkins, pour commencer à utiliser l'interface web, vous devez récupérer une clé secrète dans un fichier sur le serveur Jenkins, pour prouver que vous contrôlez le serveur. Nous pouvons récupérer cette clé et faire en sorte qu'Ansible nous l'affiche en ajoutant les lignes suivantes à notre fichier role/jenkins/tasks/main.yml :

- name: Check Jenkins Status
  ansible.builtin.shell:
    cmd: systemctl status jenkins
  register: check_jens

- name: Debug
  debug:
    msg: "{{ check_jens.stdout_lines }}"

Cet ajout affiche la valeur de

systemctl status jenkins

6. Déployer votre playbook

C'est ici que vous déployez votre Playbook, et que Jenkins s'installe automatiquement pour vous. Pour déployer votre Playbook, vous devez fournir des valeurs appropriées aux 3 variables définies à travers nos rôles.

  • La variable {{jenkins_localhost}} pointe vers l'adresse localhost de Jenkins. C'est typiquement http://localhost:8080
  • La variable {{server_name}} fournit le nom de domaine sur lequel le serveur Jenkins doit être accessible. Il s'agit du domaine pour lequel vous avez précédemment configuré les enregistrements DNS.
  • La variable {{server_email}} fournit l'adresse e-mail de l'administrateur du serveur (ceci est requis).

Vous pouvez choisir de fournir la valeur de ces variables de différentes manières. Vous pourriez les fournir lors de l'exécution, auquel cas vous déploieriez votre Playbook avec la commande ci-dessous :

ansible-playbook --extra-vars "server_name=domain-name jenkins_localhost=http://127.0.0.1:8080 
server_email=email" playbook.yml 

En remplaçant domain-name et email par les valeurs appropriées.

Voici un exemple :

ansible-playbook --extra-vars "server_name=jen.obimadu.pro 
jenkins_localhost=http://127.0.0.1:8080 
server_email=hello@obimadu.pro" playbook.yml

Pour d'autres façons de fournir la valeur des variables, visitez Using Variables

ET C'EST TOUT 🎉 🎉 Vous disposez maintenant d'un moyen entièrement automatisé pour déployer (et/ou redéployer) votre Serveur Jenkins !