Mise en place d'un pipeline CICD avec Jenkins & Ansible, pour la stack Odoo, PostgreSQL, pgAdmin

Photo by JJ Ying on Unsplash

Mise en place d'un pipeline CICD avec Jenkins & Ansible, pour la stack Odoo, PostgreSQL, pgAdmin

Table of contents


LinkedIn | GitLab | GitHub | Credly


1. Introduction

Le déploiement continu et l'intégration continue (CI/CD) sont des pratiques essentielles dans le développement de logiciels modernes, permettant aux équipes de livrer des applications avec plus de rapidité, fiabilité et sécurité. Ce projet vise à établir un pipeline CI/CD utilisant Jenkins et Ansible pour automatiser le déploiement de plusieurs applications, incluant Odoo, PostgreSQL, pgAdmin, et une application web personnalisée nommée ic-webapp.

1.1. Objectifs

Le principal objectif de ce lab est de mettre en place une infrastructure automatisée qui permettra non seulement d'accélérer le processus de déploiement des mises à jour logicielles mais aussi de minimiser les risques d'erreurs humaines. Cela sera bénéfique pour améliorer la continuité des opérations commerciales et optimiser la gestion des ressources. Plus précisément, le projet vise à :

- Automatiser : Automatiser le processus de déploiement des applications pour garantir des livraisons rapides et sans erreur.

- Sécuriser : Assurer que toutes les configurations et les déploiements se font dans un environnement sécurisé pour protéger les données et les services.

- Documenter : Fournir une documentation claire et détaillée qui peut être utilisée pour la maintenance et l'évolution future du système.

1.2. Aperçu des technologies utilisées

Pour atteindre ces objectifs, le pipeline CI/CD sera construit en utilisant :

- Jenkins : Un serveur d'automatisation open source qui offre un large éventail de plugins pour supporter la construction et le déploiement de divers projets logiciels.

- Ansible : Un outil d'automatisation qui permet de configurer des systèmes, déployer des logiciels, et orchestrer des tâches plus avancées telles que la gestion de la configuration continue.

- Docker : Utilisé pour la conteneurisation des applications, garantissant ainsi que les logiciels fonctionnent de manière uniforme et cohérente à travers différents environnements de développement et de production.

- Git : Système de contrôle de version pour gérer les changements dans les documents, les programmes, et d'autres collections d'informations liées au développement du logiciel.

- Terraform : Terraform est un outil de gestion d'infrastructure sous forme de code (Infrastructure as Code - IaC) développé par HashiCorp.

1.3. Aperçu de l'Architecture

Le pipeline sera configuré pour gérer les déploiements sur trois serveurs différents, chacun hébergé sur le cloud (AWS) ou en On Premises, selon la préférence et les ressources disponibles. Chaque serveur jouera un rôle spécifique dans l'architecture globale :

- Serveur Jenkins : Gère l'intégration et le déploiement continu des applications.

- Serveur Applications : Héberge les applications web ic-webapp et pgAdmin.

- Serveur Odoo : Exécute l'application de gestion Odoo et sa base de données PostgreSQL.

- Un nœud Jenkins : C'est une instance qui permettra d'étendre les capacités de l'instance Jenkins maître. cet agent permettra d'exécuter les tâches assignées par l'instance maître et permettent une distribution efficace des charges de travail

La documentation suivante détaillera chaque aspect du pipeline, de l'installation et la configuration des outils à la création et l'exécution des scripts de déploiement, en passant par la gestion des erreurs et des versions.

2. Prérequis

Avant de mettre en place le pipeline CI/CD avec Jenkins, Docker, Ansible, et Terraform pour le déploiement de la stack Odoo, Postgres, pgAdmin, et une application Python, il est essentiel de s'assurer que tous les prérequis suivants sont correctement installés et configurés :

2.1. Configuration des serveurs

1. Serveur Jenkins : Une instance (AWS t2.medium recommandé) où Jenkins sera installé, qui servira à orchestrer le pipeline CI/CD.

2. Serveur Applications : Une instance (AWS t2.micro recommandé) pour héberger les applications web vitrine ic-webapp et pgAdmin.

3. Serveur Odoo : Une instance (AWS t2.micro recommandé) qui sera dédiée à l'application Odoo et la base de donnée sous Postgres.

4. Un nœud Jenkins : C'est une instance qui permettra d'étendre les capacités de l'instance Jenkins maître. cet agent permettra d'exécuter les tâches assignées par l'instance maître et permettent une distribution efficace des charges de travail

Chaque serveur doit disposer d'une connectivité réseau appropriée (SSH avec clés, acces via le protocole TCP dans les ingress ...).au niveau des security groups

2.2. Logiciels nécessaires (Jenkins, Docker, Ansible, Git)

1. Jenkins : Une instance Jenkins doit être préinstallé et configuré pour gérer les jobs et orchestrer le pipeline. >> Comment installer Jenkins

2. Docker : Docker doit être installé sur les instance pour permettre la conteneurisation des applications. Cela inclut Docker Engine et, Docker Compose pour gérer les applications multi-conteneurs (nous utiliserons Ansible pour simplifier cette tache). >> Comment installer Docker

3. Ansible : Ansible est utilisé pour l'automatisation de la configuration et du déploiement des applications sur les serveurs. Il doit être installé sur le serveur Jenkins pour exécuter les playbooks. >> Comment installer Ansible

4. Git : Nécessaire pour le versionnage des codes source et des configurations d'infrastructures. Git doit être installé sur le serveur Jenkins pour permettre le clonage des dépôts et la gestion des versions. Terraform (optionnel) : Si utilisé, Terraform doit être configuré pour gérer l'infrastructure sous forme de code, ce qui permet un déploiement et une gestion dynamiques des ressources cloud.

5. Terraform : (optionnel), installé sur une machine tièrce, nous perettra de provisionner les défferentes instances dont nous aurons besoin. >> Comment installer Terraform

2.3. Connaissances Requises

Compréhension de CI/CD : Une compréhension de base des concepts de l'intégration continue et du déploiement continu.

Base en scriptage : Connaissance en Bash pour scripts shell et en YAML pour les configurations Docker et Ansible.

Administration système : Compétences en gestion de systèmes Unix/Linux, notamment pour la configuration réseau, la gestion des processus, et la surveillance.

Gestion de réseau : Connaissance des concepts réseau de base, essentiels pour configurer correctement les interactions entre les différents services et applications.

3. Configuration de l'Infrastructure

3.1. Provisionner des instances à l'aide de terraform avec gitlab comme outil de remote state

Dans ce depôt, vous retrouverez des explication sur comment utiliser les modules terraform proposer pour provisionner une instance ec2 en utilisant gitlab comme remote state manager ou même la solution s3 de AWS pour le même rôle :

\>> Provisionner une instance ec2 grâce à Terraform

3.2 Préparation de Jenkins

3.2.1. Installation de Jenkins

Pour l'installation de Jenkins, se référer à la documentation : Installation de Jenkins sur une instance ec2 (AWS)

3.2.2. Configuration de l'agent Jenkins (slaves)

La configuration des agents Jenkins, également appelés "nœuds" ou "slaves", est une étape cruciale pour étendre les capacités d'un instance Jenkins maître. Ces agents exécutent les tâches assignées par l'instance maître et permettent une distribution efficace des charges de travail, surtout lors de l'exécution de plusieurs jobs ou de jobs particulièrement lourds. La mise en place correcte des agents assure une meilleure scalabilité et optimisation des ressources dans un environnement CI/CD.

Pour mettre en œuvre cette solution, nous allons provisionner, grace à terraform une nouvelle instance qui servira de noeud à l'instance master Jenkins en utilisant le IaaC terraform proposé plus haut, où en provisionnant une instance manuellement dépuis la console aws

Installation de Java

Une fois connecté en ssh à notre instance ec2 qui devra servir de noed, entrez les commandes suivantes depuis le terminal

sudo apt update
sudo apt install openjdk-11-jdk -y

3.2.3. Configuration de Jenkins

Plugin requis

Installer le plugins : SSH Build Agents

Ce plugin permet à Jenkins de se connecter et de lancer des agents sur des machines distantes via SSH.

Crédentials

  1. Se rendre dans "Manage Jenkins" > "Manage Credentials".

  2. Ajoutez une nouvelle credential de type "SSH Username with private key".

  3. Entrez le nom d'utilisateur de votre instance EC2 et la clé privée que vous avez configurée pour l'accès SSH.

Enregistrement d'un credential sous Jinkins

Ajouter un nouvel agent

  1. Allez dans "Manage Jenkins" > "Manage Nodes and Clouds".

  2. Cliquez sur "New Node".

  3. Entrez un nom pour le nœud, sélectionnez "Permanent Agent", puis cliquez sur "Create".

Création d'un node sous Jenkins

Configurez les paramètres de l'agent :

  1. Remote root directory: Un chemin dans lequel Jenkins peut exécuter des builds (/home/ubuntu/jenkins_path).

  2. Labels: Des étiquettes pour identifier l'agent.

  3. Usage: Déterminez comment cet agent sera utilisé (exclusivement ou laissé à Jenkins pour décider).

  4. Launch method: Sélectionnez "Launch agents via SSH".

  5. Host: L'adresse IP ou le DNS de votre instance EC2.

  6. Credentials: Sélectionnez les credentials SSH que vous avez créés.

  7. Host Key Verification Strategy: Choisissez "Non verifying Verification Strategy" pour simplifier, mais pour plus de sécurité, il est recommandé de configurer une stratégie de vérification.

Lancement de l'agent

Une fois tout configuré, Jenkins essaiera de se connecter à l'instance EC2 et de démarrer l'agent lorsqu'un build doit être exécuté sur ce nœud. Vous pouvez vérifier le statut de l'agent dans la section "Manage Nodes and Clouds" pour vous assurer qu'il est connecté correctement.

Agent Jenkins en ligne

3.3. Configuration du gestion SCM

se rendre dans l'option ConfigureTools où à l'adresse : public_ip_address_jenkins_instance/configur..

Mettre à jour le repertoire de git pour la prise en charge du build

4. Développement du Pipeline (CI)

4.1. Structure générale du pipeline (stages)

Structure Générale du Pipeline CI/CD

La mise en place d'un pipeline CI/CD pour la solution Odoo, PostgreSQL, pgAdmin, et une application web vitrine nécessite une structuration claire et détaillée des étapes de build, test, release et déploiement.

Voici un aperçu de la structure générale du pipeline qui sera implémentée dans Jenkins pour automatiser l'ensemble du processus de développement et de déploiement.

Stages du Pipeline

Initialisation :

Checkout : Récupération du code source depuis le système de gestion de version. Préparation de l'environnement : Installation des dépendances nécessaires pour le build et le test.

Build :

Construction des images Docker : Pour l'application vitrine une image Docker est construite en utilisant un Dockerfiles spécifique.

Tests :

health check : Exécution d'une commande shell pour vérifier la disponibilité du service une fois le conteneur test lancée.

Release :

Tagging des images : Attribution de tags à l'images Docker construite, en utilisant un identifiants de version ou des hashes de commit pour la traçabilité de la release. Push des images : Envoi des images vers un registre Docker pour stockage et récupération lors du déploiement.

Déploiement :

Déploiement : Déploiement de chaque stack (odoo+postgres et pgadmin+ic-webapp) sur les serveurs de production distinct.

Intégration et Déploiement Continus

Le pipeline est conçu pour permettre une intégration et un déploiement continus, où chaque commit dans le dépôt de code (Gitlab) déclenche automatiquement un nouveau cycle de ce pipeline. Cette automatisation assure que toutes les modifications sont rapidement testées et prêtes à être déployées, minimisant ainsi le temps de mise en marché et augmentant la réactivité aux besoins des utilisateurs.

4.2. Détails de chaque étape du pipeline

4.2.1 Déclaration des variables

Dans le Jenkinsfile, la section des variables d'environnement joue un rôle crucial en définissant les paramètres qui seront utilisés à travers les différentes étapes du pipeline.

   environment {
        IMAGE_NAME = "ic-webapp"
        IMAGE_TAG = "latest"
        LOCAL_TAG = "1.0"
        IP_ANSIBLE = "18.211.168.237"
        IP_ODOO = "54.226.148.2"
        IP_PGADMIN = "54.209.185.19"
        JENKINS_PATH = "jenkins_path"
        USER_SERVER = "ubuntu"
        REPO_ODOO = "https://gitlab.com/CarlinFongang-Labs/projet-odoo/deploy-odoo-postgresql-pgadmin/odoo-postgresql-ansible.git"
        REPO_PGADMIN = "https://gitlab.com/CarlinFongang-Labs/projet-odoo/deploy-odoo-postgresql-pgadmin/pgadmin-webapp-with-ansible.git"
    }
    agent {
        label 'runner_ec2_aws'
    }

Voici une explication de chaque variable et son importance dans le processus de CI/CD :

Variables générales

IMAGE_NAME: Nom de l'image Docker qui sera construite et déployée. Cela permet de personnaliser et de reconnaître facilement l'image au sein des registres Docker.

IMAGE_TAG: Tag de l'image Docker pour la version la plus récente. Utiliser latest permet de s'assurer que la dernière version de l'image est toujours utilisée là où c'est nécessaire.

LOCAL_TAG: Une version spécifique de l'image, ici "1.0", qui peut être utilisée pour assurer un suivi de versions spécifiques ou pour des déploiements ciblés.

IP_ANSIBLE, IP_ODOO, IP_PGADMIN: Adresses IP des serveurs sur lesquels les différentes applications seront déployées. Ces adresses permettent à Ansible de cibler correctement les machines pour le déploiement

Chemins et références

JENKINS_PATH: Le chemin dans le système de fichiers où Jenkins stocke les données de travail. Cela peut inclure des scripts, des fichiers temporaires ou des configurations spécifiques à Jenkins.

USER_SERVER: Nom d'utilisateur utilisé pour les connexions SSH lors des déploiements Ansible. Typiquement, ubuntu est le nom d'utilisateur par défaut pour les instances EC2 Ubuntu sur AWS.

Références de répertoire Git

REPO_ODOO: URL du dépôt Git contenant les configurations et les scripts Ansible pour déployer l'application Odoo. Ce lien est essentiel pour permettre au pipeline de récupérer les dernières configurations et scripts nécessaires au déploiement. REPO_PGADMIN: URL du dépôt Git pour les configurations de pgAdmin. Cela assure que les scripts et configurations nécessaires pour déployer pgAdmin sont accessibles et à jour.

Configuration de l'agent Jenkins

agent { label 'runner_ec2_aws' }: Définit l'agent Jenkins qui exécutera le pipeline. Ici, runner_ec2_aws fait référence au label assigné à un notre agents Jenkins configurés précédement et qui fonctionne dans un environnement AWS. Cela garantit que les tâches du pipeline sont exécutées dans l'environnement approprié.

4.2.2. Build: Création de l'image Docker

La phase de build est une étape crutiale dans notre pipeline CI/CD où le code source de notre application est transformé en un artefact. Pour notre application vitrine, cette phase est orchestrée à l'aide de Docker, qui nous permet de construire une image contenant tout le nécessaire pour exécuter notre application.

4.2.3. Déclaration des secrets

Pour renseigner des secrets dans Jenkins et les utiliser de manière sécurisée dans des pipelines, nous pouvons configurer et utiliser les secrets comme des mots de passe, des clés SSH, des tokens API, et d'autres informations sensibles :

1: Accéder aux Credentials dans Jenkins Allez dans le menu principal, cliquez sur "Manage Jenkins". Choisissez "Manage Credentials".

2: Choisir le Scope des Credentials Sous "Stores scoped to Jenkins", cliquez sur "(global)" pour définir les credentials qui sont accessibles à tous les jobs, ou choisissez un domaine spécifique si vous voulez restreindre l'accès à certains jobs ou pipelines.

3: Ajouter un Nouveau Credential

  • Cliquez sur "Add Credentials" sur le côté gauche.

  • Choisissez le type de credentials que vous souhaitez ajouter. Les options courantes incluent :

  • Username with password – pour les combinaisons nom d'utilisateur/mot de passe.

  • Secret text – pour les tokens API ou les secrets arbitraires.

  • SSH Username with private key – pour les connexions SSH sécurisées.

  • Certificate – pour l'authentification basée sur certificat.

  • Remplissez les champs nécessaires, tels que :

  • Scope: Choisissez "Global" (accessible de partout) ou "Jenkins" (limité à des jobs spécifiques).

  • ID: Laissez ce champ vide pour autogénérer un ID, ou entrez un identifiant personnalisé.

  • Description: Fournissez une description claire pour identifier ce credential dans la liste.

  • Username, Password/Secret, Private Key, etc., selon le type de credential ajouté.

\>\> Découvrez comment créer un token éphémère Dockerhub

Description du Dockerfile

Le Dockerfile défini pour une application utilisant Python 3.6 basé sur une image Alpine Linux, cette image est choisie car offre une grande légèreté et une bonne sécurité. Voici les étapes détaillées du processus de build :

ARG version="3.6-alpine"
FROM python:${version}

LABEL desciption="ic-webapp"
LABEL maintainer="Carlinfg <fongangcarlin@gmail.com>"

WORKDIR /opt

# Installer Flask and git
RUN apk update && \
    apk add --no-cache git bash gawk && \
    pip install Flask

RUN git clone https://github.com/LaboCloud/ic-webapp.git /opt


# Copy the releases.txt file into the working directory
COPY releases.txt /opt/releases.txt
COPY env_vars.sh /opt/env_vars.sh

# Permissions
RUN chmod +x /opt/env_vars.sh && \
    chmod +x env_vars.sh

# Set environment variables
ENV ODOO_URL=$ODOO_URL
ENV PGADMIN_URL=$PGADMIN_URL

# Port
EXPOSE 8080

# Start
ENTRYPOINT ["sh", "-c", "source /opt/env_vars.sh", "-s"]
CMD ["python", "app.py"]

1. Base et dépendances :

Image de base : L'image de base est python:3.6-alpine. Alpine est choisie pour sa simplicité et sa petite taille.

Installation de Dépendances : Installation de Git, Bash et Gawk. Ces outils sont nécessaires pour cloner le répertoire du projet et exécuter des scripts shell.

2. Récupération du code source :

Le code source de l'application est cloné depuis un dépôt Git externe directement dans le répertoire de travail /opt du conteneur.

3. Configuration de l'environnement :

Fichiers de configuration : Les fichiers releases.txt et env_vars.sh sont copiés dans le conteneur. Ces fichiers contiennent respectivement les variables de configuration et un script pour initialiser ces variables d'environnement.

Permissions : Des permissions d'exécution sont attribuées au script env_vars.sh pour assurer sa bonne exécution. Variables d'Environnement : Les variables ODOO_URL et PGADMIN_URL sont définies dans l'environnement du conteneur à partir des valeurs extraites par le script env_vars.sh.

4. Exposition de port et démarrage :

Le port 8080 est exposé pour permettre l'accès à l'application depuis l'extérieur du conteneur.

ENTRYPOINT ["sh", "-c", "source /opt/env_vars.sh", "-s"] : Le conteneur est configuré pour exécuter le script env_vars.sh au démarrage, suivi de la commande python app.py pour démarrer l'application Flask.

Description du script "env_vars.sh"

Ce script Bash, destiné à être utilisé dans notre conteneur, il nous permet de gère les variables d'environnement pour les URL de d'Odoo et pgAdmin, en fonction de leur présence dans un fichier de configuration releases.txt.

présente brièvement ce script 

#!/bin/bash
releases_file_path="/opt/releases.txt"

if test -f "$releases_file_path"; then
   export ODOO_URL=$(awk -F ': ' '/ODOO_URL/ {print $2}' $releases_file_path)
   export PGADMIN_URL=$(awk -F ': ' '/PGADMIN_URL/ {print $2}' $releases_file_path)
else
   echo "Les URL par défaut des variables ODOO_URL and PGADMIN_URL, vont être utilisées"
fi

exec "$@"

Une fois les instances destinées à accueillir Odoo et pgAdmin provisionnées et les adresses IP connues, nous pourrons renseigner ces IP/EIP dans le fichier releases.txt afin que ces dernieres soient prise en compte et embarquées dans l'image docker lors de la phase de build dans le pipeline Jenkins.

Notre fichier releases.txt se présente sous le formation suivant :

ODOO_URL: http://54.226.148.2:8090
PGADMIN_URL: http://54.209.185.19:8080
VERSION: 2.0

pour mettre en œuvre la tache de build du Dockerfile préalablement défini dans un pipeline Jenkins, nous allons rédiger un script groovy approprié à cette tâche :

        stage('Build image') {
            steps {
                script {
                    sh 'which git'
                    sh 'docker build -t $IMAGE_NAME:$LOCAL_TAG .'
                }
            }
        }

4.2.4. Test d'acceptation

Dans la phase de "Test d'acceptation" de notre pipeline Jenkins, l'application est d'abord déployée dans un environnement de conteneur isolé pour simuler son comportement en production et ensuite testé.

        stage('Run contenair') {
            //agent { docker { image 'alpine' } }
            steps {
                script {
                    sh 'docker run -d -p 8080:8080 --name $IMAGE_NAME-test $IMAGE_NAME:$LOCAL_TAG'
                    sh 'sleep 5'
                    sh 'sudo apt install curl -y'
                }
            }
        }
        stage('Test image') {
            agent any
            steps {
                script {
                    sh '''
                        docker ps
                        IP_TEST=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$IMAGE_NAME-test")
                        response=$(curl -s -o /dev/null -w "%{http_code}" "http://$IP_TEST:8080")
                        if [ "$response" -eq 200 ]; then
                            echo "La connexion au conteneur est réussie."
                        else
                            echo "Erreur: La connexion au conteneur a échoué avec le code de réponse HTTP $response."
                        fi
                    '''  
                }
            }
        }

Voici les étapes principales :

Lancement du conteneur : Un conteneur Docker est démarré à partir de l'image construite précédemment, exposant l'application sur le port spécifié.

Installation de Curl : Curl est installé pour faciliter les tests HTTP, permettant de faire des requêtes simples pour tester la connectivité et la réponse de l'application.

Validation du service :

  • Récupération de l'IP : L'adresse IP interne du conteneur est récupérée, ce qui est utilisé pour adresser les requêtes de test.

  • Requête HTTP : Une requête HTTP est envoyée à l'application via la commande Curl. Le code de réponse HTTP est vérifié pour s'assurer qu'il est égal à 200, indiquant que l'application répond correctement et est prête pour le déploiement. Si le code est différent, une erreur est signalée indiquant un échec de connexion.

4.2.5 Stop Test: Nettoyage post-tests

        stage('Clean Test') {
            agent any
            steps {
                script {
                    sh '''
                        docker stop ${IMAGE_NAME}-test && docker rm ${IMAGE_NAME}-test
                    '''
                }
            }
        }

Le stage "Clean Test" dans notre pipeline Jenkins permet de maintenir un environnement de build propre et gérer efficacement les ressources. Ce stage est spécifiquement mis en place pour nettoyer les conteneurs Docker qui ont été utilisés pour les tests, assurant qu'aucun artefact ou état résiduel ne compromet les exécutions futures du pipeline.

4.2.6. Release: tag des images et gestion des versions

Le stage "Release Docker image" joue un rôle central dans notre pipeline de CI/CD en s'assurant que l'image Docker construite et testée est publiée sur DockerHub. Ce processus permet de rendre les images disponibles pour un déploiement ultérieur sur différents environnements ou pour être utilisées par d'autres parties prenantes du projet.

        stage('Release Docker image') {
            environment {
                DOCKERHUB_USER = credentials('DHUB_USER')
                DOCKERHUB_TOKEN = credentials('DHUB_TOKEN')        
            }
            agent any
            steps {
                script {                    
                    sh 'docker tag $IMAGE_NAME:$LOCAL_TAG $DOCKERHUB_USER/$IMAGE_NAME:$IMAGE_TAG'
                    sh 'docker tag $IMAGE_NAME:$LOCAL_TAG $DOCKERHUB_USER/$IMAGE_NAME:$GIT_COMMIT'
                    sh 'echo $DOCKERHUB_TOKEN | docker login -u $DOCKERHUB_USER --password-stdin'
                    sh 'docker push $DOCKERHUB_USER/$IMAGE_NAME:$IMAGE_TAG'
                    sh 'docker push $DOCKERHUB_USER/$IMAGE_NAME:$GIT_COMMIT'  
                    sh 'echo "Publication de l image sur DockerHub..." '
                }
            }
        }

5. Utilisation d'Ansible pour le déploiement (CD)

5.1. Création des rôles Ansible pour Odoo, postgres, pgAdmin et ic-webapp

5.1.1. Utilisation des docker-compose dans Ansible pour la création d'un role, playbook odoo et postgres

Description du role odoo

Organisation des répertoires du rôle

5.1.2 Structure du role Ansible pour Odoo

1. Variables (vars/main.yml et defaults/main.yml):

vars/main.yml: Contient les configurations spécifiques nécessaires pour le déploiement, comme les images Docker pour Odoo et PostgreSQL, les ports, et les volumes.

defaults/main.yml: Définit les valeurs par défaut qui peuvent être utilisées globalement ou surchargées spécifiquement lors de l'exécution du playbook.

2. Template Docker Compose (templates/odoo-template.yml.j2):

Ce fichier est un modèle Jinja2 pour Docker Compose qui configure les services Odoo et PostgreSQL. Il inclut des directives pour les volumes, les réseaux, et les secrets nécessaires pour sécuriser la communication entre les services.

version: '3.7'

services:
  odoo_web_service:
    image: {{ ODOO_IMAGE }}
    depends_on:
      - db
    ports:
      - "{{ ODOO_PORT }}:8069"
    volumes:
      - "{{ ODOO_DATA_VOLUME }}:/var/lib/odoo"
      - "{{ ODOO_CONFIG_VOLUME }}:/etc/odoo"
      - "{{ ODOO_ADDONS_VOLUME }}:/mnt/extra-addons"
    networks:
      - odoo_network
    environment:
      - PASSWORD_FILE=/run/secrets/postgresql_password
    secrets:
      - postgresql_password
    restart: always

  db:
    image: {{ POSTGRES_IMAGE }}
    environment:
      - POSTGRES_DB={{ POSTGRES_DB }}
      - POSTGRES_PASSWORD_FILE=/run/secrets/postgresql_password
      - POSTGRES_USER={{ POSTGRES_USER }}
      - PGDATA=/var/lib/postgresql/data/pgdata
    volumes:
      - "{{ POSTGRES_DATA_VOLUME }}:/var/lib/postgresql/data/pgdata"
    secrets:
      - postgresql_password
    networks:
      - odoo_network
    restart: always

networks:
  odoo_network:
    driver: bridge

volumes:
  {{ ODOO_DATA_VOLUME }}:
  {{ POSTGRES_DATA_VOLUME }}:

secrets:
  postgresql_password:
    file: {{ POSTGRES_PASSWORD_FILE }}

ce template reprend intégralement la structure d'un docker compose conventionnel et intègre des variable ansible, ce qui le rend flexible et réutilisable selon le contexte

  1. Tâches Ansible (tasks/main.yml):

Création du répertoire Docker Compose:

- name: Ensure the Docker Compose directory exists
  ansible.builtin.file:
    path: "{{ odoo_compose_directory }}"
    state: directory

Cette tâche crée le répertoire où le fichier Docker Compose sera stocké et ensuite exécuté, cela permet de s'assurer de l'emplacement du fichier avant toutes actions futures

Gestion des secrets

- name: Ensure odoo_pg_pass exists
  ansible.builtin.file:
    path: "{{ POSTGRES_PASSWORD_FILE }}"
    state: touch
    mode: '644'
  become: true

Cette tache permet de s'assure que le fichier contenant le mot de passe PostgreSQL existe et est accessible.

Déploiement de la configuration Docker Compose:

- name: Deploy Odoo Compose configuration
  ansible.builtin.template:
    src: "{{ odoo_compose_file }}"
    dest: "{{ odoo_compose_directory }}/odoo-compose.yml"
  become: true

Cette tache permet de déployer le fichier Docker Compose dans le répertoire spécifié en utilisant le template Jinja2 précédent.

Exécution de Docker Compose

- name: Run Docker Compose
  ansible.builtin.shell:
    chdir: "{{ odoo_compose_directory }}"
    cmd: "docker-compose -f odoo-compose.yml up -d"
  become: true

Lance les services spécifiés dans le fichier Docker Compose, démarrant ainsi les conteneurs pour Odoo et PostgreSQL.

Pour en savoir plus : Le role odoo et postgres est disponible sur le dépôt via ce lien

Vous pourrez y consulter les variables utilisées ainsi que leurs roles et comment les ajuster

Déploiement de la stack Odoo

Pour mettre en œuvre le stage correspondant au déploiement de la stack Odoo, ayant le role déjà disponible, nous avons commencé par rédigé un playbook, qui à été intégré par la suite dans le stage

Description du playbook odoo-deploy.yml

Organisation du playbook Odoo

Le playbook Ansible décrit ci-dessous est conçu pour orchestrer le déploiement de l'application Odoo en utilisant le roles qui à été mis en place à cet effet et qui facilitent la configuration et la mise en service des instances nécessaires. Ce playbook est structuré en deux phases principales :

vérification de la connectivité SSH via le role check_ssh", l'installation de docker et docker-compose via le role "prepare_docker" et la configuration du déploiement d'Odoo via le role "odoo_deploy".

---
- name: Verify SSH Connectivity on Dynamic Hosts
  hosts: dynamic_hosts
  gather_facts: no
  roles:
    - check_ssh

- name: Setup Odoo
  hosts: dynamic_hosts
  vars_files:
    - group_vars/all.yml
  roles:
    - prepare_docker
    - odoo_deploy

fichier odoo-deploy.yml

Notez que ce playbook à la particularité d'embarquer une variable ansible dans le fichier hosts.yml, cette variable permet de récupérer l'adresse IP de l'instance sur laquelle sera déployé le stack au moment de l'exécution de celle-ci.

all:
  children:
    dynamic_hosts:
      vars:
        ansible_user: "{{ USER_SERVER }}"
      hosts:
        prod:
          ansible_host: "{{ lookup('env', 'IP_ODOO') }}"

fichier hosts.yml

Pour en savoir plus sur le playbook ainsi que son utilisation : Dépôt du playbook permettant de déployer la stack Odoo+Postgres

5.1.3 Utilisation des docker-compose dans Ansible pour la création d'un role, playbook pgAdmin et ic-webapp

De la même façon que que le role odoo_deploy ainsi que le playbook odoo-deploy ont été mis en œuvre, nous avons repris intégralement le même process pour l'élaboration des role et playbook ansible de la stack pgAdmin et ic-webapp

Pour en savoir plus sur le role pgadmin_deploy ainsi que son utilisation

Pour en savoir plus sur le playbook pgadmin-deploy ainsi que son utilisation

6 Automatisation des déploiements

6.1. Jobs Jenkins pour le déploiement d'Odoo et PGAdmin

6.1.1. Description du stage pour le déploiement de la stack Odoo

Ce stage à pour objectif d'automatiser le déploiement de la pile comprenant l'application Odoo et la base de données PostgreSQL sur une instance ec2 spécifié par la variable IP_ODOO dans le fichier hosts.yml.

        stage('Deploy stack Odoo_Postgres') {
            environment {
                SSH_EC2 = credentials('SSH_EC2')
            }
            steps {
                script { 
                    sh'''
                        export PATH=$PATH:/home/ubuntu/.local/bin
                        rm -rf odoo-stack-deploy
                        git clone $REPO_ODOO ./odoo-stack-deploy
                        cd odoo-stack-deploy

                        ansible-galaxy install -r roles/requirements.yml -f
                        chmod 600 $SSH_EC2

                        ssh -o StrictHostKeyChecking=no -i $SSH_EC2 ${USER_SERVER}@${IP_ODOO} "
                        rm -rf .secrets
                        mkdir .secrets
                        echo "odoo" > .secrets/odoo_pg_pass
                        "

                        ansible-playbook -i hosts.yml odoo-deploy.yml --private-key $SSH_EC2 -vvv  
                    '''
                }
            }
        }

6.1.2. Description du stage pour le déploiement de la stack pgAdmin

Ce stage à pour objectif d'automatiser le déploiement de la pile comprenant l'application pgAdmin et le site vitrine ic-webapp dont l'image à été buildé à l'entrée du pipeline, ceci sur une instance ec2 spécifié par la variable IP_PGADMIN dans le fichier hosts.yml.

        stage('Deploy stack PGAdmin_IC_WebApp') {
            environment {
                SSH_EC2 = credentials('SSH_EC2')
            }
            steps {
                script { 
                    sh'''
                        export PATH=$PATH:/home/ubuntu/.local/bin
                        rm -rf pgadmin-stack-deploy
                        git clone $REPO_PGADMIN  ./pgadmin-stack-deploy
                        cd pgadmin-stack-deploy
                        ansible-galaxy install -r roles/requirements.yml -f
                        chmod 600 $SSH_EC2

                        ssh -o StrictHostKeyChecking=no -i $SSH_EC2 ${USER_SERVER}@${IP_PGADMIN} "
                        ls
                        "

                        ansible-playbook -i hosts.yml pgadmin-deploy.yml --private-key $SSH_EC2 -vvv
                    '''
                }
            }
        }

6.2. Configuration des webhook Jenkins et Gitlab

Étape 1 : Générer un Token Gitlab personnel

Générer un Token personnel, pour cela, vous pouvez vous rendre dans Profile Settings > Access Tokens.

Étape 2 : Configurer Jenkins pour accepter les webhooks de GitLab

Installer le Plugin GitLab : Allez à Manage Jenkins > Manage Plugins > Available, recherchez "GitLab Plugin" et installez-le.

Configurer le Plugin GitLab :

  1. Dans Manage Jenkins > Configure System, descendez jusqu'à la section GitLab.

  2. Renseignez l'URL de GitLab et un token d’accès personnel (Personal Access Token)

Étape 3 : Configurer le Projet Jenkins pour utiliser GitLab

Configurer le Projet (pipeline) Jenkins :

  1. Ouvrez la configuration dU projet Jenkins. Projet > Configurer

  2. Sous la section Source Code Management, choisissez "Git" et renseignez l’URL de votre dépôt GitLab.

  3. Dans la section Build Triggers, cochez Build when a change is pushed to GitLab. GitLab webhook push doit être sélectionné.

  4. Configurez les autres options selon vos besoins spécifiques (par exemple, les branches à construire).

Étape 4 : Créer un Webhook dans GitLab

  1. Accédez au projet dans GitLab

  2. Allez dans Settings > Webhooks.

  3. Entrez l'URL du webhook Jenkins, qui est généralement sous la forme http://JENKINS_URL/project/NOM_DU_JOB. L'URL exacte dans Jenkins sous la configuration du projet, dans la section Build Triggers.

  4. Choisissez les événements pour lesquels vous souhaitez déclencher des builds. Généralement, vous sélectionnerez "Push events" pour les projets de développement standard. Cliquez sur Add Webhook.

Étape 5 : Tester le Webhook

Après avoir configuré le webhook, nous pouvons utiliser le bouton Test à côté du webhook dans GitLab pour envoyer une requête de test à Jenkins et vérifier que la connexion est établie correctement.

Si tout est configuré correctement, Jenkins devrait déclencher un build lorsque le webhook est activé par un push dans le dépôt GitLab.

6.3. Run et test du pipile

6.3.1. Exécution manuelle du pipeline

Apres provisionnement des instances destinées à accueillir Odoo et pgAdmin, nous allons récupérer les IP publics de celle-ci que nous allons renseigner dans le fichier "releases.txt", pour ensuite lancer manuellement notre pipeline et observer le résultat

Site vitrine ic-webapp

Acces à l'interface d'Odoo

Acces à l'interface de pgAdmin

6.3.2. Exécution automatique du pipeline (déclenchement via webhook)

Pipeline update via le webhook

L'application reste disponible après la mise jour du pipeline

On peut confirmer le bon fonctionnement de webhook également via le détails de la requête push effectué par Gitlab réussie

Références

Configurer des webhook jenkins et gitlab

Provisionner un instance ec2 avec terraform

Installer Ansible

Playbook Odoo et PostgreSQL

Playbook pgAdmin & ic-webapp