1. CI的重要性
随着devops的快速发展,很多公司都已经将devops实践到日常运维工作中,devops从以前最简单的写个shell脚本部署数据库、部署应用服务器到现在的从代码提交、项目构建、自动化测试等都有机结合了起来,这样的自动化大大减少了运维人员的工作压力,也减少了运维人员在工作中的人工失误导致的投产事故。
原来在中国银行是从13年开始实践CI的,其中用的CI框架就是Jenkins,当时是在笔者所在的开放平台团队试点,经过了半年的试点就感受到了CI带来的魅力,主要感受体现在以下几点:
1)部署速度更快了:当时我们使用的服务框架是dubbo,所有的服务都注册在了zk上,大大小小服务加起来也有几十个,再加上每个服务多机互备,导致每次部署版本需要花费很长时间,因为当时没有上生产运维自动化部署,所以快速部署的优势只能体现在我们开发环境上,上了CI之后部署就是真的一键部署,非常方便,完全不用担心部署错了。这里说明下后来我呆过的一家电商生产环境也通过CI部署,将近100个系统,运维部署人员只有3个,而且每次投产都是喝着咖啡投产很惬意,有时甚至直接在家部署版本。
2)代码质量提升了:上了CI后因为大家提交的代码都要通过checkstyle、findbugs进行代码静态复查,谁都不愿意在CI Sonar报表里看到自己的代码一堆警告吧,为了面子也要尽自己最大怒力把代码写规范了,代码按照要求写规范了,低级问题不再发生,代码质量自然提升上去了。
3)回归测试更快了:CI之后,通过增加单元测试和集成功能测试能够在每次提交代码触发自动化回归测试,让每次提交的代码都通过了单元测试和自动化集成测试,再次保证了提交的代码都是经过回归测试的。
好了说了那么多CI的优点,现在回归正题,这篇文章主要是讲下通过Jenkins如何把我们常用的Springboot项目运行起来,这个流程不单单适用于Springboot项目,同样适用于其他的项目,只是在build和部署的时候会有一些差异,这里我们在CI过程中构建用的是maven、源码仓库用的是Git,对于用Ant、Gradle构建的朋友需要装下相关的插件。
2. Jenkins的安装
war包直接运行,部署到tomcat等应用服务器中,安装包直接安装
安装完成后需要更新plugin插件
3. 创建Maven自动化部署任务
安装完成之后就可以开始创建CI任务了,这次我们创建的CI任务主要是完成从Git上拉取最新的源码、对源码进行编译、将编译后的jar 、war部署到服务器,下面就开始详细介绍下整个过程细节。
1)创建一个构建Maven项目

点击jenkins左侧的新建按钮之后会展示新建页面,这里会展示一些模版,因为笔者使用的是Maven构建的项目,所以这里选择了第二个Maven构建模版,这个模版会自动帮你创建一些maven项目常用的步骤,如果在列出来的模版中没有你需要的构建模版,可以使用第一个选项,构建一个自由风格的软件项目,这个选项的模版中所有的作业步骤都可以自己进行定制,很方便。
2)配置Git下载源码

先在Repository URL输入需要构建的项目的git地址,这里的地址可以是github这类公有的git仓库也可以是公司私有的git仓库,配置好了项目源码地址,还需要点击Add按钮配置Credential,可以采用username+password方式或者usrname+private key,类似于我们在自己的客户端更新git代码,同时别忘了配置branch,git默认是master分支,这里也可以做成参数化,后面会简单介绍下如何在jenkins里参数化一些东西,让整个构建更加灵活。
如果整个项目中涉及到多个repo,那就需要点击图片右下角的Add Repository按钮进行创建其他的repo地址和credential。
这里单独说下上面提到的需要配置Credential,Credential的配置需要在首页点击左侧的Credentials按钮

这是配置好不同repo的页面,其中图标是小钥匙的是通过配置私钥方式创建的Credential,图标是用户头像下面有些密码的图标是通过用户名密码创建的Credential。因为很多git私服是没有配置用户名密码pull代码的,所以只能配置通过机器私钥pull代码,在配置用户名密码过程中一直失败的朋友,一定要看下是不是git服务器只支持通过私钥获取代码。
2)配置JDK、Maven版本;
下面就是配置JDK和Maven了,大家需要在Jenkins服务器上安装JDK和maven,具体的如何安装JDK和Maven应该不用再介绍了吧。
在Jenkins机器都装好JDK和Maven后,还需要在Jenkins里配置下JAVA_HOME和MAVEN_HOME的环境变量,这样Jenkins构建的时候才能找到你项目需要的JDK版本和Maven版本,这里JDK是可以配置多个的,毕竟所有项目不可能使用一样的版本编译。
这些都是在系统管理中进行配置,具体如何配置就不讲了,太简单了,看图就知道了,就是配个JDK和MAVEN在服务器的路径,很简单。

3)build工程

4)配置ssh
大家回想下我们一般编译好项目后会怎么去部署sprigboot的版本?当然是把编译后的jar或war包发送到待部署服务器。可以通过配置ssh,jenkins就可以自己登陆到远程服务器然后执行后续的部署命令了。
配置ssh也比较简单,在首页找到左侧的系统设置,点进去后一直往下拉找到“Publish over SSH”,然后配置远程服务器的HostName/IP地址、username和密码。配置好以后可以点击右下角的“Test Configuration”验证ssh配置是否有效。

5)远程部署
配置好ssh后我们再回到刚才建的Maven任务的配置页面,找到Post Steps模块点击Add post-build step后从列表中选择Send files or execute commands over SSH,这时候需要在弹出菜单中选择一个配置的SSH服务器并选择编译好的jar或war文件,最后就是在SSH登陆的服务器上执行的shell命令了。

在“Name”中选择刚才配置的ssh配置;在“Source files”中输入项目编译后jar、war保存的相对路径地址和文件名,注意这里的相对路径是相对于项目的根目录来的,maven项目一般都在target下;接下来“Remove prefix”就是用来配置去掉上一步配置的待部署文件的路径地址的,这样jenkins就能够知道具体的要传输的文件名了;“Remote directory”就是配置需要传输的目标地址的相对路径,这个相对路径是相对于在ssh中配置的用户的根目录来的;最后需要配置的就是“Exec command”就是在文件传输后需要执行的shell命令,这里可以将要远程执行的命令直接维护在这里,也可以将部署和运行springboot项目的命令写在shell里,我还是比较习惯于将这些启动信息维护在服务端的shell。下面就给下这个shell的源码,大家要用的话改成自己的路径和文件名就可以了,代码很简单就是先配置好jdk环境变量,备份之前的执行码,然后通过ps找到正在运行的执行码进程编号,然后通过kill命令杀掉这个进程,再启动新编译的jar、war。
DATE=$(date +%Y%m%d)
export JAVA_HOME PATH CLASSPATH
JAVA_HOME=/usr/lib/jvm/jdk-8u144-linux-x64/jdk1.8.0_144(改成自己的JDK路径)
PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH
DIR=/root/xxxxx(需要修改为你项目待拷贝和运行的目录)
JARFILE=xxxxx-0.1.jar
if [ ! -d $DIR/backup ];then
mkdir -p $DIR/backup(改成自己需要将原执行码备份的路径)
fi
cd $DIR
ps -ef | grep $JARFILE | grep -v grep | awk '{print $2}' | xargs kill -9
mv $JARFILE backup/$JARFILE$DATE
mv -f /root/Jenkins-in/$JARFILE .
java -jar $JARFILE > out.log &
if [ $? = 0 ];then
sleep 30
tail -n 50 out.log
fi
cd backup/
ls -lt|awk 'NR>5{print $NF}'|xargs rm -rf
都配置好后保存就可以了,后续还可以通过pre、post step增加很多其他步骤,例如静态代码复查、单元测试、集成测试、邮件通知等等,这里就不详细介绍了,大家可以根据自己项目需要自己摸索,不是很难。
4. 运行CI任务
运行CI任务就很简单了,直接在首页面板找到你刚才配置的任务,点击左侧的立即执行就可以了,通过Console Output可以查看任务运行的日志,如果运行报错也会在这里有所体现错误日志。

5.其他常用配置
这里再介绍几个常用到的配置,会对日常的CI工作很有帮助。
参数化构建
我们在日常开发过程中一般都会有多套环境,开发、sit、uat、生产等等,那么我们是否要配置多个CI任务呢?答案当然是不需要,如果配置那么多环境,那么多项目乘上那么多环境,那是要有多少CI任务啊,Jenkins很贴心的提供了参数化构建功能,只要在任务配置中点选参数化构建,就可以通过添加参数来完成不同环境的部署。
实现参数化部署的前提当然也是我们开发的项目配置文件已经分环境配置了,不是那种低端的都写在一个配置文件里,通过注释手工切环境那种。springboot的项目我们可以通过配置不同的profile来切换使用不同的环境参数,这里只需要配置不同环境的ssh和java启动命令中的profile就可以了,将这些都参数化,在运行的时候选择不同环境进行构建就行了。

超时配置
在日常构建过程中功能,单机版的Jenkins构建任务都是串行的,所以如果一个任务卡住了那么会影响到后续任务的正常构建所以一般我们需要配置下任务的超时时间和超时后的动作,这样就能保证后续任务在一定时间内被执行到。
当然你也可以配置Jenkins主从版,这样各个团队可以在自己的从服务器构建,最后将结果汇总到主服务器,这样各个团队都不会互相影响。

丢弃构建
之前项目组就遇到过CI这台服务器很快磁盘空间就满了,后来看了下原来是因为很多项目没有设置丢弃策略,这里建议大家还是配置下比较好,jenkins默认是不丢弃,那么日记月累还是会有很多构建后的文件的。

后话
自动化部署只是持续集成中的关键一步,通过自动化构建和部署已经能够很大程度上的缩减我们的代码构建和版本部署的人力了,整个持续集成还涉及到很多内容,文章开篇也提到了还涉及到单元测试、自动化功能测试等,单元测试也是整个工程活动中非常重要的一步,后面我也会好好介绍下单元测试,这个让程序猿又爱又恨的东西,单元测试用好了以后也会对整个代码质量有质的提高,敬请期待。
网友评论