5 min read

Mise en place d'une pipeline de CI/CD avec Jenkins

Dans ce blog nous allons voir comment mettre en place une pipeline de CI/CD avec des outils IaC, telle que Terraform et Ansible.

#jenkins

#git

#terraform

#ansible

#docker

Article publié le 31 janv. 2023

·

5 min de lecture

1. Configuration du GitHub

Comme dans ce tutoriel, tous les répertoires nécessaires se trouvent dans le répertoire GitHub de Kanops, alors une fois la configuration pour récupérer le Jenkinsfile effectuée, nous n'aurons plus besoin de récupérer les autres dossiers, car ils seront directement récupérés également.
On va dans premier temps cliquer sur Créer un job : jenkins_create_job.png

Puis, sur le .gif ci-dessous, on va configurer notre nouvelle pipeline, qui va récupérer directement nos fichiers sur notre GitHub sur la branche main. Puis, on termine en indiquant le chemin vers notre Jenkinsfile :

jenkins_add_git.gif

Une fois la configuration terminée, nous pouvons déjà lancer notre pipeline une première fois pour que Jenkins prenne en compte notre Jenkinsfile.

⭐️ Une fois la pipeline lancée une première fois, il faudra approuver le script groovy écrit pour le multiple choix de l'environnement de déploiement. Pour cela il faudra se rendre dans Administrer Jenkins > In-process Script Approval et approuver le script.

💡 Nous pouvons nous connecter à notre conteneur pour vérifier que les répertoires terraformet ansible ont également étaient récupérés :

docker exec -it jenkins /bin/bash

Une fois dans le conteneur on peut lister le répertoire /var/>jenkins_home/workspace/Deploy_app pour vérifier que nos dossier sont là :

jenkins_list_workspace.png

2. Création du serveur avec Terraform

La première chose dont on a besoin est d'un serveur opérationnel pour héberger notre application. Sur le site d'OVH différents types de machines sont proposés. Pour le tutoriel, nous choisirons un serveur d2-4. Dans notre Jenkinsfile nous allons donc dans un premier temps créer notre serveur et mettre en place un pare-feu (Security Groups pour Openstack).

⭐️ Il faudra auparavant modifier le fichier terraform/${env}/cloud-structure/main.tf et copier le contenu de votre clé ssh publique pour la valeur public_key. Sans ça, vous ne pourrait pas accéder au serveur en SSH.

Ici le stage correspondant dans notre Jenkinsfile :

stage('Terraform - Création de l\'instance'){
    steps {
        script{
            // Openstack/Terraform - Login and deploy
            sh """ \
                export OS_AUTH_URL=https://auth.cloud.ovh.net/
                export OS_PROJECT_ID=$OS_PROJECT_ID
                export OS_PROJECT_NAME=$OS_PROJECT_NAME
                export OS_USER_DOMAIN_NAME=$OS_USER_DOMAIN_NAME
                export OS_USERNAME=$OS_USERNAME
                export OS_PASSWORD=$OS_PASSWORD
                export OS_INTERFACE=public
                export OS_IDENTITY_API_VERSION=3

                echo "Terraform - Add/Update ssh key pai
                cd $WORKSPACE/terraform/$INSTANCE.terraform_folder/cloud-structure
                terraform init
                terraform apply --auto-approve

                echo "Terraform - Configure security groups and update instance"
                cd $WORKSPACE/terraform/$INSTANCE.terraform_folder/projects
                terraform init
                terraform apply --auto-approve
            """
        }
    }
}

⭐️ Les variables de Openstack présentent ici devrons être configurées en tant que variables d'environnement directement dans Jenkins.

1.3. Configuration du serveur avec Ansible

Une fois notre serveur créer, il faudra le configurer en installant les paquets nécessaires afin qu'il soit opérationnel pour héberger notre application. Pour cela, le bloc ci-dessous permettra d'appeller notre playbook playbook-config.yml :

stage('Ansible - Configuration de l\'instance'){
    steps {
        script{
            // Configuration de notre instance
            ansiblePlaybook (
                colorized: true,
                disableHostKeyChecking: true,
                inventory: "${INSTANCE.public_ip},",
                playbook: "$WORKSPACE/ansible/playbook_config.yml",
                extras: "-u debian --private-key ${INSTANCE.private_key_path}"
            )
        }
    }
}

Ce playbook installera Docker ainsi que d'autres paquets nécessaires pour pouvoir déployer des conteneurs avec Docker sur notre instance.

1.4. Build de l'image Docker

Une fois le serveur configuré, on devra packagé notre application dans une image Docker. Ici, une fois l'image construite, nous allons le compresser au format .tar pour ensuite l'envoyé sur notre serveur.

⭐️ Ici, nous envoyons directement l'image aprés l'avoir compressé, ce qui peut être long. Pour accéder plus rapidement à l'image sur un serveur distant, nous pouvons utiliser Dockerhub pour stocker nos images. Grâce à leur divers CDN répartis dans le monde, l'accès à nos images sera plus rapide.

Ici, la partie concernée dans le Jenkinsfile :

sh """
cd app
docker build -t app-local:latest .
docker save -o $WORKSPACE/applocal-latest.tar app-local:latest
scp -i ${INSTANCE.private_key_path} $WORKSPACE/applocal-latest.tar debian@${INSTANCE.public_ip}:/home/debian
"""

1.5. Exécution de tests et déploiement

Une fois notre image Docker disponible sur notre serveur, nous pouvons donc passer à l'étape du lancement des tests. Ici, le test sera lancé également via ansible-playbook :

// Test de notre app
ansiblePlaybook (
    colorized: true,
    disableHostKeyChecking: true,
    inventory: "${INSTANCE.public_ip},",
    playbook: "$WORKSPACE/ansible/playbook_deploy.yml",
    extras: "-u debian -e mode=test --private-key ${INSTANCE.private_key_path}"
)

Une fois les tests terminés, nous récupérons les résultats et en fonction du résultat nous indiquerons dans notre pipeline les étapes à réalisées :

// Get and Check test
sh "scp -i ${INSTANCE.private_key_path} debian@${INSTANCE.public_ip}:/tmp/app-results/results.txt $WORKSPACE/results.txt"
result = sh(returnStdout: true, script: "cat $WORKSPACE/results.txt").trim()
if(result != "200"){
    currentBuild.result = 'ABORTED'
    currentBuild.displayName = "Tests K.O"
    error('Tests K.O')
}
else{
    echo "Tests O.K"

    // Déploiement de notre app
    ansiblePlaybook (
        colorized: true,
        disableHostKeyChecking: true,
        inventory: "${INSTANCE.public_ip},",
        playbook: "$WORKSPACE/ansible/playbook_deploy.yml",
        extras: "-u debian -e mode=deploy --private-key ${INSTANCE.private_key_path}"
    )
}

2. Lancement de la pipeline

Nous pouvons donc lancer notre pipeline pour créer notre infrastructure (ou la mettre à jour), laisser notre playbook Ansible configurer le serveur, construire l'image Docker de notre App, lancer les tests et pour finir, déployer notre application :

jenkins_job_load.gif

Juste à attendre que notre pipeline se termine :

jenkins_pipeline_end.png

Et nous pouvons donc accéder à notre application :
jenkins_app_deployed.png

🧙🏻‍♂️ Voilà, nous avons mis en place notre pipeline Jenkins permettant d'agir sur une infrastructure Cloud et déployer notre application de manière complétement automatisée !

Auteur Billy PAYET

Billy PAYET

Billy est un expert en DevOps qui a une solide expérience en automatisation et en intégration continue. Il utilise des outils tels que Ansible, Jenkins et Docker pour améliorer les processus de déploiement et de livraison des applications. Il est passionné par l'amélioration continue et aider les équipes à atteindre leurs objectifs de qualité et de performance.