1. Introduction
1.介绍
In this article, we’ll be implementing a simple Continuous Delivery pipeline with Jenkins, Marathon and Mesos.
在本文中,我们将使用Jenkins、Marathon和Mesos实现一个简单的持续交付管道。
First, we will give a high-level overview of the technology stack and architecture, with an explanation of how everything fits together. Following that, we’ll move onto a practical, step by step example.
首先,我们将对技术栈和架构作一个高层次的概述,并解释一切是如何结合在一起的。之后,我们将转到一个实际的、一步一步的例子。
The outcome of this will be a fully automated Jenkins pipeline, deploying our application to our Mesos cluster using Marathon.
这样做的结果将是一个完全自动化的Jenkins管道,使用Marathon将我们的应用程序部署到我们的Mesos集群。
2. Overview of Technology Stack
2.技术栈概述
When working with containers and microservice architectures, we face new operational problems that we wouldn’t have done with more traditional stacks.
在使用容器和微服务架构时,我们面临着新的操作问题,而这些问题在更传统的堆栈中是不会出现的。
For example, when deploying to a cluster, we have to deal with scaling, failover, networking and more. These difficult, distributed computing problems, can be solved with distributed kernels and schedulers, like Apache Mesos and Marathon.
例如,当部署到一个集群时,我们必须处理扩展、故障转移、网络等问题。这些困难的分布式计算问题,可以用分布式内核和调度器来解决,比如Apache Mesos和Marathon。
2.1. Mesos
2.1.中场休息
Mesos, in simplest terms, can be seen as the single server where our applications will be run. In reality, we have a cluster, but it’s this abstraction that makes it so useful.
Mesos,用最简单的话来说,可以看作是我们的应用程序将在其中运行的单一服务器。在现实中,我们有一个集群,但正是这种抽象性使它如此有用。
2.2. Marathon
2.2.马拉松
Marathon is the framework which is used to deploy our applications to Mesos, solving difficult problems for us (health checking, auto-scaling, failover, monitoring etc).
Marathon是用于将我们的应用程序部署到Mesos的框架,为我们解决了一些棘手的问题(健康检查、自动扩展、故障转移、监控等)。
3. Setup and Installation
3.设置和安装
This article assumes you already have Jenkins, Mesos and Marathon running. If this is not the case, consult the official documentation for each of them to learn how to set them up. Without this, you won’t be able to implement any of the steps in the guide.
本文假设你已经运行了Jenkins、Mesos和Marathon。如果不是这样,请查阅它们各自的官方文档,了解如何设置它们。没有这些,你将无法实施指南中的任何步骤。
4. Our Delivery Pipeline
4.我们的交付管道
We shall be creating the following Jenkins pipeline:
我们将创建以下Jenkins流水线。
There’s nothing particularly complex about this approach – it’s synonymous to the flow you of most modern CD pipelines. In our case, building will mean containerising the application, and deploying will mean using Marathon to schedule it on a Mesos cluster.
这种方法并不特别复杂–它与大多数现代CD管道的流程是同义的。在我们的案例中,构建意味着将应用程序容器化,而部署意味着使用马拉松将其安排在Mesos集群上。
5. Testing and Building Our Application
5.测试和构建我们的应用程序
The first step is to build and test our application. To keep things simple, the application we are going to be working with is a Spring Boot application. Because of this, our resulting artifact will be an executable jar. It won’t have any external dependencies other than the JRE, making it very simple to execute.
第一步是建立和测试我们的应用程序。为了简单起见,我们将要使用的应用程序是一个Spring Boot应用程序。正因为如此,我们生成的工件将是一个可执行的jar。除了JRE之外,它没有任何外部依赖,这使得它的执行非常简单。
5.1. Creating Our Job
5.1.创造我们的工作
The first thing we want to do is create our Jenkins job. Let’s select “New Item” in the left-hand navigation bar, then select create a freestyle project, naming it “marathon-mesos-demo“:
我们要做的第一件事是创建我们的Jenkins工作。让我们在左侧导航栏中选择 “新项目”,然后选择创建一个自由式项目,将其命名为”marathon-mesos-demo“:。
5.2. Integrating With Git
5.2.与Git集成
Next, let’s configure it to clone the Github repository containing our application:
接下来,让我们将其配置为克隆包含我们应用程序的Github仓库。
For the sake of simplicity, our repository is public, meaning that we are able to clone over https. If this wasn’t the case and we were cloning over SSH, there would be an additional step to set up an SSH user and private key, beyond the scope of this article.
为了简单起见,我们的版本库是公开的,这意味着我们可以通过 https 克隆。如果不是这样,我们通过 SSH 克隆,将有一个额外的步骤来设置 SSH 用户和私钥,超出了本文的范围。
5.3. Setting up Build Triggers
5.3.设置构建触发器
Next, let’s set up some build triggers so our job will poll git for new commits every minute:
接下来,让我们设置一些构建触发器,这样我们的工作将每分钟轮询git的新提交。
5.4. Generating Our Build Script
5.4.生成我们的构建脚本
We can now tell our job to execute a shell script when it runs. As we are working with a simple Spring Boot Maven project, all we need to do is run the command “mvn clean install“. This will run all the tests, and build our executable jar:
现在我们可以告诉我们的工作,让它在运行时执行一个shell脚本。由于我们使用的是一个简单的Spring Boot Maven项目,我们需要做的就是运行”mvn clean install“命令。这将运行所有测试,并构建我们的可执行jar:。
5.5. Building Our Project
5.5.建设我们的项目
Now we’ve set up the beginning of our pipeline, let’s trigger it manually by clicking “Build Now” on the job. Once the job is finished, we can confirm it has passed by it being marked as blue.
现在我们已经建立了管道的起点,让我们通过点击作业上的 “立即构建 “来手动触发它。一旦作业完成,我们可以通过它被标记为蓝色来确认它已经通过。
6. Containerizing Our Application
6. 容器化我们的应用程序
Let us move onto the next stage of our pipeline, which is packaging and publishing our application with Docker. We need to use Docker as containers are specifically what Marathon manages. This isn’t unreasonable, as virtually anything can run in a container. It’s easier for a tool like Marathon to work with the abstraction granted by these.
让我们进入管道的下一个阶段,也就是用Docker打包和发布我们的应用程序。我们需要使用Docker,因为容器是马拉松管理的具体内容。这并不是不合理的,因为几乎任何东西都可以在容器中运行。对于像马拉松这样的工具来说,利用这些容器所赋予的抽象性来工作会更容易。
6.1. Creating the Dockerfile
6.1.创建Docker文件
First, let’s create a Dockerfile in the project root. Essentially, a Dockerfile is a file containing instructions to the Docker Deamon on how to build an image:
首先,让我们在项目根中创建一个Dockerfile。从本质上讲,Dockerfile是一个文件,包含了对Docker Deamon的指示,即如何构建一个镜像。
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′.
我们正在构建的镜像很简单–它所包含的只是一个可执行的jar和一个shell命令,当容器启动时将执行它。我们还必须确保我们暴露了我们的应用程序将监听的端口,在这种情况下是’8082’。
6.2. Publishing the Image
6.2.发布图像
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:
现在我们已经能够构建我们的镜像,让我们创建一个简单的bash脚本,该脚本可以构建并发布到我们的私有Docker Hub仓库,并将其放在我们的项目根中。
#!/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.
你可能需要将你的镜像推送到公共的docker注册中心或你的私人注册中心。
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.
$BUILD_NUMBER环境变量由Jenkins填充,每次构建都会递增。尽管有点脆,但这是让每次构建都增加版本号的快速方法。$DOCKER_PASSWORD也是由Jenkins填充的,在这种情况下,我们将使用EnvInject插件,以便对其进行保密。
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.
虽然我们可以将这个脚本直接存储在Jenkins中,但最好的做法是将其保留在版本控制中,因为它可以和我们项目的其他部分一起进行版本控制和审计。
6.3. Building and Publishing on Jenkins
6.3.在Jenkins上构建和发布
Now let’s modify our Jenkins job so it runs “Dockerise.sh” after building the jar:
现在让我们修改我们的Jenkins作业,使它在构建jar后运行 “Dockerise.sh”。
And then, let’s run our job to confirm again, confirming everything is working by it going blue.
然后,让我们再次运行我们的工作来确认,通过它变成蓝色来确认一切都在工作。
7. Deploying Our Image
7.部署我们的图像
Our pipeline is nearly complete. There is only one more stage, which is to use Marathon to deploy our application to our Mesos cluster.
我们的管道已经接近完成。只有一个阶段了,那就是使用马拉松将我们的应用程序部署到我们的Mesos集群。
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.
Jenkins附带了一个”使用马拉松部署“插件。该插件充当马拉松API的封装器,使其比使用传统的shell脚本时更容易。你可以通过插件管理器来安装它。
7.1. Creating Our Marathon.Json File
7.1.创建我们的Marathon.Json文件
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.
在我们使用马拉松插件之前,我们需要创建一个 “marathon.json “文件,并将其存放在我们的项目根目录下。这是因为该插件依赖于它。
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:
这个文件。”marathon.json “包含一个Mesos应用定义。这是对我们想要运行的长期运行的服务(应用程序)的描述。最终,Jenkins马拉松插件将把文件的内容POST到马拉松/v2/apps端点。然后马拉松将反过来安排定义的应用程序在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.
属性。”portMappings“需要正确设置,以使我们的应用程序可以从我们的Mesos slave访问。这基本上意味着,将容器的端口8082,映射到主机(Mesos slave)上的一个随机端口,这样我们就可以从外部世界与我们的应用程序对话。在部署我们的应用程序后,马拉松会告诉我们这个端口是什么。
7.2. Adding a Marathon Deployment Build Step
7.2.添加马拉松部署的构建步骤
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.
注意,我们要告诉插件马拉松在哪里运行,在这里是 “localhost:8081″。我们还告诉它我们要部署的图像。这就是我们文件中空的 “image “字段被替换成的内容。
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
7.3.验证我们在马拉松中的部署
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 this case, it’s been randomly allocated the port 31143 on localhost, which will internally map to port 8082 in our container as configured in the application definition. We can then visit this URL in our browser to confirm the application is being served correctly.
在这种情况下,它被随机分配到localhost的31143端口,这将在内部映射到应用定义中配置的容器中的8082端口。然后我们可以在浏览器中访问这个URL,以确认应用程序被正确提供。
8. Conclusion
8.结论
In this article, we’ve created a simple Continuous Delivery pipeline using Jenkins, Marathon, and Mesos. Whenever we push a change to our code, it will be running in an environment a few minutes later.
在这篇文章中,我们使用Jenkins、Marathon和Mesos创建了一个简单的持续交付管道。每当我们推送一个对代码的修改,几分钟后它就会在一个环境中运行。
Later articles in this series will cover more advanced Marathon topics, such as application health checking, scaling, failover. Other use cases for Mesos, such as batch processing may also be covered.
本系列文章的后面部分将涵盖更高级的马拉松主题,如应用健康检查、扩展、故障转移。Mesos的其他用例,如批处理,也可能会涉及。
The source code for our application is available on over on GitHub; this is a Maven project which should be able to run as is.
我们应用程序的源代码可在GitHub上找到;这是一个Maven项目,应该可以按原样运行。