Retour Atelier Continuous Delivery – Partie 2 – Déploiement continu avec Jenkins Remote SSH Plugin

Pour déployer une application sur un serveur Tomcat distant, nous avons vu précédemment comment utiliser Apache Tomcat Maven Plugin. Nous pouvons aussi utiliser un script. Cette solution plus élaborée est certainement plus proche des solutions d’exploitation existantes aujourd’hui dans nos entreprises. 

Dans l’esprit DevOps, il faut avoir un mode de déploiement le plus tôt possible identique à celui de la production. L’approche par script convient ainsi à un maximum d’environnements possibles (du test jusqu’à la production).
Pour ce faire, le script sera placé sur le serveur distant et exécuté à distance.

Le but de cet article est de vous proposer une solution pour déployer une application web sur un serveur Tomcat distant à chaque commit sur votre repository. Pour cela, nous allons utiliser le plugin Remote SSH pour Jenkins.

Prérequis

Lors de l’atelier, les différents outils étaient fournis sur des machines virtuelles Linux sur Amazon EC2. Si vous souhaitez refaire les manipulations sur votre poste, vous aurez besoin d’installer :

Il vous faudra donc une machine distante avec un serveur SSH si vous souhaitez réaliser cet exemple.

Téléchargement du projet d’exemple

Nous avons mis à disposition un projet d’exemple xebia-petclinic-lite sous GitHub. Pour tester cet article, vous pouvez cloner ce projet. Nous avons déjà décrit cette partie dans notre précédent article.

git clone https://github.com/xebia-france-training/xebia-petclinic-lite.git

Vous devez avoir un serveur Nexus installé en local. Une fois installé, vous devez changer dans le pom.xml les URLs des repositories avec vos valeurs (le serveur Nexus des Xebia Tech Events n’est actif que pendant les ateliers).

<distributionManagement>
 <repository>
  <id>xebia-tech-event-nexus-releases</id>
  <name>Xebia Tech Event Nexus Releases</name>
  <url>http://votreNexus/content/repositories/releases</url>
 </repository>
 <snapshotRepository>
  <id>xebia-tech-event-nexus-snapshots</id>
  <name>Xebia Tech Event Nexus Snapshots</name>
  <url>http://votreNexus/content/repositories/snapshots</url>
 </snapshotRepository>
</distributionManagement>

Ensuite, un « mvn deploy » permettra d’avoir un projet fonctionnel déployé dans votre repository.

Création du script

Le script shell que nous allons créer doit assurer les fonctions suivantes :

  • Arrêter Tomcat,
  • Supprimer le war et les dossiers de l’application dans webapps et temp,
  • Télécharger une version de l’application depuis Nexus,
  • Démarrer Tomcat,
  • Effectuer un test de connexion HTTP à la page principale de l’application pour vérifier le bon démarrage de l’application déployée.

Pour le téléchargement du war, nous faisons appel à l’API REST du serveur Nexus. Nous allons utiliser le service /artifact/maven/content, dont voici les paramètres :

  • g : Group id de l’artéfact (Obligatoire).
  • a : Artifact id de l’artéfact (Obligatoire).
  • v : Version de l’artéfact (Obligatoire) Supporte les mots-clés comme « LATEST », « RELEASE » et les version SNAPSHOT ou non (« 1.0-SNAPSHOT », « 1.2.3′ …).
  • r : Identifiant du repository Nexus qui contient l’artéfact (Obligatoire). Attention, par défaut, les artéfacts versionnés et les snapshots ne sont pas stockés dans le même repository. Donc pensez à mettre le bon identifiant de repository ici « releases » ou « snapshots » (rechercher des versions SNAPSHOT dans le repository RELEASES ne va pas être simple !). Petite astuce, vous pouvez aller voir dans votre settings.xml de Maven pour connaitre les repositories (normalement, seulement présent sur le serveur d’intégration continue).
  • p : Type de packaging de l’artéfact (Optionnel, par défaut il vaut .jar, donc pour un .war, il faut bien penser à le spécifier).
  • c : Qualificatif de l’artifact (Optionnel, voir la notion d’identifier dans MAVEN).
  • e : Extension de l’artéfact (Optionnel) A VOIR

Ainsi, télécharger la dernière snapshot d’un artefact peut se faire grâce à une simple commande CURL sous Unix, dont voici un exemple :

curl "http://nexus.xebia-tech-event.info:8081/nexus/service/local/artifact/maven/content?g=fr.xebia.demo.petclinic&a=xebia-petclinic-lite&r=snapshots&v=LATESTS&e=war" \
   --silent \
   --show-error  \
   --output "/opt/tomcat/apache-tomcat-6/webapps/xebia-petclinic-lite.war"

Comme dit plus haut, le serveur Nexus du Xebia Tech Event est démarré uniquement pendant les ateliers, inutile donc d’essayer cette URL depuis chez vous !

Pour vérifier le bon démarrage de Tomcat, on peut de nouveau utiliser la commande CURL pour vérifier si l’application est bien déployée. En voici un exemple :

curl --connect-timeout 10 --retry 10 --silent --show-error -w "%{http_code}" -o /dev/null http://localhost:8080/xebia-petclinic-lite

Vous pouvez retrouver le script complet qui nous a servi pendant l’atelier sur tomcat-deploy-petclinic. Seules quelques adaptations seront nécessaires pour utiliser ce script sur vos environnements de production (changement de groupId, d’URL de repository Nexus, etc).

Le plugin Remote SSH pour Jenkins

Notre script est maintenant prêt. Il ne vous reste plus qu’à le transférer vers votre machine distante (par SCP ou FTP, comme bon vous semble). Une fois sur le serveur, vous pouvez le lancer « à la main » pour vérifier qu’il fonctionne.

Dans notre exemple, nous nous authentifions sur les serveurs grâce à des clés privées, mais le reste de l’exercice peut aussi se faire avec un login et un mot de passe si vous le souhaitez.

Le Jenkins Remote SSH Plugin permet de se connecter à un serveur distant et d’y exécuter une série de lignes de commande. Un des avantages majeurs de la solution est qu’elle n’est pas intrusive. En effet, il n’y a pas d’agent spécifique à installer sur la machine, un simple accès SSH suffit. La gestion des clés et mots de passe se trouve ainsi centralisée dans Jenkins.
Lancer le script fait donc parti d’un job Jenkins. On pourra ainsi créer des workflows avec une succession de jobs.

Installation et configuration du plugin

Pour installer le plugin, rendez-vous dans la partie Administrer Jenkins, Gestion des plugins, puis dans l’onglet Disponible. Cochez la ligne devant le plugin, puis cliquez sur le bouton Installer qui se trouve tout en bas de la page.

Une fois le plugin installé, il faut configurer la liste des hôtes que nous voulons utiliser dans nos Builds. Pour cela, rendez vous dans la partie Administrer Jenkins, Configurer le système. Vous avez accès une section SSH Remote hosts dans laquelle nous allons déclarer les hôtes. Les boutons Ajouter et Supprimer permettent de gérer facilement la liste. Ensuite, il n’y a plus qu’à remplir les hôtes avec les informations suivantes :

  • Hostname : serveur hébergeant votre Tomcat (Obligatoire),
  • Port : d’écoute SSH (Optionnel, 22 par défaut),
  • User Name : nom de l’utilisateur qui sera connecté au serveur (Obligatoire),
  • Password/Passphrase : si vous utilisez une authentification simple, c’est ici qu’on ajoute le mot de passe, sinon cela peut aussi être la passphrase (Optionnel),
  • Keyfile : si vous utilisez une authentification avec clé privée, on ajoute ici le chemin vers la clé qui doit se trouver sur le même serveur que Jenkins (Optionnel).

Petit inconvénient, il est impossible de créer un alias pour la configuration de chaque serveur. De plus, la liste des hôtes est unique pour toute l’instance Jenkins. Si plusieurs projets sont présents sur l’instance, avec des noms d’hôtes relativement similaire, cela peut nuire à la lisibilité.

Exploitation du script

Après avoir installé votre script sur la machine Tomcat et avoir déclaré ce serveur Tomcat dans Jenkins, nous allons maintenant configurer l’invocation du script.
Pour cela, il suffit de créer un projet Free-style dans Jenkins, de cocher l’option Execute shell script on remote host using SSH.
Sélectionnez ensuite l’hôte qui vous intéresse, puis dans la partie Post-build script, ajoutez la commande de lancement de votre script shell (par exemple /usr/local/script/deploy_on_tomcat ).
Vous pouvez lancer le job pour vérifier son fonctionnement.
Nous avons créé un job séparé ici, mais rien ne vous empêche de l’intégrer directement dans votre build Jenkins principal. Si vous déclenchez une intégration continue à chaque commit sur le dépôt de source, vous allez ainsi faire du déploiement continu sur votre serveur.
Si l’on possède plusieurs machines, il faudra par contre créer plusieurs jobs différents (c’est-à-dire créer plusieurs projets Free Style). L’hôte n’est pas paramétrable.

Conclusion

Pour résumer, nous pouvons dresser le bilan suivant de l’utilisation du jenkins-ssh-plugin pour automatiser le déploiement depuis Jenkins sur des serveurs Tomcat :

Avantages

  • Simple et rapide à mettre en place,
  • Pas d’agent à installer sur les serveurs,
  • Gestion centralisée des accès aux machines,
  • Se branche facilement sur l’intégration continue pour un déploiement continu en 0 clic,
  • Compatible avec un mode de livraison en production (avec un bon script bien robuste, rien n’est impossible !).

Inconvénients

  • Liste statique des hôtes
  • Tous les hôtes sont à un seul endroit dans la configuration, cela devient compliqué à gérer avec un nombre croissant d’environnements,
  • Le job est lié à la machine sur laquelle il exécute le script,
  • Impossible de déployer l’application sur plusieurs machines, sauf à créer plusieurs jobs,
  • Le script doit être déployé préalablement sur le(s) serveur(s) Tomcat.

Publié par Xavier Bucchiotty

Software Engineer Scala Fanboy FP constant learner Akka trainer

Commentaire

5 réponses pour " Retour Atelier Continuous Delivery – Partie 2 – Déploiement continu avec Jenkins Remote SSH Plugin "

  1. Publié par , Il y a 7 années

    Bonjour,

    Pour effectuer ce genre de déploiement continu, nous utilisons ici un packaging RPM (nos serveurs sont sous RHEL5) qui est fait pas le plugin rpm-maven-plugin.

    Ensuite on utilise le exec-maven-plugin pour exécuter un simple script de déploiement qui copie le RPM généré sur le serveur et exécute la commande d’installation. Des paramètres passés à maven permettent de sélectionner les serveurs de déploiement soit sur la ligne de commande, soit dans Jenkins.

    On y retrouve le même genre de problème, la liste des serveurs est centralisée.

    Les avantages :
    – déploiement possible sur plusieurs serveurs
    – le packaging en rpm permet de gérer tous les scripts de pré/post installation
    – on ne dépend pas de Jenkins
    – le packaging rpm est accepté et apprécié par les équipes de mise en prod classique

    Les inconvénients :
    – on repose sur un script shell pas vraiment industrialisé
    – Le script est à inclure dans tous les projets (on pourrait se passer de ça en faisant un plugin mayen)

  2. Publié par , Il y a 7 années

    Comment gérez-vous les migrations de base de données? Avec quelque chose comme DbDeploy ou Flyway? Et avant toute migration, faites-vous des backups à chaud?

  3. Publié par , Il y a 7 années

    @GB,

    Merci de soulever la question du déploiement des changements de base de données sur lequel nous aurions du détailler plus notre raisonnement.

    La mise à jour des bases de données est un sujet à part entière avec ses patterns, sa littérature (e.g. Refactoring Databases: Evolutionary Database Design) et ses outils (e.g. DbDeploy ou Flyway que vous citez). Sujet que nous ne traitons pas aujourd’hui :-).

    Nous avons pris une hypothèse simplificatrice : la mise à jour des bases de données est un cas marginal du déploiement automatisé sur les environnements de test / validation.
    Nous pensons que le déploiement automatisé après chaque commit/push sur un environnement de test apporte beaucoup de valeur car il permet d’automatiser les tests bout-en-bout (Selenium, user acceptance, performances, etc). De même, planifier un déploiement sur l’environnement de recette de la dernière version qui a passé les « user acceptance tests » permet de toujours faire travailler l’équipe de Q&A sur la dernière version. Pour éviter l’indisponibilité en journée d’un déploiement ‘rustique et brutal’, nous proposons de planifier ces déploiements chaque nuit.
    Si la base de données change une ou deux fois par itération. Notre hypothèse simplificatrice est très efficace.

    Une fois l’équipe mature sur le déploiement automatisé de la seule webapp, nous proposons d’aborder :
    1. l’automatisation du déploiement complet (inclus SGBD)
    2. les déploiements sans interruption de service (session draining, etc)
    3. la dé-corrélation déploiement/activation-de-nouvelles-fonctionnalités grâce à des feature toggles

    Pour conclure, nous sommes d’accord, la mise à jour des SGBD est importante … mais nous le traiterons dans une autre série de billets :-)

    Cyrille (Xebia)

  4. Publié par , Il y a 6 années

    Merci pour cette série de tutos. N’ayant pas pu participer à tous les workshops je vous suis très reconnaissant de les avoir mis en ligne, et en plus cela permet de s’y replonger plusieurs mois après !

    Il y a une petite typo dans l’exemple montrant comment télécharger la dernière snapshot d’un artefact :
    g=fr.xebia.demo.petclinict
    Ça ne saute pas forcément aux yeux mais la lettre t est en trop. En effet, j’ai passé une paire d’heures à essayer de comprendre pourquoi mon nexus me renvoyait systématiquement 404 avant de m’en rendre compte !… :)

  5. Publié par , Il y a 6 années

    Merci pour tes retours.

    Et la coquille est corrigée. Désolé pour les heures des 404 :-)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Xebian, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.