ADDOPS团队霍明明 360云计算
女主宣言
该文章出自于ADDOPS团队,是一篇关于Jenkins 与 Docker 的持续集成实践,当前使用Jenkins做CI,并且支持Docker插件做CD的实践案例使用越来越多,该文章只是一个开始,后续还会有Jenkins与docker集成的一个系列,希望大家能持续关注,最后希望该文章能给大家更多的一些关于持续集成的启发。
PS:丰富的一线技术、多元化的表现形式,尽在“HULK一线技术杂谈”,点关注哦!
前言
持续集成(CI/CD)是一种软件开发实践。用于帮助团队成员频繁、快速的集成,测试他们的工作成果,以尽快发现集成错误。 更频繁、更早的集成意味着更早的发现问题。通过持续集成,及时发现和解决代码故障,提高代码质量,减少故障处理成本等等。
常见持续集成工具
目前持续集成的生态越来越完善,工具也有很多,开源的或商业的。如:
最最流行的,也是使用最多的 Jenkins
有着持续集成DNA的ThoughtWorks GO。理念:"Deployment as pipeline" (华为容器平台应该是基于GO做的二次开发实现)
Atlassian工具链之一的Bamboo (数人云应该是基于Banboo实现的CI/CD)
与Gitlab紧密集成的Gitlab CI
专为开源打造的Travis CI,与Github紧密集成
使用 python 语言实现的Buildbot,相信 pythoner 看到会喜欢
我们的选型是 Jenkins,所以我们来看下 Jenkins
Jenkins
Jenkins 特点
Jenkins是开源的应用最广泛的持续集成工具,支持CI, CD;
Jenkins有很多插件,而且用户也可以自定义插件,可扩展性非常强;
Jenkins对Docker支持非常好,有一套完善的Docker插件;
Jenkins2.0开始支持Pipeline,一个非常强大的插件,使用基于Groovy的DSL,支持CI/CD流水线;
Jenkins 基于 Java 语言开发;
Jenkins 几个概念
master 是jenkins安装和运行的地方,它负责解析job脚本,处理任务,调度计算资源;
agent 负责处理从master分发的任务;
executor 就是执行任务的计算资源,它可以在master或者agent上运行。多个executor也可以合作执行一些任务;
job 任务,用来定义具体的构建过程;
Groovy 是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy 可以使用其他 Java 语言编写的库。Jenkins 用Groovy作为DSL;
pipeline 流水线即代码(Pipeline as Code),通过编码而非配置持续集成/持续交付(CI/CD)运行工具的方式定义部署。流水线使得部署是可重现、可重复的;
流水线包括节点(Node)、阶段(Stage)和步骤(Step)。
流水线执行在节点上。节点是Jenkins安装的一部分。流水线通常包含多个阶段。一个阶段包含多个步骤。流水线上手指南可以查看到更多的内容。
node 在Pipeline中的context中,node是 job 运行的地方。 node会给job创建一个工作空间。工作空间就是一个文件目录,这是为了避免跟资源相关的处理互相产生影响。工作空间是node创建的,在node里的所有step都执行完毕后会自动删除。
stage 阶段,stage是一个任务执行过程的独立的并且唯一的逻辑块,pipeline定义在语法上就是由一系列的stage组成的。 每一个stage逻辑都包含一个或多个step。
step 步骤,一个step是整个流程中的一系列事情中的一个独立的任务,step是用来告诉Jenkins如何做。
Jenkinfile Jenkins支持创建流水线。它使用一种基于Groovy的流水线领域特定语言(Pipeline DSL)的简单脚。而这些脚本,通常名字叫Jenkinsfile。它定义了一些根据指定参数执行简单或复杂的任务的步骤。流水线创建好后,可以用来构建代码,或者编排从代码提交到交付过程中所需的工作。Jenkins中的Jenkinsfile有点类似Docker中的Dockfile的感觉
Jenkins 部署
Jenkins组件其实非常少,安装部署也非常简单。 Jenkins按角色就两类: master节点和slave节点。master安装完成后,在控制台中添加节点即可。
下面以Dcoker的部署方式为例说一下Jenkins的部署:
master 节点
查看 docker hub 中 jenkins 的 image
[root@k3128v /home/huomingming]# docker search jenkinsNAME DESCRIPTION STARS OFFICIAL AUTOMATEDjenkins Official Jenkins Docker image 2600 [OK] stephenreed/jenkins-java8-maven-git Automated build that provides a continuous... 53
可以看到第一个是官方提供的,所以我们选择这个即可。
拉取 jenkins image
docker pull jenkins
启动 jenkins 容器
jenkins没有数据库,所有数据都是存放在文件中的,首先在本地创建jenkins数据目录,用于保存jenkins的数据 这个目录需要定期的备份,用于容灾(当前jenkins容器所在节点由于不可抗因素无法使用时,可以在新机器上使用备份的数据启动新的jenkins master节点)。
sudo mkdir /var/jenkins
sudo chown 1000:1000 /var/jenkins
sudo docker run -p 8080:8080 -p 50000:50000 -v /var/jenkins:/var/jenkins_home --name my_jenkins -d jenkins
这样jenkins就成功跑起来了。可以直接通过机器的8080端口访问jenkins. 本地的/var/jenkins就相当于容器里jenkins用户的用户主目录,所以要保证该目录的权限为uid为j1000的用户目录。
配置 jenkins
启动完 jenkins master 后,在浏览器中数据输入 http://jenkins_master_ip:8080 登录 Jenkins 控制台进行接下来的安装和配置。 具体图就不贴出来了~~
查看jenkins的版本
java -jar /usr/share/jenkins/jenkins.war --version
slave 节点
安装 java jdk
yun install java-1.8.0-openjdk
创建 jenkins 用户
$ useradd -m jenkins -d /home/jenkins$ passwd jenkins
创建工作目录
mkdir /data/jenkinschown jenkins.jenkins /data/jenkins
添加 jenkins 用户到 docker 用户组
sudo usermod -a -G docker jenkins
配置 ssh 互信,master免密码登陆slave
master 有多种管理 slave 的方式,我们选择SSH方式 在master节点中,切换到jenkins用户 ssh-keygen -t rsa 创建秘钥对 把公钥拷贝到slave节点
scp ~/.ssh/id_rsa.pub jenkins@slave_ip:~/.ssh/authorized_keys
确保在scp前,slave节点根目录下.ssh目录已存在
chmod 700 authorized_keys
使用 jenkins 来构建 docker 是需要安装插件的。那我们需要安装哪些插件呢?
Jenkins 有哪些 Docker 的 Plugins
是非常丰富的,但并不是我们都能用的上,所以需要根据你使用的环境和平台来选择适合自己的 plugin 安装就可以了。 每个 plugin 都需要适配 Jenkins 的版本,且每个 plugin 也需要依赖一些其它 plugin,上面都已经做了标注,需要配套来用。
这里介绍几个常用的 Docker 插件
Docker Commons Plugin
其基本功能:
API for managing Docker image and container fingerprints
Credentials and location of Docker Registry
Credentials and location of Docker Daemon (aka Docker Remote API)
ToolInstallation for Docker CLI clients
DockerImageExtractor extension point to get Docker image relations from jobs
Simple UI referring related image fingerprints in Docker builds
Docker Plugins
该插件是将 docker 作为 jenkins 的 slave 来使用,来在 docker 容器种完成项目的build,build 完成后该容器 slave 容器就会被销毁。所有的工作都是在 slave 容器内完成。
docker-build-step
该插件在 build 过程种增加了对 Docker 命令的支持。
Docker Pipeline Plugin
基于 Docker Commons Plugin 实现的一些上层的基于 Docker 的 Pipeline 编排
Docker Hub Notification Trigger Plugin
该插件提供了当registry中的image发生变化时触发build新镜像的功能。
CloudBees Docker Build and Publish
该插件提供了通过 Dockerfile 来构建项目并将生成的镜像上传到镜像仓库的功能。
CloudBees Docker Custom Build Environment
This plugin allows the definition of a build environment for a job using a Docker container.
该插件适用于 “自由风格的软件项目”,如图:
CloudBees Docker Traceability
用于追踪通过jenkins启停的容器的事件
Kubernetes
This plugin allows Jenkins agents to be dynamically provisioned on a Kubernetes cluster. The aim of the Kubernetes plugin is to be able to use a Kubernetes cluster to dynamically provision a Jenkins agent (using Kubernetes scheduling mechanisms to optimize the loads), run a single build, then tear-down that slave.
与 Kubernetes 结合,通过 kubernetes 提供 jenkins 的 slave 节点。利用 kubernetes 的调度功能提供快速的启停 slave 节点执行 build 等任务。目前是0.11版本,稳定性有待验证。
Jenkins 有没有 API?
因为,我们不是直接在 Jenkins 的 Dashbord 来操作, 而是集成到现有平台,所以我们需要使用它的API。
Jenkins的Remote API以REST的形式进行提供。例如,我们搭建的Jenkins站点为http://myjenkins.com:8080。那么,访问http://myjenkins.com:8080/api 即可查看到该站点所有可用的API;
查询操作
执行一些动作
例如,我要创建一个 job,名字为 my_job
my_job的配置文件
<?xml version='1.0' encoding='UTF-8'?><project>
<actions/>
<description></description>
<keepDependencies>false</keepDependencies>
<properties/>
<scm class="hudson.scm.NullSCM"/>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers class="vector"/>
<concurrentBuild>false</concurrentBuild>
<builders/>
<publishers/>
<buildWrappers/></project>
调用 api 创建 my_job
curl -X POST http://www.xxx.xxx/jenkins/createItem?name=my_job --user uname:pass --data-binary "my_job_config.xml" -H "Content-Type: application/xml"
然后,你就可以在 Jenkins dashboard 上看到这个 job 了。它的管理页面为http://myjenkins.com:8080/job/my_job。那么我们访问 /my_job/api/ 即可查看到该job可用的API。
更多的 api 介绍可以参考Jenkins的官方wiki,这里只是个引子,在此就不过多进行介绍。
总结
该篇文章主要是介绍了Jenkins和docker的持续集成的实现部分,后续还有关于Jenkins的压测、性能扩展、高可用等,还需要持续深入的介绍。敬请关注。