概述
持续集成的速度是衡量一个团队敏捷水平的核心指标之一,CI也需要持续升级。
- CI1.0 单机,集中式,只有一台jenkins服务器,负责所有任务。
问题:随着项目的增多,资源出现严重不足,打包失败率飙升, jenkins服务本身也容易崩溃.
- CI2.0 分布式,jenkins master只负责调度,占用资源的编译任务全部交由容器化的slave完成。
问题:slave容器静态分布,持续运行,在没有编译任务时造成资源闲置。
- CI3.0 容器化jenkins master,通过marathon实现持续运行,并通过mesos的jenkins插件实现slave动态创建和销毁,实现资源的按需利用。
资源调度:Mesos
Apache Mesos是一款开源集群管理软件。Mesos经过了Facebook,Twitter这些大型公司的万台主机验证,在国内,爱奇艺、去哪网,小米网等公司也拥有大规模的Mesos集群应用。Mesos实现了两级调度架构,可以管理多种类型的应用程序,支持Docker。第一级调度是Master的守护进程,管理Mesos集群中所有节点上运行的Slave守护进程。集群由物理服务器或虚拟服务器组成,用于运行应用程序的任务,比如Hadoop和MPI作业。第二级调度由被称作Framework的“组件”组成。Framework包括调度器(Scheduler)和执行器(Executor)进程,其中每个节点上都会运行执行器。Mesos能和不同类型的Framework通信,每种Framework由相应的应用集群管理。图中只展示了Hadoop和MPI两种类型,其它类型的应用程序也有相应的Framework。Mesos支持多种Framework,比如说Hadoop,Spark,Storm等等,各类型的Framework在它上面都可以运行。
mesos的核心功能是资源收集和任务分配,如下:
容器管理:Marathon
Marathon 是可以和 Mesos 一起协作的一个 framework,用来运行持久性的应用,比如docker。用户可以通过WEB UI和API将应用发布到mesos集群中。
扩展和故障恢复
比如我们启动三个服务,分别是一个节点的,三个节点的和五个节点的。我们想拓展这些服务的话,可以调用Marathon的API进行扩展,并且是秒级的。如果有一台主机宕掉了, Marathon会均匀地把服务迁移到其他的机器上,选择资源有空余的机器进行迁移。这样能就保证服务是动态的调度,保证服务的高可用,并且这些都是它内部自行处理的,不需要手动干预。
Jenkins 与 Mesos 集成
Jenkins和Mesos的集成由master的容器化,和slave的动态创建、销毁两部分组成。由于Jenkins与mesos的集成需要mesos库的支持,造成Jenkins官方的镜像无法使用,所以需要在官方镜像中写入mesos。另外,通过marathon在mesos中运行Jenkins master,以保证master的持续可用性。对于slave的调度,mesos官方提供了jenkins的插件,为jenkins提供了调度mesos资源的能力,如下:
部署
整个部署包括Mesos集群、Marathon框架和Jenkins服务,Mesos和Marathon支持集群模式,所以需要Zookeeper来存储配置信息,实现集群的选举。
zookeeper集群
下载
$ wget http://apache.fayea.com/zookeeper/stable/zookeeper-3.4.8.tar.gz
$ tar zxvf zookeeper-3.4.8.tar.gz
$ ln -s zookeeper-3.4.8 zookeeper
$ cd zookeeper/conf
$ cp zoo_sample.cfg zoo.cfg
修改配置,3台一致
$ vim zoo.cfg
dataDir=/usr/local/tmp/zookeeper
clientPort=2181
server.1=192.168.197.170:2888:3888
server.2=192.168.197.171:2888:3888
server.3=192.168.197.172:2888:3888
每台服务器设置不同的ID
$ echo "1" > /usr/local/tmp/zookeeper/myid
Mesos、Marathon集群
Mesos官方只提供了源码安装的方式,还好mesosphere提供了各个发行版的二进制包,推荐使用仓库安装。
仓库配置
$ sudo rpm -Uvh http://repos.mesosphere.com/el/7/noarch/RPMS/mesosphere-el-repo-7-1.noarch.rpm
安装
$ sudo yum install -y mesos
mesos-master配置
$ echo 'zk://192.168.197.170:2181,192.168.197.171:2181,192.168.197.172:2181/mesos' > /etc/mesos/zk
$ echo "CLUSTER_NAME" > /etc/mesos-master/cluster
$ echo "IP" > /etc/mesos-master/ip
$ echo "HOSTNAME" > /etc/mesos-master/hostname
mesos-slave配置
$ echo "docker,mesos" > /etc/mesos-slave/containerizers
$ echo "IP" > /etc/mesos-slave/ip
$ echo "HOSTNAME" > /etc/mesos-slave/hostname
启动mesos
$ systemctl start mesos-master
$ systemctl start mesos-slave
访问mesos控制台:http://master_ip:5050
下载marathon
$ wget http://downloads.mesosphere.com/marathon/v1.1.1/marathon-1.1.1.tgz
$ tar zxvf marathon-1.1.1.tgz
$ ln -s marathon-1.1.1 marathon
运行marathon,指定相同的zookeeper启动多台会自动组成一个集群
$ cd marathon/bin
$ nohup ./start -h HOSTNAME --http_credentials "admin:admin" --master zk://zk://192.168.197.170:2181,192.168.197.171:2181,192.168.197.172:2181/mesos --zk zk://192.168.197.170:2181,192.168.197.171:2181,192.168.197.172:2181/marathon &> output.log &
访问marathon控制台:http://master_ip:8080
运行Jenkins master容器
在marathon控制台启动jenkins master容器:
{
"id": "jenkinsmaster",
"cmd": null,
"cpus": 1,
"mem": 600,
"disk": 0,
"instances": 1,
"labels": {
"HAPROXY_GROUP":"external",
"HAPROXY_0_VHOST":"jenkins.evan.com"
},
"container": {
"type": "DOCKER",
"docker": {
"image": "jenkins_mesos",
"network": "BRIDGE",
"portMappings": [
{
"containerPort": 8080,
"hostPort": 31080
},
{
"containerPort": 31500,
"hostPort": 31500
}
],
"parameters": []
},
"healthChecks": [
{
"path": "/login",
"portIndex": 0,
"protocol": "HTTP",
"gracePeriodSeconds": 300,
"intervalSeconds": 60,
"timeoutSeconds": 20,
"maxConsecutiveFailures": 3,
"ignoreHttp1xx": false
}
],
"volumes": [
{
"containerPath": "/var/jenkins_home",
"hostPath": "/data/share/docker/jenkins_master",
"mode": "RW"
}
]
},
"healthChecks": [
{
"protocol": "HTTP",
"path": "/login",
"portIndex": 0,
"gracePeriodSeconds": 300,
"intervalSeconds": 60,
"timeoutSeconds": 20,
"maxConsecutiveFailures": 3
}
],
"env": {
"JENKINS_SLAVE_AGENT_PORT": "31500"
}
}
访问jenkins。
配置mesos jenkins插件
安装mesos插件
在System config界面配置mesos插件
设置mesos库的路径和mesos master的地址
点击右下方Advanced,设置标签、和slave资源
继续点击右下方Advanced,设置slave以容器方式运行
新建job设置标签,测试。
问题
- jenkins的配置存储在文件系统,如果运行jenkins的mesos slave宕机,marathon会在其它slave重新启动,但配置会丢失。
解决:一个方法是使用分布式文件系统,结合marathon的资源控制,确保jenkins只运行在挂载了共享的mesos slave。 另一个方法是通过SCM Sync Configuration Plugin 这个插件将jenkins配置存储在版本库中,实时同步。
- Jenkins在多台mesos slave上运行时会造成ip的变化,无法确定。
解决:通过marathon-lb实现服务发现
参考资料
mesos 文档:http://mesos.apache.org/documentation/latest/
marathon 文档:https://mesosphere.github.io/marathon/docs/
如何做好持续集成——Jenkins on Mesos 实践
Delivering eBay’s CI Solution with Apache Meso