Semplice pipeline di Jenkins con Marathon e Mesos

1. Introduzione

In questo articolo, implementeremo una semplice pipeline di consegna continua con Jenkins, Marathon e Mesos.

Per prima cosa, forniremo una panoramica di alto livello dello stack tecnologico e dell'architettura, con una spiegazione di come tutto si integra. Successivamente, passeremo a un esempio pratico, passo dopo passo.

Il risultato di ciò sarà una pipeline Jenkins completamente automatizzata, che distribuirà la nostra applicazione al nostro cluster Mesos utilizzando Marathon.

2. Panoramica dello stack tecnologico

Quando lavoriamo con container e architetture di microservizi, dobbiamo affrontare nuovi problemi operativi che non avremmo risolto con stack più tradizionali.

Ad esempio, durante la distribuzione in un cluster, dobbiamo gestire la scalabilità, il failover, il networking e altro ancora. Questi difficili problemi di calcolo distribuito possono essere risolti con kernel distribuiti e scheduler, come Apache Mesos e Marathon.

2.1. Mesos

Mesos, in termini più semplici, può essere visto come l'unico server in cui verranno eseguite le nostre applicazioni. In realtà, abbiamo un cluster, ma è questa astrazione che lo rende così utile.

2.2. Maratona

Marathon è il framework utilizzato per distribuire le nostre applicazioni su Mesos, risolvendoci problemi difficili (controllo dello stato, scalabilità automatica, failover, monitoraggio ecc.).

3. Configurazione e installazione

Questo articolo presuppone che tu abbia già Jenkins, Mesos e Marathon in esecuzione. In caso contrario, consultare la documentazione ufficiale di ciascuno di essi per apprendere come configurarli. Senza questo, non sarai in grado di implementare nessuno dei passaggi della guida.

4. La nostra pipeline di consegna

Creeremo la seguente pipeline Jenkins:

Non c'è niente di particolarmente complesso in questo approccio: è sinonimo del flusso delle più moderne pipeline di CD. Nel nostro caso, costruire significherà containerizzare l'applicazione e distribuire significherà usare Marathon per programmarla su un cluster Mesos.

5. Testare e costruire la nostra applicazione

Il primo passo è creare e testare la nostra applicazione. Per mantenere le cose semplici, l'applicazione con cui lavoreremo è un'applicazione Spring Boot. Per questo motivo, il nostro artefatto risultante sarà un jar eseguibile. Non avrà dipendenze esterne diverse da JRE, rendendolo molto semplice da eseguire.

5.1. Creare il nostro lavoro

La prima cosa che vogliamo fare è creare il nostro lavoro Jenkins. Selezioniamo "Nuovo elemento" nella barra di navigazione a sinistra, quindi selezioniamo crea un progetto freestyle, chiamandolo " marathon-mesos-demo " :

5.2. Integrazione con Git

Successivamente, configuriamolo per clonare il repository Github contenente la nostra applicazione:

Per semplicità, il nostro repository è pubblico, il che significa che siamo in grado di clonare su https . Se non fosse così e stessimo clonando su SSH, ci sarebbe un passaggio aggiuntivo per configurare un utente SSH e una chiave privata, oltre lo scopo di questo articolo.

5.3. Configurazione dei trigger di build

Successivamente, configuriamo alcuni trigger di build in modo che il nostro lavoro interroghi git per nuovi commit ogni minuto:

5.4. Generazione del nostro script di build

Ora possiamo dire al nostro lavoro di eseguire uno script di shell quando viene eseguito. Dato che stiamo lavorando con un semplice progetto Spring Boot Maven, tutto ciò che dobbiamo fare è eseguire il comando " mvn clean install ". Questo eseguirà tutti i test e creerà il nostro jar eseguibile :

5.5. Costruire il nostro progetto

Ora che abbiamo impostato l'inizio della nostra pipeline, attiviamolo manualmente facendo clic su "Build Now" sul lavoro. Una volta terminato il lavoro, possiamo confermare che è passato contrassegnandolo come blu.

6. Containerizzazione della nostra applicazione

Passiamo alla fase successiva della nostra pipeline, che consiste nel confezionare e pubblicare la nostra applicazione con Docker. Dobbiamo usare Docker poiché i container sono specificamente ciò che Marathon gestisce. Questo non è irragionevole, poiché praticamente qualsiasi cosa può essere eseguita in un contenitore. È più facile per uno strumento come Marathon lavorare con l'astrazione concessa da questi.

6.1. Creazione del Dockerfile

Per prima cosa, creiamo un Dockerfile nella radice del progetto. In sostanza, un Dockerfile è un file contenente le istruzioni per il Docker Deamon su come costruire un'immagine:

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:

In questo caso, è stata assegnata in modo casuale la porta 31143 su localhost, che internamente verrà mappata alla porta 8082 nel nostro contenitore come configurato nella definizione dell'applicazione. Possiamo quindi visitare questo URL nel nostro browser per confermare che l'applicazione viene servita correttamente.

8. Conclusione

In questo articolo abbiamo creato una semplice pipeline di consegna continua utilizzando Jenkins, Marathon e Mesos. Ogni volta che inseriamo una modifica al nostro codice, verrà eseguita in un ambiente pochi minuti dopo.

Gli articoli successivi di questa serie tratteranno argomenti Marathon più avanzati, come il controllo dello stato delle applicazioni, il ridimensionamento e il failover. Possono essere trattati anche altri casi d'uso per Mesos, come l'elaborazione in batch.

Il codice sorgente della nostra applicazione è disponibile su GitHub; questo è un progetto Maven che dovrebbe essere in grado di funzionare così com'è.