Jenkins持续集成工具

Jenkins介绍整理于:https://www.jianshu.com/p/5f671aca2b5a

Jenkins介绍

jenkins可以在代码上传仓库(如github,gitlab)后,在jenkins(一个网站界面)中通过获取代码仓库中最新代码,进行自动化部署,而省去手动打包、上传服务器、部署这一系列步骤,非常方便。

Jenkins起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行。Jenkins用Java语言编写,可在Tomcat等流行的servlet容器中运行,也可独立运行。通常与版本控制工具(SCM)、构建工具结合使用。常用的版本控制工具有SVN、GIT,构建工具有Maven、Ant、Gradle。

CI / CD

持续集成

CI(Continuous integration,中文意思是持续集成)是一种软件开发实践。持续集成强调开发人员提交了新代码之后,立刻进行构建、(单元)测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。借用网络图片对CI加以理解。

很多公司还基于Jenkins开发了自己的插件,从而与内部自研系统进行集成。并且,Jenkins 2.x版本支持Pipeline as Code特性,允许用户通过代码来定义流水线,从而可以将CI过程也纳入版本管理,这与近几年诞生的GitOps理念不谋而合。此外,Jenkins社区也诞生了kubernetes-plugin这样的插件,使得我们可以将流水线的执行从传统的物理机转移到容器中,再依托Kubernetes的调度能力,就可以实现动态的资源调度和利用。

不过,Jenkins由于历史悠久,插件众多,要想用好它也并不容易。不论是1.x版本的UI配置风格,还是2.x的Groovy脚本,对于普通开发者而言,都是有一定的学习成本的。除此之外,Jenkins作为一个半自动的持续集成工具,很多时候我们的需求场景都需要基于jenkins编写一些脚本,导致整体接入效率较低,且无法标准化。最后,Jenkins开源版本也缺乏一些企业级的特性,比如隔离性、服务高可用等等。

持续交付

CD(Continuous Delivery, 中文意思持续交付)是在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境(类生产环境)中。比如,我们完成单元测试后,可以把代码部署到连接数据库的Staging环境中更多的测试。如果代码没有问题,可以继续手动部署到生产环境。下图反应的是CI/CD 的大概工作模式。

为什么要持续集成

想象一下这个场景,我们实际的项目中经常会遇到这种情况,客户临时提出一个需求,让我们短时间内做出一个产品原型,然后客户看了满意之后再在这个产品原型的基础上提出一些新的需求点,然后不断迭代这个过程。

如果我们按照原来的瀑布流程来开发产品肯定是无法完成这个任务的,首先就卡在需求上,因为客户无法提供完整的需求,我们就无法根据需求来开发一个完成度很高的产品,那么客户就会产生不满,公司拿不到项目会因此丢单。

其次,时间问题,无法短时间内完成一个高完成度的产品,如果赶工可能会存在产品有重大缺陷无法被发布之前就发现,导致公司由此蒙受损失。

为了避免以上这些风险,持续集成就成了一个很好的解决问题方案,它能保证团队开发人员提交代码的质量,减轻了软件发布时的压力;

持续集成中的任何一个环节都是自动完成的,无需太多的人工干预,有利于减少重复过程以节省时间、费用和工作量。

大规模部署的烦恼

对于同样的功能,在用户量不同的系统中,工作量是完全不同的,后台为性能考虑而设计的架构完全不一样。对于CI&CD 也是如此,小规模的很容易,配几个作业就可以完成工作,但对于大规模的CI&CD,一旦系统数量、实例数量上去后各种问题就都来了。下面列举几个主要的问题。

1)更新问题。更新一次要耗费大量精力,很多企业都是晚上更新,员工得通宵加班,还不能保证更新没问题,不具备快速大批量部署的能力。

2)部署包(jar 包、war 包、ear 包等)的管理问题。为了保证版本可追溯,出错后能够回滚,我们需要保存各个历史版本,而且方便下载。

3)版本的安全性。传统上以Java 语言开发的系统多数以jar 包、war 包、ear 包的方式发布,容易被篡改(人为修改,传输过程不完整);通常我们用md5 来验证完整性,但包与md5 对应关系的管理并没有系统化,往往在出问题后人工进行md5 验证。

4)主机管理问题。系统部署到哪些机器上需要进行主机管理?在部署时人工选择部署到哪台主机显然不是一种明智的方式,能否自动进行调度?同时,不会产生有些主机性能堪忧、有些主机空闲导致的负载不均情况。

5)端口管理问题,在部署Java 项目时我们并不建议设置太多的JVM 内存,因此一台主机上往往能够部署多个应用实例,同一台机器上多个实例的开放端口就必须不一致,于是端口又成了需要管理的资源。有人会说可以选用虚拟机,一台虚拟机上只部署一个实例。当然,这也是可以的。实际上,多数企业也是这么做的。这种做法也有弊端,虚拟机虽然帮助做了隔离,但会损失一些主机性能;虚拟机要使用内网IP,这样IP 又成了稀有资源,当部署多个实例时IP 会不够用。

6)负载均衡管理问题。不管是在主机上部署多个实例,还是利用虚拟机来部署多个实例,在做集群时,都会通过代理(Nginx、Apache、LVS……)软件来做负载均衡,因此我们需要把各实例的访问地址配置到负载器的配置文件中。实例数少的时候手工配置还可以接受,多了就没法手工配置了。当然,方法也会有,比如用Etcd+Confd+Nginx(HAProxy)来做服务发现,我们需要自己部署一套工具,并进行维护,复杂的框架提高了对运维人员的要求。

7)服务伸缩问题。当服务访问量上去后,要能够具备快速扩充的能力;当访问量下去后,要能够具备缩小服务规模的能力,收放自如。这种弹性的服务能力显然是通过工具来完成的,手动完成是不可能的。

8)IP 管理问题。当大规模部署后,IP 资源会成为稀有资源,如何用更少的IP 来部署更多的服务?IP 的分配及管理显然不能人工完成,那样效率太过低下,这就需要一个IP 管理工具。

使用Jenkins进行测试、打包

Jenkins是一个强大的CI工具,虽然本身使用Java开发,但也能用来做其他语言开发的项目CI。下面讲解如何使用Jenkins创建一个构建任务。

登录Jenkins, 点击左侧的新建,创建新的构建任务。

然后输入任务名称,任务名称可以自行设定,但需要全局唯一。输入名称后选择构建一个自由风格的软件项目。并点击下方的确定按钮即创建了一个构建任务。之后会自动跳转到该job的配置页面。

下图是构建任务设置界面,可以看到上方的几个选项“General”, “源码管理”, “构建触发器”,”构建环境”, “构建”, “构建后操作”。下面逐一介绍。

General

General是构建任务的一些基本配置。名称,描述之类的。

描述: 对构建任务的描述。

丢弃旧的构建: 服务器资源是有限的,有时候保存了太多的历史构建,会导致Jenkins速度变慢,并且服务器硬盘资源也会被占满。当然下方的”保持构建天数” 和 保持构建的最大个数是可以自定义的,需要根据实际情况确定一个合理的值。

其他几个选项在这里不做介绍,有兴趣的可以查看Jenkins”帮助信息”, 就是选项最右边的那个蓝色问号,会有一个大概的介绍。不过这些”帮助信息”都是英文的。

源码管理

源码管理就是配置你代码的存放位置。

Git: 支持主流的github 和gitlab代码仓库。因我们的研发团队使用的是gitlab,所以下面我只会对该项进行介绍。

Repository URL:仓库地址

Credentials:凭证。可以使用HTTP方式的用户名密码,也可以是RSA文件。 但要通过后面的”ADD”按钮添加凭证。

Branches to build:构建的分支。*/development表示development分支,也可以设置为其他分支。

源码浏览器:你所使用的代码仓库管理工具,如github, gitlab。选自动就好。

构建触发器

构建触发器,顾名思义,就是构建任务的触发器。

Build whenever a SNAPSHOT dependency is built:只要快照依赖任务被构建,就构建当前任务。就是说,[A]项目依赖[B]项目的一个快照版本的module[M],如果[A]和[M]都有Jenkins任务时,那么,当[M]任务构建时,就会触发[A]任务的构建。

触发远程构建(例如,使用脚本): 该选项会提供一个接口,可以用来在代码层面触发构建。这里不做介绍,后期可能会用到。

Build after other projects are built: 该选项意思是”在其他projects构建后构建”。这里不作介绍,后期可能会用到该选项。

Build periodically: 周期性的构建。很好理解,就是每隔一段时间进行构建。日程表类似 linux crontab书写格式。如下图的设置,表示每隔30分钟进行一次构建。

Poll SCM:该选项是配合上面这个选项使用的。当代码仓库发生改动,jenkins并不知道。需要配置这个选项,周期性的去检查代码仓库是否发生改动。

Build when a change is pushed to GitLab:当有更改push到gitlab代码仓库,即触发构建。后面会有一个触发构建的地址,一般被称为webhooks。需要将这个地址配置到gitlab中,webhooks如何配置后面介绍。这个是常用的构建触发器。

token也可以不配置,如果配置的话要去Gitlab 仓库配置 webhooks,当仓库收到push,不是gitlab收到,是某一个仓库收到 push操作或者merge请求事件 才会触发构建 ,和仓库相关:

  1. 进入 Gitlab 中 monitor 仓库的设置页面
  2. 进入集成配置页面,复制 jenkins 触发器配置页面的 url 及 Token
  3. 触发事件 默认事件类型是push
  4. 配置完成后,添加weohooks
  5. 添加了一条 ,在页面下面测试触发设置 测试用test 测试用push events 推送事件
  6. 如果200显示成功,执行成功了

构建环境

构建环境就是构建之前的一些准备工作,如指定构建工具(比如使用ant)。

可以空着。

Pre Steps

这里用了Sonar作为代码质量管理平台。

mvn sonar:sonar -Dsonar.projectKey=wisefly-framework -Dsonar.host.url=http://sonar.wisefly.cn:9000 -Dsonar.login=a38e7472128442bccf49dfed26929bd946dec225

mvn sonar:sonar -Dsonar.projectKey=area-medical-info-platform -Dsonar.host.url=http://sonar.wisefly.cn:9000 -Dsonar.login=dcb072b700f0d3a2f278e6e225fa75e022dfd87c

执行shell

运行shell脚本(默认为sh,但这是可配置的)来构建项目。脚本将以工作区作为当前目录运行。

cd /opt/apache-tomcat-9.0.37/webapps/jenkins/workspace/framework-jenkins/business-file/business-file-web
mvn -DskipTests docker:build
cd /opt/apache-tomcat-9.0.37/webapps/jenkins/workspace/framework-jenkins/business-gateway
mvn -DskipTests docker:build
cd /opt/apache-tomcat-9.0.37/webapps/jenkins/workspace/framework-jenkins/business-monitor
mvn -DskipTests docker:build
cd /opt/apache-tomcat-9.0.37/webapps/jenkins/workspace/framework-jenkins/business-wcenter/wcenter-web
mvn -DskipTests docker:build
cd /opt/apache-tomcat-9.0.37/webapps/jenkins/workspace/framework-jenkins/business-workflow/business-workflow-web
mvn -DskipTests docker:build

构建后操作

Name: SSH Server的名称。SSH Server可以在jenkins-系统设置中配置。

source files: 需要发送给远程主机的源文件。

Remove prefix: 移除前面的路径。如果不设置这个参数,则远程主机会自动创建构建源 source files 包含的那个路径。

Remote directory: 远程主机目录。

Exec command:在远程主机上执行的命令,或者执行的脚本。

Exec command:

docker run --name wisefly-file -p 18766:18766 -e "SPRING_PROFILES_ACTIVE=test" -e TZ="Asia/Shanghai" -v /home/wisefly/logs/business-file:/logs -idt 10.0.1.104:5000/business-file-web

   转载规则


《Jenkins持续集成工具》 锦泉 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
一致性 一致性
强一致性、弱一致性、最终一致性、读写一致性、单调读、因果一致性 的区别与联系。
2020-12-25
下一篇 
MQTT协议 MQTT协议
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通讯协议,该协议构建于TCP/IP协议上。
2020-12-24
  目录