Automatisation avec Jenkins et OpenShift

Magazine
Marque
GNU/Linux Magazine
Numéro
260
Mois de parution
novembre 2022
Spécialité(s)


Résumé

La conteneurisation d’une application est aujourd’hui un standard dans le monde du développement, mais orchestrer des applications conteneurisées c’est encore mieux. Automatiser la construction de l’application ainsi que son déploiement est bénéfique pour l’accélération du cycle du développement logiciel. L’automatisation est réalisable par des pipelines de CI/CD et en reposant sur des plateformes de conteneurisation. Dans cet article, on démontrera étape par étape comment automatiser le build et le déploiement d’un exemple d’application Node.js en mettant en œuvre les outils : OpenShift, GitHub et Jenkins.


Body

1. Introduction

Le terme DevOps est au cœur du développement logiciel, ainsi en mettant en place une démarche DevOps sur un projet, cela implique certains prérequis et une multitude de technologies à mettre à disposition pour assurer la réussite du projet dans un mode agile / DevOps.

Le processus du développement logiciel nécessite plusieurs étapes, en commençant par la compilation (build) de/des applications(s), tests et déploiement dans les environnements cibles. Ce processus, pour être efficace et pour qu’il puisse répondre aux prérequis des méthodologies agiles et du DevOps également, il faut implémenter la culture DevOps d’une part au sein des équipes et préparer les environnements et l’usine logicielle pour l’accomplissement de l’ensemble des phases du projet.

Dans cet article, on mettrait le process DevOps pour le déploiement d’un exemple d’application Node.js. La compilation et le déploiement de l’application sont réalisés dans OpenShift. L’automatisation des étapes de Build et de déploiement sera confiée dans un premier temps à une instance Jenkins créée par un template OpenShift.

Pour info : au début de l’article, on commence par présenter quelques concepts sur le modèle DevOps, les architectures à base de conteneurs et l’automatisation. Les ateliers réalisés dans cet article se basent tous sur ces concepts, je trouve nécessaire de faire un petit rappel.

2. Quelques définitions

2.1 DevOps

Le modèle DevOps repose sur une culture de collaboration qui s'accorde bien avec les principes de la philosophie open source et les méthodes de travail agiles. Ainsi pour développer des architectures applicatives modernes, il faut adopter de nouveaux processus, différents de ceux qui fonctionnaient par le passé. C’est pour cette raison qu’une démarche DevOps va apporter l’amélioration du processus du développement et d’exploitation, mais en plus contribuer au déclenchement de changements culturels au sein de l’entreprise.

Enfin et pour garantir la réussite du modèle DevOps, il faut sélectionner les outils adaptés à vos processus. Pour que l’équipe d’exploitation puisse suivre le rythme rapide des cycles de développement, elle doit s’appuyer sur une plateforme hautement flexible et traiter l’infrastructure de la même manière que les développeurs traitent leur code, car les déploiements manuels prennent plus de temps, sans compter le risque d’erreurs. Une plateforme hautement flexible peut se reposer sur une infrastructure OpenShift ou Kubernetes par exemple, pour déployer des applications à base de conteneurs ou des architectures applicatives à microservices.

2.2 Conteneurs et microservices

2.2.1 Les conteneurs

Les conteneurs constituent une manière simple et efficace pour empaqueter et exécuter des services. Un conteneur contient toutes les dépendances nécessaires au bon fonctionnement de l’application. Les conteneurs sont isolés du reste du système en s’appuyant sur des fonctionnalités du noyau Linux. L’avantage est de ne pas solliciter beaucoup de ressources matérielles. La technologie des conteneurs améliore non seulement l’efficacité, la souplesse et la capacité de réutilisation des applications, mais aussi la portabilité de ses applications. En effet, l’OCI (Open Container Interface) fournit un ensemble de normes de l’industrie qui définissent une spécification d’exécution de conteneur et une spécification d’image de conteneur (voir références 2). La spécification d’image définit le format de l’ensemble de fichiers et de métadonnées formant une image de conteneur. Lorsque vous créez une application en tant qu’image de conteneur, conforme à la norme OCI, vous pouvez utiliser n’importe quel moteur de conteneur compatible OCI pour exécuter l’application.

La norme OCI est fondée sur des spécifications qui définissent un format d’image standard, communautaire et non propriétaire.

Pour exécuter un conteneur, il faut créer ce qu’on appelle une image de conteneur (voir figure ci-dessous). Les images constituent la base de l’exécution des conteneurs. Les conteneurs en cours d’exécution utilisent une vue immuable de l’image, ce qui permet à plusieurs conteneurs de réutiliser la même image simultanément.

Les images sont stockées soit localement, soit dans des référentiels d’images, on utilise souvent le terme anglophone Images Registry.

Il existe une multitude de registres d’images :

  • DockerHub ;
  • Registre de conteneurs Google GCR (Google Container Registry) ;
  • Registre de conteneurs Amazon Elastic Container ;
  • Red Hat Quay.

Il est également possible d’héberger un registre de conteneurs privé. Harbor est un référentiel de conteneurs qui peut être déployé en interne à l’entreprise (On-Premise).

couches image-s

2.2.2 Les microservices

Les microservices désignent une approche architecturale de développement d’application. Les microservices sont des services liés entre eux par des appels API, ils sont distribués et faiblement couplés.

Les avantages d’une architecture applicative à microservice sont :

  • une modification apportée à un composant n’affecte pas l’ensemble de l’application ;
  • les équipes développement sont en mesure de créer rapidement de nouveaux composants d’applications pour répondre aux évolutions des besoins dans le cycle de vie du projet ;
  • les services peuvent être développés et déployés indépendamment les uns des autres ;
  • chaque service peut être codé dans une technologie et dans un langage différent des autres, et ainsi optimiser la performance et la fiabilité de l’application en totalité ;
  • l’architecture à microservice permet des déploiements et des montées de versions plus agiles ;
  • assurer une haute évolutivité, résilience, facilité de déploiement, et exposition par les API.

Note : dans cet article, on déploie donc un microservice en tant que conteneur dans la plateforme OpenShift, c’est la raison pour laquelle j’ai voulu évoquer quelques termes autour de la technologie des conteneurs et du DevOps.

2.3 Orchestration des conteneurs

Le déploiement des conteneurs est avantageux pour accélérer le processus de la livraison, mais en environnement de production, déployer un conteneur isolé sur une machine constitue un ensemble de limitations :

  • si le conteneur se trouve dans un état d’échec, aucun moyen ne permet d’automatiser son redémarrage ;
  • impossible d’augmenter le nombre d’instances de ce conteneur pour répondre à une montée en charge ou à une grande sollicitation de l’application ;
  • la gestion automatisée des mises à jour des versions de l’application ;
  • assurer la santé de l’application tout au long du cycle d’exécution du conteneur.

En raison de ces limitations, le besoin d’un orchestrateur de conteneurs demeure nécessaire, permettant d’offrir toutes les tâches assurant le bon fonctionnement de ces derniers, d’autant plus lorsque l’application est architecturée en microservices et disposant donc de plusieurs conteneurs distribués.

Les plateformes d’orchestration les plus utilisées aujourd’hui sur le marché sont Kubernetes et OpenShift.

2.3.1 Kubernetes

Kubernetes est un service d’orchestration qui automatise le processus du déploiement, de la gestion et de la mise à l’échelle des applications en conteneurs. Une plateforme Kubernetes permet d’éliminer plusieurs processus manuels et d’assurer un cycle de vie applicatif automatisé et de remédier à différentes limitations citées dans le paragraphe précédent.

Kubernetes est le moyen le plus efficace pour optimiser le développement des applications cloud-native.

Les fonctionnalités principales de Kubernetes sont :

  • orchestrer des conteneurs sur plusieurs hôtes ;
  • optimiser l’utilisation des ressources physiques requises pour l’exécution des différentes applications hébergées au sein du cluster Kubernetes ;
  • automatiser et contrôler les déploiements ainsi que la montée en versions des différentes images encapsulant les applications ;
  • mise à l’échelle automatique des conteneurs (augmentation du nombre des conteneurs à la volée) à travers les fonctionnalités d’autoscaling horizontal (HPA) et vertical qui sont nativement intégrées à Kubernetes ;
  • Kubernetes peut utiliser les contrôles d’intégrité (Health-check) définis dans les manifestes de déploiement des services pour une autoréparation des conteneurs, en cas d’échec.

2.3.2 OpenShift

OpenShift est une plateforme basée principalement sur l’orchestrateur Kubernetes. C’est un produit Red Hat connu sous le nom Red Hat OpenShift Container Platform.

L’avantage d’OpenShift par rapport à Kubernetes est qu’il dispose d’un mécanisme de compilation du code source en se reposant sur les bibliothèques et les environnements d’exécution pour la plupart des langages de programmation.

En effet, à partir du code source stocké dans un référentiel Git, OpenShift peut récupérer directement le code source, puis compile et déploie l’application. Le déploiement fait en sorte de créer toutes les ressources nécessaires pour le bon fonctionnement du service déployé. OpenShift est fourni également avec un ensemble de services disponibles de modèles pour faire du CI/CD et la supervision, par exemple.

2.4 Intégration continue et déploiement continu

Dans une démarche DevOps, le concept d’intégration continue et de déploiement continu est fréquemment utilisé et il est considéré comme étant le pilier de cette démarche. Le principe de ce concept est la mise en œuvre de l’automatisation complète des phases de compilation, tests et déploiement d’applications.

2.4.1 Intégration continue

L’intégration continue est une méthodologie utilisée en développement logiciel avec laquelle le code développé est intégré régulièrement et fréquemment à un référentiel de gestion de versions tel que GitHub ou GitLab. Une fois que le code est intégré, l’intégration continue mène aussi la partie compilation et tests automatisés.

2.4.2 Déploiement continu

Le déploiement continu est une extension de l’intégration continue, une fois le code compilé et testé, une nouvelle version de l’application ou du service est déjà prête à être déployée dans les environnements d’avant production et en suite en production. Le déploiement en production le plus souvent n’est pas automatique et nécessite une approbation au préalable.

Il existe un autre terme équivalent au déploiement continu qui est la livraison continue, qui elle consiste à déployer automatiquement les changements du code dans un environnement de test ou de « préprod » afin de s’assurer du bon fonctionnement de l’application avant de promouvoir en production.

2.5 Pipelines CI/CD

Un pipeline de CI/CD est une série d’étapes à réaliser en vue de distribuer une nouvelle version d’une application. Toutes les tâches à réaliser dans le cadre de l’intégration continue et du déploiement continu peuvent être associées à un pipeline permettant d’automatiser l’ensemble des phases du pipeline.

Les phases d’un pipeline sont :

  • compilation (build) du code source depuis un référentiel Git ;
  • test du code comprenant les tests unitaires, tests fonctionnels, et tests de qualité du code, par exemple ;
  • stockage de la nouvelle version et de ses métadonnées dans un gestionnaire de packages ;
  • déploiement en environnement de préproduction en vue de réaliser des tests supplémentaires, à l’instar des tests de performance ;
  • déploiement en production ;
  • supervision et récupération des informations de l’application en cours d’exécution en vue de détecter une éventuelle anomalie ou un dysfonctionnement.

cicd-process-s

3. Installation d’un cluster OpenShift

Plusieurs produits permettent d’installer OpenShift, tout dépend du besoin de l’entreprise si elle veut mettre en place une plateforme OpenShift installée au sein de l’infrastructure interne (On-Premise) ou dans le cloud pour bénéficier d’une plateforme managée.

Les différentes plateformes OpenShift existantes sont :

  • Red Hat OpenShift Container Platform : fournit une plateforme OpenShift destinée aux entreprises pour l’orchestration de conteneurs dans n’importe quel datacenter public ou privé. Cette plateforme est nativement compatible avec la plupart des fournisseurs cloud et de virtualisation.
  • Red Hat OpenShift Dedicated : fournit un environnement OpenShift géré dans un cloud public à l’instar de AWS, GCP, Microsoft Azure ou IBM Cloud. L’infrastructure OpenShift est gérée par Red Hat pour assurer les montées de versions ou les patchs, par exemple.
  • Red Hat OpenShift Online : c’est la plateforme OpenShift disponible en ligne offrant des solutions de création, de déploiement et d’hébergement d’applications dans un environnement cloud. C’est aussi Red Hat qui gère le cycle de vie du cluster.
  • Red Hat OpenShift Kubernetes Engine : fournit un sous-ensemble des fonctions présentes dans OpenShift Container Platform, tel que le système d’exploitation orienté conteneur Red Hat Entreprise Linux CoreOS, le moteur CRI-O, la plateforme d’orchestration de conteneur Kubernetes et les principaux services de cluster (console web, mises à jour OTA, registre interne).
  • Red Hat Code Ready Containers : fournit une installation minimale d’OpenShift à des fins de développement local ou pour tester la plateforme OpenShift.

Une alternative permettant de déployer un environnement OpenShift est de provisionner une sandbox OpenShift depuis le site Red Hat Developer : https://developers.redhat.com/developer-sandbox.

C’est ce mode de provisioning qui sera utilisé dans cet article pour mettre à disposition l’environnement OpenShift.

Vous pouvez également déployer OpenShift avec Code Ready Container (voir mon article : « Petite introduction à OpenShift » paru dans LM 250 [1]).

3.1 Provisionner OpenShift

Pour provisionner une sandbox OpenShift, rendez-vous sur le site :
https://developers.redhat.com/developer-sandbox.

Vous aurez une page comme dans la figure ci-dessous :

sandbox-s

Cliquez sur le bouton Start your sandbox for free, puis connectez-vous avec un nom d’utilisateur et un mot de passe (sinon, créez un compte Red Hat).

connexion-s

Une fois connecté, cliquez sur le bouton Start using your sandbox comme indiqué sur la figure ci-dessous.

start-s

Vous êtes redirigé vers une console vous permettant de vous connecter à OpenShift. Il suffit de cliquer sur le bouton DevSandbox.

connexion-openshift-s

C’est fait ! Notre environnement OpenShift est maintenant prêt pour déployer notre application.

En provisionnant une sandbox, on aura accès à un projet dédié pour déployer nos ressources. Dans mon cas, le nom du projet (namespace au sens Kubernetes) est issam-mejri-ext-dev.

console-projet-s

Commençons la mise en œuvre de notre application dans le paragraphe suivant.

4. Création manuelle des ressources dans OpenShift

Il existe deux manières de créer des ressources dans OpenShift, une via la console, et c’est la méthode la plus simple pour ceux qui veulent une prise en main rapide de la plateforme, et la deuxième, c’est d’avoir recours à la ligne de commande. À travers la ligne de commande, il est possible de taper directement des commandes (mode imperative) pour la création des ressources, ou de créer des manifestes de déploiements dans des fichiers YAML (mode declarative).

4.1 Déploiement de notre application via la console OpenShift

Le code source de notre application est stocké dans le référentiel Git :
https://github.com/imejri/nodejs-app.git.

Le dépôt Git contient le code source de notre application Node.js ainsi que les fichiers de déploiement des ressources OpenShift, dont nous aurons besoin lors de l’étape de la mise en place du pipeline CI/CD dans Jenkins et GitLab CI.

OpenShift dispose de plusieurs scénarios de déploiement. Dans notre cas, c’est de fournir l’URL du référentiel Git de notre application à OpenShift, ensuite la plateforme récupère automatiquement le code source pour compiler et déployer toutes les ressources de l’application.

La console offre deux perspectives, une pour les développeurs, et une autre pour les administrateurs. Nous choisissons le mode développeur pour intégrer notre application comme illustré sur la figure ci-dessous.

console-dev-s

Cliquez ensuite sur Import from Git pour spécifier l’URL du référentiel Git :

console-git-s

Une fois qu’OpenShift accède au référentiel Git et en parcourant la racine du dépôt, il va détecter la présence d’un Dockerfile. Dans ce cas précis, il lancera un build de type Docker permettant de créer l’image correspondante et de la pousser vers le registry interne d’OpenShift.

Il est possible d’indiquer sur quelle branche la compilation sera réalisée ainsi que le chemin vers les sources lorsque le code de l’application se trouve dans un sous-répertoire, et non à la racine du référentiel Git.

Les autres options sont :

  • les ressources qui seront créées à la suite de la compilation ;
  • le port cible à exposer ;
  • le choix pour la création de la route permettant d’accéder à l’application en dehors d’OpenShift ;
  • possibilité de choisir une autre stratégie de build (Builder Image, par exemple). On évoquera cette stratégie dans la partie CI/CD.

console-creation-s

Si l’on clique sur Edit Import Strategy - Builder Image, on affiche l’ensemble des images de build permettant de créer l’environnement de compilation du code et d’exécution de l’application. Dans notre cas, une image Node.js est choisie par défaut.

Génial ! OpenShift a réussi à détecter le langage de notre application.

console-builder-image-s

Enfin, on clique sur le bouton Create pour lancer le processus de build et de déploiement.

Pour vérifier que notre application a été bien déployée, visitez l’onglet Topology de la console :

console-topology-s

Accédez à l’application en cliquant sur la petite flèche encadrée en rouge dans l’illustration précédente.

Il s’agit de l’URL (route) créée automatiquement par OpenShift pour accéder à l’application depuis l’extérieur (https://nodejs-app-git-issam-mejri-ext-dev.apps.sandbox-m2.ll9k.p1.OpenShiftapps.com/).

Super ! Notre application est désormais accessible.

app-shark-s

4.2 Déploiement de notre application via la CLI OpenShift

Le déploiement de notre application par la ligne de commande est très simple à faire. Une seule commande génère toutes les ressources nécessaires à l’exécution de l’application.

Sur les nouvelles versions d’OpenShift, la console fournit un terminal (OpenShift Web Terminal) qui inclut tous les outils pour administrer OpenShift.

Pour lancer un terminal, il suffit de cliquer sur le symbole situé en haut à droite de la console (voir figure ci-dessous).

console-terminal-s

Une fois le terminal lancé, on n’a pas besoin de se connecter à notre projet OpenShift, car l’authentification est intégrée directement dès lors que le terminal est en cours d’exécution.

Commençons par supprimer l’ancien déploiement :

$ oc get deploy/nodejs-app-git --show-labels
NAME             READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
nodejs-app-git   1/1     1            1           4h19m   app.kubernetes.io/component=nodejs-app-git,app.kubernetes.io/instance=nodejs-app-git,app.kubernetes.io/name=nodejs-app-git,app.kubernetes.io/part-of=nodejs-app-git-app,app.OpenShift.io/runtime-version=16-ubi8,app.OpenShift.io/runtime=nodejs,app=nodejs-app-git

On supprime toutes les ressources créées en spécifiant le label app=nodejs-app-git :

$ oc delete all -l app=nodejs-app-git
pod "nodejs-app-git-6d7c8fbc65-m5ljm" deleted
service "nodejs-app-git" deleted
deployment.apps "nodejs-app-git" deleted
buildconfig.build.OpenShift.io "nodejs-app-git" deleted
imagestream.image.OpenShift.io "nodejs-app-git" deleted
route.route.OpenShift.io "nodejs-app-git" deleted

Maintenant, on peut déployer notre application à nouveau, mais cette fois-ci en invoquant la commande oc new-app :

$ oc new-app --name nodejs-app --strategy=docker https://github.com/imejri/nodejs-app.git#master
--> Found container image aa67ba2 (16 months old) from Docker Hub for "node:10-alpine"
 
    * An image stream tag will be created as "node:10-alpine" that will track the source image
    * A Docker build using source code from https://github.com/imejri/nodejs-app.git#master will be created
      * The resulting image will be pushed to image stream tag "nodejs-app:latest"
      * Every time "node:10-alpine" changes a new build will be triggered
 
--> Creating resources ...
    imagestream.image.OpenShift.io "node" created
    imagestream.image.OpenShift.io "nodejs-app" created
    buildconfig.build.OpenShift.io "nodejs-app" created
    deployment.apps "nodejs-app" created
    service "nodejs-app" created
--> Success
    Build scheduled, use 'oc logs -f buildconfig/nodejs-app' to track its progress.
    Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
     'oc expose service/nodejs-app'
    Run 'oc status' to view your app.

Sur la console OpenShift, cliquez sur Topology dans le volet de navigation pour afficher les ressources créées.

console-resources-s

Mais pour l’instant, notre route permettant d’atteindre l’application n’est pas encore créée. Il faut la créer comme indiqué sur la sortie de la commande oc new-app précédente :

$ oc expose service/nodejs-app
route.route.OpenShift.io/nodejs-app exposed

Notre application est désormais accessible :

$ oc get route -l app=nodejs-app
NAME         HOST/PORT                                                                  PATH   SERVICES     PORT       TERMINATION   WILDCARD
nodejs-app   nodejs-app-issam-mejri-ext-dev.apps.sandbox-m2.ll9k.p1.OpenShiftapps.com          nodejs-app   8080-tcp                 None

5. Environnement CI/CD et automatisation

Pour automatiser la compilation et la création de l’image Docker ainsi que le déploiement dans OpenShift de notre application, il faut avoir recours à des outils de CI/CD. Dans cet article, j’ai choisi Jenkins.

La création du serveur Jenkins sera réalisée directement via un pod dans OpenShift. En effet, OpenShift dispose d’un catalogue de services permettant d’ajouter des fonctionnalités directement intégrées à la plateforme, ce qui facilite le provisioning de la solution souhaitée.

6. Pipeline de build et de déploiement avec Jenkins

Dans cette partie de l’article, nous mettons en place l’automatisation des différentes étapes réalisées manuellement dans les paragraphes précédents en reposant sur une instance Jenkins déployée en tant que pod dans OpenShift. L’automatisation du processus CI/CD est réalisable par un job Jenkins de type pipeline.

Un pipeline Jenkins est créé à partir d’un fichier JenkinsFile qui contient l’ensemble des phases de compilation, tests et déploiement de l’application.

Notre instance Jenkins, sans entrer dans les détails, car ce n’est pas le but de l’article, intègre un plug-in permettant de communiquer avec les API OpenShift. Le plug-in à installer dans le cas où vous voudriez intégrer un serveur Jenkins en dehors d’OpenShift est OpenShift Jenkins Pipeline (DSL) Plug-in.

6.1 Déploiement du pod Jenkins

Le déploiement du pod Jenkins se fait via la console OpenShift. Dans le volet gauche de la console, l’onglet Add est le point d’accès à un assistant qui vous permet de choisir entre différentes méthodes de déploiement d’une application sur le cluster OpenShift. Cliquez sur Add pour afficher la liste des choix pour le déploiement des applications. Dans notre cas, il faut développer la section All Services dans le volet droit de la fenêtre, dans All Items choisir CI/CD comme indiqué sur la figure ci-dessous :

console-items-s

Cliquez ensuite sur CI/CD pour afficher la liste des services disponibles. Dans cette liste, on peut choisir le template Jenkins avec le volume persistant (voir capture d’écran ci-dessous).

console-jenkins-persistent-s

Après avoir sélectionné Jenkins, cliquez sur instanciate Template. Dans la fenêtre qui apparaît, gardez toutes les valeurs par défaut, puis cliquez sur le bouton create en bas de la fenêtre.

Dans l’onglet Topology, le pod Jenkins apparaît avec l’ensemble des ressources nécessaires pour accéder à la console Jenkins.

console-pod-jenkins-s

6.2 Accès à la console Jenkins

À la suite au déploiement du template Jenkins dans le paragraphe précédent, une route est créée permettant d’accéder à la console du serveur Jenkins.

En copiant l’URL dans notre navigateur, on accède à la page d’authentification :

console-authetification-jenkins-s

Cliquez sur Log in with OpenShift. Cela permet de s’authentifier avec les credentials d’accès à OpenShift.

Félicitation ! On peut désormais commencer à créer notre pipeline de CI/CD dans Jenkins.

6.3 Création du projet nodejs-app

Dans ce paragraphe, nous allons créer un projet de type pipeline pour le déploiement de notre application.

Dans le volet gauche de la console Jenkins, cliquez sur Nouveau Item, puis saisissez le nom du projet et choisissez Pipeline dans la liste des types de projets.

console-jenkins-projet-s

Une nouvelle fenêtre d’affiche permettant de configurer notre projet. Dans notre exemple, le build et le déploiement de l’application seront réalisés à partir d’un JenkinsFile, autrement dit, il faut indiquer à Jenkins où trouver ce fichier ainsi que le code source de l’application. Il faut aller tout en bas de la fenêtre et dans la section Pipeline, choisir Pipeline Script from SCM. Dans SCM, choisir Git et finalement dans Repositories, indiquez l’URL de notre projet dans GitHub, dans notre cas, c’est https://github.com/imejri/nodejs-app.git.

Finalement, cliquez sur le bouton Sauver pour enregistrer votre projet.

Le projet apparaît dans notre console Jenkins (voir figure ci-dessous).

console-jenkins-pipeline-s

Tout le reste des phases de build et de déploiement (pipeline de CI/CD) de l’application est inscrit dans le JenkinsFile, c’est le concept du Pipeline As Code.

Voici à quoi ressemble notre JenkinsFile :

/* Pipeline Jenkins to build et deploy nodejs Shark App */
/* Auteur: Mejri Issam */
 
pipeline {
        // We will use any agent available.
        agent any
        // set a timeout of 30 minutes for this pipeline.
        options
        {
            timeout(time: 30, unit: 'MINUTES')
        buildDiscarder(logRotator(numToKeepStr: '5', artifactNumToKeepStr: '5'))
        }
        // List of parameters required to configure before the launch of the pipeline.
        parameters{
 string(name: 'BRANCH', defaultValue: 'master', description: 'Name of the branch to use.')
 string(name: 'NB_REPLICAS', defaultValue: '1', description: 'Number of replicas for deployment.')
 choice(name: 'ENVIRONMENT', choices: ['issam-mejri-ext-dev', 'issam-mejri-ext-stage'], description: 'The name of the environement where we want to deploy/build resources.')
 choice(name: 'DEPLOYMENT_TYPE', choices: ['','BUILD', 'DEPLOY'], description: 'The name of the type of deployment to process, can be either Build or Deploy.')
 string(name: 'IMAGE_TAG', defaultValue: '', description: 'tag for the build image.')
 string(name: 'SOURCES_URL', defaultValue: 'https://github.com/imejri/nodejs-app.git', description: 'Gitlab repository source of the application.')
 
        }
 
        // List of stages used on the pipelines.
        stages
        {
           stage('Checkout.')
            {
                steps
                {
                    script{
                            if ( params.DEPLOYMENT_TYPE.isEmpty() )
                            {
                              // Use SUCCESS FAILURE or ABORTED
                              currentBuild.result = "FAILURE"
                              throw new Exception("The Parameters DEPLOYMENT_TYPE is empty, the value must be either BUILD or DEPLOY, Please set DEPLOYMENT_TYPE parameters.")
                            }
                    }
                        
                    checkout([$class: 'GitSCM',
                    branches: [[name: "*/${env.BRANCH}"]],
                    userRemoteConfigs:[[credentialsId: 'gitlab', url: "${env.SOURCES_URL}"]]
                    ])
                    
                } // steps
            } // stage
 
            stage("Build Source Code")
            {
                when {
                    // Only for BUILD Deployment type.
                    expression { params.DEPLOYMENT_TYPE == 'BUILD' }
                }
                steps
                {
 
                    script
                    {
                       sh """
                 oc delete bc -l build=nodejs-image
                 oc new-build --name=nodejs-image --image-stream=openshift/nodejs:16-ubi8 ${params.SOURCES_URL} --to='nodejs-image:${params.IMAGE_TAG}'
                        """
                    } // script
                } // steps
            } // stage
 
            stage("Deploy resources for DEV/STAGE environments.")
            {
                 when {
                    expression { params.DEPLOYMENT_TYPE == 'DEPLOY' }
                 }
                steps
                {
                    script
                    {
                       sh """
                        oc apply -f nodejs-image-demo-deploy.yaml -n ${params.ENVIRONMENT}
             oc set image deployment/nodejs-image-demo nodejs-image-demo=image-registry.openshift-image-registry.svc:5000/issam-mejri-ext-dev/nodejs-image:${IMAGE_TAG}
             oc scale --replicas=${params.NB_REPLICAS} deployment/nodejs-image-demo
                        oc apply -f nodejs-image-demo-svc.yaml -n ${params.ENVIRONMENT}
                        """
                    } // script
                } // steps
            } // stage
 
        stage("Create route to access the Application")
                {
                 when {
                    expression { params.ENVIRONMENT == 'issam-mejri-ext-dev' && params.DEPLOYMENT_TYPE == 'DEPLOY' }
                 }
                steps
                {
                    script
                    {
            sh """
               oc delete route nodejs-image-demo
                         oc expose svc/nodejs-image-demo
            """
                    } // script
                } // steps
            } // stage
        } // stages
 
        post
        {
            always
            {
                deleteDir() // Delete the current workspace.
                dir("${env.WORKSPACE}@script")
                {
                    deleteDir()
                } // dir
            } // always
        } // post
} // pipeline

Dans notre JenkinsFile, j’ai créé les stages suivants :

  • Checkout du code permettant de cloner le dépôt dans le répertoire de travail de Jenkins ;
  • Build Source Code pour la compilation du code avec la stratégie source to image (S2I) évoquée au début de l’article ;
  • Deploy resources for DEV/STAGE environments pour le déploiement de l’application dans le cluster OpenShift ;
  • Create route to access the Application pour la création de la route permettant de créer l’URL d’accès à l’application.

Il faut noter aussi que notre pipeline est paramétrable avec la section parameters au début du JenkinsFile. Le paramétrage permet de « variabiliser » le déploiement et la compilation, cela permet par exemple d’agir sur le versioning de notre application, le nombre de replicas à déployer ou encore la branche de référence pour l’exécution du pipeline (dans notre exemple, c’est la master branch).

Revenons à nos moutons, dans la console Jenkins, cliquez sur le projet nodejs-app, puis dans la partie gauche de la console, cliquez sur Lancer un build avec des paramètres. Nous allons réaliser un build d’une version 1.2 de notre application. Dans Environment, on va choisir notre projet OpenShift.

Dans DEPLOYMENT_TYPE, on choisit Build pour compiler le code source. On a une séparation dans notre pipeline de l’étape de build et du déploiement.

console-jenkins-build-s

C’est bon, on est prêt pour exécuter notre pipeline, il suffit de cliquer sur le bouton Build en bas de la fenêtre.

Le déroulement du pipeline est accessible via la Console Output :

pipeline-build-s

Notre image d’application est accessible dans OpenShift dans la partie Builds de la console :

image-build-jenkins-s

La deuxième étape de notre pipeline est le déploiement de l’application et la création de la route. C’est le même déroulement que dans l’étape de build avec un changement de deux paramètres :

  • DEPLOYMENT_TYPE : Deploy
  • NB_REPLICAS : 3

On va déployer 3 pods de notre application en restant toujours sur la version du build précédent (v1.2). La sortie console permet de suivre le déroulement du déploiement :

console-jenkins-deploy-s

Vérifions dans OpenShift le déploiement des trois pods et la création de la route en ligne de commande et depuis la console :

deploy-openshift-jenkins-s

À partir du terminal intégré à OpenShift :

# oc get pods -l deployment=nodejs-image-demo
NAME                                READY   STATUS    RESTARTS   AGE
nodejs-image-demo-b54f97476-29wvl   1/1     Running   0          4m18s
nodejs-image-demo-b54f97476-6l5wl   1/1     Running   0          4m14s
nodejs-image-demo-b54f97476-p9rl7   1/1     Running   0          4m18s

Vérifions la création de la route :

# oc get routes -l app=nodejs-image-demo
NAME                HOST/PORT                                                                      PATH   SERVICES            PORT       TERMINATION   WILDCARD
nodejs-image-demo   nodejs-image-demo-issam-mejri-ext-dev.apps.sandbox.x8i5.p1.openshiftapps.com          nodejs-image-demo   8080-tcp                 None

Comme vous l’avez remarqué tout au long de ce paragraphe, un simple clic sur un bouton dans la console Jenkins permet le build et le déploiement de notre application. C’est bien le concept d’automatisation et d’intégration et déploiement continu qui a été mis en place via Jenkins et la plateforme OpenShift.

Conclusion

La plateforme OpenShift nous a permis d’automatiser le processus de compilation et de déploiement de notre application Node.js, le fait aussi d’intégrer un outil de CI/CD comme Jenkins à OpenShift facilite la création et l’exécution du pipeline à travers notre JenkinsFile.

Un autre outil plus intégré à la plateforme, et aussi une alternative à Jenkins s’appelle Tekton. Cet outil permet de réaliser du CI/CD Cloud Native, c’est-à-dire sans besoin d’un outil annexe pour mettre en place du CI/CD. Si j’en ai le temps, je pourrais vous faire découvrir cette technologie dans un prochain article.

Références

[1] https://connect.ed-diamond.com/GNU-Linux-Magazine/glmf-250/petite-introduction-a-openshift

[2] https://opencontainers.org/



Article rédigé par

Par le(s) même(s) auteur(s)

Builder des images de conteneurs

Magazine
Marque
Linux Pratique
Numéro
142
Mois de parution
mars 2024
Spécialité(s)
Résumé

La technologie des conteneurs a révolutionné le monde du développement et de la livraison logicielle en offrant une manière isolée, réplicable et éphémère de déployer des applications et leurs dépendances. Au cœur de cette révolution se trouve la création des images de conteneurs, qui sont essentiellement des instantanés de l'application et de son environnement d'exécution. Divers outils et technologies ont vu le jour pour faciliter et optimiser la création de ces images. Dans cet article, nous explorerons les différentes technologies dominantes de création d'images, telles que Docker, Podman, Buildah et Buildpacks, et nous plongerons dans leurs spécificités, et mettrons en pratique le build des images et la création des applications conteneurisées.

Allier tests et DevSecOps : la route vers une application sécurisée

Magazine
Marque
GNU/Linux Magazine
Numéro
266
Mois de parution
novembre 2023
Spécialité(s)
Résumé

Depuis la rigidité du modèle Waterfall, où la sécurité des applications était souvent une réflexion tardive post-développement, l'évolution s'est dirigée vers la méthodologie Agile. Aujourd'hui, non seulement la sécurité des applications est intégrée dès le départ à travers les tests, mais elle se fond également dans des approches plus avancées comme le DevSecOps et l'intégration continue, reflétant une transition vers une conception sécurisée, agile et automatisée.

Protégez vos ressources Kubernetes avec TrilioVault

Magazine
Marque
Linux Pratique
Numéro
138
Mois de parution
juillet 2023
Spécialité(s)
Résumé

TrilioVault est une solution innovante de protection et de gestion des données conçue spécifiquement pour Kubernetes. Elle offre une approche transparente et évolutive pour sécuriser, sauvegarder et restaurer les applications et les données dans les environnements Kubernetes. Dans cet article, nous explorerons les concepts clés de Triliovault et comment il s'intègre avec Kubernetes pour fournir une solution de protection des données inégalée.

Les derniers articles Premiums

Les derniers articles Premium

Présentation de Kafka Connect

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Un cluster Apache Kafka est déjà, à lui seul, une puissante infrastructure pour faire de l’event streaming… Et si nous pouvions, d’un coup de baguette magique, lui permettre de consommer des informations issues de systèmes de données plus traditionnels, tels que les bases de données ? C’est là qu’intervient Kafka Connect, un autre composant de l’écosystème du projet.

Le combo gagnant de la virtualisation : QEMU et KVM

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

C’est un fait : la virtualisation est partout ! Que ce soit pour la flexibilité des systèmes ou bien leur sécurité, l’adoption de la virtualisation augmente dans toutes les organisations depuis des années. Dans cet article, nous allons nous focaliser sur deux technologies : QEMU et KVM. En combinant les deux, il est possible de créer des environnements de virtualisation très robustes.

Brève introduction pratique à ZFS

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Il est grand temps de passer à un système de fichiers plus robuste et performant : ZFS. Avec ses fonctionnalités avancées, il assure une intégrité des données inégalée et simplifie la gestion des volumes de stockage. Il permet aussi de faire des snapshots, des clones, et de la déduplication, il est donc la solution idéale pour les environnements de stockage critiques. Découvrons ensemble pourquoi ZFS est LE choix incontournable pour l'avenir du stockage de données.

Générez votre serveur JEE sur-mesure avec Wildfly Glow

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Et, si, en une ligne de commandes, on pouvait reconstruire son serveur JEE pour qu’il soit configuré, sur mesure, pour les besoins des applications qu’il embarque ? Et si on pouvait aller encore plus loin, en distribuant l’ensemble, assemblé sous la forme d’un jar exécutable ? Et si on pouvait même déployer le tout, automatiquement, sur OpenShift ? Grâce à Wildfly Glow [1], c’est possible ! Tout du moins, pour le serveur JEE open source Wildfly [2]. Démonstration dans cet article.

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 65 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous