Pipeline Jenkins simple avec Marathon et Mesos

1. Introduction

Dans cet article, nous allons implémenter un pipeline de livraison continue simple avec Jenkins, Marathon et Mesos.

Tout d'abord, nous donnerons un aperçu de haut niveau de la pile technologique et de l'architecture, avec une explication de la façon dont tout s'emboîte. Ensuite, nous passerons à un exemple pratique, étape par étape.

Le résultat sera un pipeline Jenkins entièrement automatisé, déployant notre application sur notre cluster Mesos à l'aide de Marathon.

2. Présentation de la pile technologique

Lorsque nous travaillons avec des conteneurs et des architectures de microservices, nous sommes confrontés à de nouveaux problèmes opérationnels que nous n'aurions pas pu résoudre avec des piles plus traditionnelles.

Par exemple, lors du déploiement sur un cluster, nous devons gérer la mise à l'échelle, le basculement, la mise en réseau, etc. Ces problèmes informatiques difficiles et distribués peuvent être résolus avec des noyaux et des planificateurs distribués, comme Apache Mesos et Marathon.

2.1. Mesos

Mesos, en termes plus simples, peut être considéré comme le serveur unique sur lequel nos applications seront exécutées. En réalité, nous avons un cluster, mais c'est cette abstraction qui le rend si utile.

2.2. Marathon

Marathon est le framework utilisé pour déployer nos applications sur Mesos, en résolvant des problèmes difficiles pour nous (vérification de l'état, mise à l'échelle automatique, basculement, surveillance, etc.).

3. Configuration et installation

Cet article suppose que vous avez déjà Jenkins, Mesos et Marathon en cours d'exécution. Si ce n'est pas le cas, consultez la documentation officielle de chacun d'eux pour savoir comment les configurer. Sans cela, vous ne pourrez mettre en œuvre aucune des étapes du guide.

4. Notre pipeline de livraison

Nous allons créer le pipeline Jenkins suivant:

Il n'y a rien de particulièrement complexe dans cette approche - elle est synonyme de flux de la plupart des pipelines de CD modernes. Dans notre cas, la construction signifiera la conteneurisation de l'application, et le déploiement signifiera utiliser Marathon pour la planifier sur un cluster Mesos.

5. Test et construction de notre application

La première étape consiste à créer et tester notre application. Pour simplifier les choses, l'application avec laquelle nous allons travailler est une application Spring Boot. Pour cette raison, notre artefact résultant sera un fichier jar exécutable. Il n'aura aucune dépendance externe autre que le JRE, ce qui le rend très simple à exécuter.

5.1. Créer notre travail

La première chose que nous voulons faire est de créer notre travail Jenkins. Sélectionnez "Nouvel élément" dans la barre de navigation de gauche, puis sélectionnez créer un projet freestyle, en le nommant " marathon-mesos-demo " :

5.2. Intégration avec Git

Ensuite, configurons-le pour cloner le référentiel Github contenant notre application:

Par souci de simplicité, notre référentiel est public, ce qui signifie que nous pouvons cloner via https . Si ce n'était pas le cas et que nous clonions via SSH, il y aurait une étape supplémentaire pour configurer un utilisateur SSH et une clé privée, au-delà de la portée de cet article.

5.3. Configurer les déclencheurs de compilation

Ensuite, configurons quelques déclencheurs de construction afin que notre travail interroge git pour de nouveaux commits toutes les minutes:

5.4. Générer notre script de construction

Nous pouvons maintenant dire à notre travail d'exécuter un script shell lorsqu'il s'exécute. Comme nous travaillons sur un simple projet Spring Boot Maven, tout ce que nous avons à faire est d'exécuter la commande « mvn clean install ». Cela exécutera tous les tests et construira notre fichier jar exécutable :

5.5. Construire notre projet

Maintenant que nous avons configuré le début de notre pipeline, déclenchons-le manuellement en cliquant sur «Construire maintenant» sur le projet. Une fois le travail terminé, nous pouvons confirmer qu'il est passé en étant marqué en bleu.

6. Conteneurisation de notre application

Passons à l'étape suivante de notre pipeline, qui consiste à empaqueter et à publier notre application avec Docker. Nous devons utiliser Docker car les conteneurs sont spécifiquement ce que gère Marathon. Ce n'est pas déraisonnable, car pratiquement tout peut fonctionner dans un conteneur. Il est plus facile pour un outil comme Marathon de travailler avec l'abstraction accordée par ceux-ci.

6.1. Création du Dockerfile

Commençons par créer un Dockerfile à la racine du projet. Essentiellement, un Dockerfile est un fichier contenant des instructions au Docker Deamon sur la façon de créer une image:

FROM openjdk:8-jre-alpine ADD target/mesos-marathon-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8082 ENTRYPOINT ["java","-jar","/app.jar"]

The image we are building is simple – all it contains is an executable jar and a shell command which will execute it when the container starts. We also have to make sure that we are exposing the port that our application will listen on, in this case ‘8082'.

6.2. Publishing the Image

Now that we are able to build our image, let's create a simple bash script which builds and publishes it to our private Docker Hub repository, and put it in our project root:

#!/usr/bin/env bash set -e docker login -u baeldung -p $DOCKER_PASSWORD docker build -t baeldung/mesos-marathon-demo:$BUILD_NUMBER . docker push baeldung/mesos-marathon-demo:$BUILD_NUMBER 

You might need to push your image to the public docker registry or your private one.

The $BUILD_NUMBER environment variable is populated by Jenkins, incrementing with every build. Although slightly brittle, it is a quick way of getting each build to increase in version number. The $DOCKER_PASSWORD is also populated by Jenkins, and in this case, we will make use of the EnvInject plugin in order to keep it secret.

Whilst we could store this script directly in Jenkins, it's better practice for it to remain in version control, as it can then be versioned and audited alongside the rest of our project.

6.3. Building and Publishing on Jenkins

Now let's modify our Jenkins job so it runs “Dockerise.sh” after building the jar:

And then, let's run our job to confirm again, confirming everything is working by it going blue.

7. Deploying Our Image

Our pipeline is nearly complete. There is only one more stage, which is to use Marathon to deploy our application to our Mesos cluster.

Jenkins comes with a “Deploy with Marathon” plugin. This acts as a wrapper around the Marathon API, making it easier than it would be when working with traditional shell scripting. You can install it via the plugin manager.

7.1. Creating Our Marathon.Json File

Before we can use the Marathon plugin, we need to create a “marathon.json” file, and store it in our project root. This is because the plugin is dependent on it.

This file: “marathon.json” contains a Mesos Application Definition. This is a description of a long-running service (application) that we want to run. Ultimately, the Jenkins Marathon plugin will POST the contents of the file to the Marathon /v2/apps endpoint. Marathon will then in turn schedule the defined application to run on Mesos:

{ "id": "mesos-marathon-demo", "container": { "type": "DOCKER", "docker": { "image": "", "network": "BRIDGE", "portMappings": [ { "containerPort": 8082, "hostPort": 0 } ] } } }

This is the simplest configuration we can give for a containerized application.

The property: “portMappings” needs to be set correctly in order to make our application accessible from our Mesos slave. It basically means, map the container port 8082, to a random port on the host (mesos slave) so we can talk to our application from the outside world. After deploying our application, Marathon will tell us what that port used.

7.2. Adding a Marathon Deployment Build Step

Let's add a Marathon Deployment post build action to our job:

Notice we're telling the plugin where Marathon is running, in this case ‘localhost:8081'. We're also telling it the image we want to deploy. This is what the empty “image” field in our file get's replaced with.

Now we've created the final stage of our pipeline, let's run our job one more time and confirm that it's still passing, this time with the extra step where it sends our application to Marathon.

7.3. Verifying Our Deployment in Marathon

Now it's been deployed, let's take a look in the Marathon UI:

As we can see, our application is now shown in the UI. In order to access it, we just need to check what host and port it has been assigned:

Dans ce cas, il a été alloué au hasard le port 31143 sur localhost, qui sera mappé en interne au port 8082 dans notre conteneur tel que configuré dans la définition de l'application. Nous pouvons ensuite visiter cette URL dans notre navigateur pour confirmer que l'application est correctement diffusée.

8. Conclusion

Dans cet article, nous avons créé un pipeline de livraison continue simple à l'aide de Jenkins, Marathon et Mesos. Chaque fois que nous poussons une modification à notre code, il s'exécutera dans un environnement quelques minutes plus tard.

Les articles ultérieurs de cette série couvriront des sujets Marathon plus avancés, tels que la vérification de l'état des applications, la mise à l'échelle, le basculement. D'autres cas d'utilisation de Mesos, tels que le traitement par lots, peuvent également être couverts.

Le code source de notre application est disponible sur over sur GitHub; c'est un projet Maven qui devrait pouvoir fonctionner tel quel.