Jenkins在Java web项目CI/CD中的简单应用

JenkinsJenkins is a self-contained, open source automation server which can be used to automate all sorts of tasks related to building, testing, and delivering or deploying software.主要介绍使用Jenkins来达到持续集成持续交付/持续部署(CICD)的一些方案和选择,不涉及Jenkins的深入研究。实现CI/CD的方式有很多种,本文介绍的只是我这几天一些粗略的摸索,仅供大家参考。一、安装Jenkins的安装方式有很多选择,这里不做详细讨论,我这次采用了比较熟悉的部署WAR包的方式,将其部署到tomcat上来运行。部署完成之后访问相应地址即可,这是会提示新建用户,大家按照指引一步一步完成即可,不做赘述。二、新建任务Jenkins部署完成之后,接下来便要进入正题了,新建一项任务,已达到CICD的目的。首页左侧菜单按选择新建任务-》输入任务名称-》构建一个自由风格的软件项目-》确定(这里我已经创建过一个名为test的项目了)点击确定后进入了该项目的配置页面,先总览所有的配置项,共有六项:General,源码管理,构建触发器,构建环境,构建,构建后操作.从字面意思上不难理解。General,一些通用的信息,本次不做重点;源码管理,构建的来源,git,svn,亦或是其他一些源码管理服务;构建触发器,以何种规则自动触发源码的构建(持续构建),若该项不做任何配置,则只能手动触发;构建环境,本次也未做关键性修改;构建,以何种方式构建,maven, gradle, 亦或是其他;构建后操作,成功构建之后的一些操作,持续交付/持续部署的操作主要放到这一块。接下来分别较少这几项配置,以及用到的插件,已完成CI/CD的目标。1. General本次并没有做一些关键的修改2. 源码管理只说明git的一些相关配置,其他的源码管理服务同理Repository URL: git上的源码地址Credentials: 用户名/密码Branch Specifier:指定需要构建的分支上边这些做完后其实基本上已经可以了,之所以修改Advanced clone behaiours,是防止第一次构建时拉取源码超时,默认超时时间为10minutes,多次构建失败后,我把此处修改为了20minutes,如果依旧超时,可延长此处时间,或检查网络(点击Additional Behaviours旁边的add,选择Advanced clone behaiours)Shallow clone,Shallow clone depth:浅拷贝,节省拷贝时间和磁盘空间3. 构建触发器实现触发构建的方式主要有定时触发、web hook触发,这些触发方式可以单独使用,也可以组合使用。3.1 定时触发Build periodically: 周期性构建Poll SCM: 周期性检测,若源码有变化则构建图中为每六小时检测一次搞清楚jenkins中“Poll SCM”和“Build periodically”的啥意思定时构建部署,可控制频率3.2 Gitlab Hook插件 web hook触发主要介绍gitlab hook插件,接下来我们先保存已经完成的配置,回到首页,下载所需插件。 可选插件中搜索gitlab,勾选列表中的GitLab Plugin和Gitlab Hook Plugin, 选择直接安装。待安装完成后回到首页,点击右边刚刚我们创建的任务,然后点击配置回到我们之前的配置页面。 此时发现构建触发器中多了个选项:Build when a change is pushed to GitLab. GitLab CI Service URL: http://172.16.192.142:9081/jenkins/project/test,如果仍然没有,尝试重启Jenkins之后查看。 图中红框上边为Gitlab Web Hook处需要添加的URL,若Jenkins设置了不允许匿名用户执行构建操作,则需要在Gitlab安全令牌处添加第二个红圈处的Secret token。Gitlab处需要增加的配置(设置-》集成,注意登录账户需要有相应权限)随时提交,随时构建,快速相应开发人员的操作,但需要开发人员提交代码的时候确保提交可用,多次commit一次push,除非紧急需要尽量在午休时间,早上上班前,晚上下班后push代码参考资料:Gitlab利用Webhook实现Push代码后的jenkins自动构建4. 构建环境没有关键配置的修改,其中Color ANSI Console Output为下载的插件AnsiColor,可以使日志输出带有颜色,详情可查看Jenkins 的输出日志也可以变得色色的5. 构建构建部分主要采用了maven构建,确保部署Jenkins的机器已经配置好了maven环境,maven的配置不做赘述。6. 构建后操作使用maven构建打包完成后,与pom.xml同级的target目录下会生成一个war包(取决于pom.xml中的配置,对pom.xml的配置不做描述),接下来我们要做的就是将生成的war包部署到中间件或容器中,下面主要介绍两个插件,可以根据实际情况有选择的使用,使用之前首先需要参考之前介绍的步骤下载相应插件。6.1 Deploy to Container插件达到效果:构建前需保证目标中间件正常启动,每次Jenkins构建时会把指定的war包自动部署到指定的服务器上的context path中,如果目标服务已存在,首先undeploy目标服务,再把新的war包redeloy上去,已完成自动部署的功能。仅支持GlassFish,JBoss,Tomcat增加构建后操作步骤中选择Deploy war/ear to a containerWAR/EAR files中填上所需要部署的程序包,支持**/.war的形式Context path配置程序相对于中间件环境的发布路径本文中Containers我选择了Tomcat 7.x,Credentials需要在tomcat里配置上,Tomcat URL即环境的基础地址在tomcat中添加授权用户:修改conf/tomcat-users.xml<role rolename=“manager-script”/><user username=“caozeal” password="*****" roles=“manager-script”/>只是做上边这些配置的话,你会发现Jenkins的自动部署仅支持第一次,已有旧版应用运行时,自动部署会报undeploy失败,原因是在应用运行时,tomcat会对应用的资源进行锁定,导致无法覆盖更新,这时需修改tomcat的另一项配置:conf/context.xml(详情可查看Tomcat中antiResourceLocking和antiJARLocking的作用)<Context antiJARLocking=“true” antiResourceLocking=“true”>6.2 Publish Over SSH插件通过SSH操作目标服务,从而传输文件,执行命令已达到目的更灵活,支持各种中间件服务器首先在系统设置中配置上所需连接的远程服务器,配置上相关配置,其中Remote Directory是访问服务器的基础路径,之后步骤能用到然后回到任务配置继续配置构建后操作一块Remote directory 远程服务器文件夹,空即为默认的上边步骤配置的路径,如果此处不为空,即为相对路径Remove prefix 去除前置路径Exec command 执行脚本,此处的脚本比较简单,调用目标中间件的停止与启动需要注意的是执行脚本的时候有个坑,读取不到系统的环境变量,原因是此处执行脚本的方式为non-interactive + non-login shell,不会读取/etc/profile中的配置,此处的解决方案是采用bash执行命令,由于bash恒执行BASH_ENV中的变量,因此需要把/etc/profie赋值到BASH_ENV中,详细解决思路参考链接ssh连接远程主机执行脚本的环境变量问题转:深入了解bash与sh的区别三、其他至此已经完成了从开发人员push代码到应用构建、部署等相关操作的基本自动流程,具体细节部分还需要继续深入研究探索遗留问题:Jenkins构建的时候控制台乱码参考Jenkins控制台中文输出乱码解决方法处理解决之后,Jenkins启动的tomcat发生乱码自动构建部署的时候,Jenkins调用命令启动StartTAS.sh的时候会一直监听启动日志,直到超时才断开链接,这时候因超时而导致本次构建为黄灯,即不稳定的构建 ...

March 12, 2019 · 1 min · jiezi

基于 CODING 的 Spring Boot 持续集成项目

本文作者:CODING 用户 - 廖石荣持续集成的概念持续集成(Continuous integration,简称 CI)是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。持续集成的模式如图所示:CI 过程:代码编写 -> 源代码库(GitHub or gitlab)-> CI 服务器(代码构建、自动化测试、结果反馈【构建结果】)涉及 CI 工具:Jenkins、Travis CI、TeamCity、Gitlab CI、CircleCI、Codeship 等,相关资料可以查询对应的官网,其中应用广泛的 Jenkins 和 Travis CI,市场上也推出了智能化的持续集成服务商,比如「CODING 持续集成」,它是基于 Jenkins 配置集成服务,真正实现了一键提交代码,持续集成,部署服务。持续集成的优点1.解放了重复性劳动。自动化部署工作可以解放集成、测试、部署等重复性劳动,而机器集成的频率明显比手工高很多。2.更快地修复问题。持续集成更早的获取变更,更早的进入测试,更早的发现问题,解决问题的成本显著下降。3.更快的交付成果。更早发现错误减少解决错误所需的工作量。集成服务器在构建环节发现错误可以及时通知开发人员修复。集成服务器在部署环节发现错误可以回退到上一版本,服务器始终有一个可用的版本。4.减少手工的错误。在重复性动作上,人容易犯错,而机器犯错的几率几乎为零。5.减少了等待时间。缩短了从开发、集成、测试、部署各个环节的时间,从而也就缩短了中间可以出现的等待时机。持续集成,意味着开发、集成、测试、部署也得以持续。6.更高的产品质量。集成服务器往往提供代码质量检测等功能,对不规范或有错误的地方会进行标致,也可以设置邮件和短信等进行警告。持续集成服务的选择关于网上集成服务的工具很多,其中尤其以 Jenkins 服务最受欢迎,但是 Jenkins 服务需要在自己服务器上进行配置安装,以及安装各种插件,对于刚上手的小白来说,可能存在一定的门槛,操作步骤繁多,操作不够智能,不是真正的自动化运维,缺少一键发布构建服务。所以我们选择了「CODING 持续集成」。CODING 提供的集成服务是什么「CODING 持续集成」是基于 Jenkins 的,兼容 Jenkinsfile 配置文件,如果您之前有使用过或者写过 Jenkinsfile 相信您会很快上手。如何使用CODING持续集成服务「CODING 持续集成」是基于 Jenkins 的,通过 Jenkinsfile 配置文件完成 CI 的步骤,接下来将引导您一步步创建一个持续集成示例。登录 CODING,进入项目中心,点击左边菜单集成服务,开通集成服务,配置完成之后会手动触发第一次构建过程。找到或者创建 Jenkinsfile,如果你对于 Jenkins 比较熟悉的话,可以自己编写 Jenkinsfile 配置文件,也可以采用 CODING 提供的模板文件,如下我就采用了 Jenkinsfile 模板文件来实行自动化持续集成服务,您可以在修改 Jenkinsfile 的时候修改触发方式,您可以自行选择是推送到某个标签或者某个分支时间触发构建。Jenkins 以及能够为 agent 默认配置好 timezone 和 localtime (默认中国上海)。配置好 Jenkinsfile 文件以及配置好环境变量,点击保存,便可以进行持续集成项目了。如图所示,集成步骤分为拉取代码-》构建-》测试-》部署等步骤,点击每个步骤可以看到相应的命令执行情况,下面来一个一个步骤配合 Jenkinsfile 文件解释命令的一些执行情况:代码工程结构如图所示:1.检出项目,如下所示 Jenkinsfile 配置文件第一步通过 Git 检出在远程仓库分支的代码,至于哪个分支可以通过环境变量配置读取 REF 这个环境变量stage(“检出”) { steps { sh ‘ci-init’ checkout( [$class: ‘GitSCM’, branches: [[name: env.GIT_BUILD_REF]], userRemoteConfigs: [[url: env.GIT_REPO_URL]]] ) } }如上图所示,第一步主要是执行从 Git 仓库远程拉取代码,所以命令都是 Git 里面的,包括读取 Git 配置的环境变量包括更新 Jenkinsfile 文件2.构建项目,如下命令所示构建这一步主要是初始化代码和打包代码,因为我们这个工程是以 Java 为主要开发语言,所以重点关注 Java 版本和安装 Maven 命令即可打包,目前 CODING 提供的语言环境包括了 java-1.8.0_181, go-1.7.4, node-10.11.0, php-7.0.30, ruby-2.3, python-2.7.13 等。如有需要可以联系客服开通其它语言环境。stage(“构建”) { steps { echo “构建中…” sh ‘go version’ sh ’node -v’ sh ‘java -version’ // sh ‘php -v’ // sh ‘python -V’ // sh ‘gcc -v’ // sh ‘make -v’ // 请在这里放置您项目代码的单元测试调用过程,例如: sh ‘mvn clean’ // mvn 清除缓存 sh ‘mvn install’ // 构建 Maven 工程 // sh ‘make’ // make 示例 echo “构建完成.” // archiveArtifacts artifacts: ‘**/target/.jar’, fingerprint: true // 收集构建产物 } }因为这个 SpringBoot 项目是以 Java 为主的项目,所以在 Jenkinsfile 文件命令里面其实可以把其它语言的检查版本命令去掉,只需要执行 java -version 命令即可。第一次构建失败:如上图所示,第一次执行执行构建 jar 包失败,因为在本地可以正常 mvn install,所以起初我百思不得其解,上网找了很多资料,经过多番查找,最后在 Stack Overflow 找到了答案,这是由于 OpenJDK 1.8.0_181 这个版本中存在的一个 bug 所致,原文如下:链接,最终解决方案采用更改 pom.xml 文件:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <useSystemClassLoader>false</useSystemClassLoader> <skipTests>true</skipTests> </configuration></plugin>成功构建结果如下:3.测试项目,如下所示,我们 SpringBoot 工程通过 mvn test 测试命令即可,比如下面我们测试其中一个用户信息相关的单元测试:stage(“测试”) { steps { echo “单元测试中…” // 请在这里放置您项目代码的单元测试调用过程,例如: sh ‘mvn test -Dtest=com.my.segmentfault.website.Pwdtest’ //测试其中一个单元测试 echo “单元测试完成.” } }第一次失败测试结果如下:后来经检查,是单元测试代码其中存在 bug,修正之后,正确的第二次测试结果如下:4.部署项目,如下所示,部署项目命令可以执行自己写的部署脚本文件。各位可以结合自己项目的真实环境,编写简单的部署脚本,比如上传 jar 包到服务器,然后通过 java - jar XXXX.jar 包执行方式,以及上传 war 包到 tomcat 服务器,然后启动 tomcat 服务器等,也可以结合自己公司项目需要编写复杂的执行脚本文件,然后调用执行脚本命令,比如下面举一个简单的执行脚本例子。部署命令:stage(“部署”) { steps { echo “部署中…” sh ‘./deploy.sh start’ // 启动 tomcat 服务 // sh ‘./deploy.sh stop’ // 停止 tomcat 服务 echo “部署完成” } }deploy.sh 脚本:(其中一些 tomcat 服务路径配置根据自己需要进行修改)#!/bin/bash tomcat_home=/usr/tomcat/apache-tomcat-8.0.48 //修改为自己服务器的 tomcat 路径SHUTDOWN=$tomcat_home/bin/shutdown.sh STARTTOMCAT=$tomcat_home/bin/startup.sh case $1 instart) echo “启动$tomcat_home”$STARTTOMCAT ;; stop) echo “关闭$tomcat_home”$SHUTDOWN pidlist=ps -ef |grep tomcat |grep -v "grep"|awk '{print $2}' kill -9 $pidlist #!/bin/bash tomcat_home=/usr/tomcat/apache-tomcat-8.0.48 SHUTDOWN=$tomcat_home/bin/shutdown.sh STARTTOMCAT=$tomcat_home/bin/startup.sh case $1 instart) echo “启动$tomcat_home”$STARTTOMCAT ;; stop) echo “关闭$tomcat_home”$SHUTDOWN pidlist=ps -ef |grep tomcat |grep -v "grep"|awk '{print $2}' kill -9 $pidlist stop) echo “关闭$tomcat_home”$SHUTDOWN pidlist=ps -ef |grep tomcat |grep -v "grep"|awk '{print $2}' kill -9 $pidlist #删除日志文件,如果你不先删除可以不要下面一行 rm $tomcat_home/logs/ -rf #删除tomcat的临时目录 rm $tomcat_home/work/* -rf ;; restart) echo “关闭$tomcat_home”$SHUTDOWN pidlist=ps -ef |grep tomcat |grep -v "grep"|awk '{print $2}' kill -9 $pidlist #删除日志文件,如果你不先删除可以不要下面一行 rm $tomcat_home/logs/* -rf #删除tomcat的临时目录 rm $tomcat_home/work/* -rf sleep 5 echo “启动$tomcat_home”$STARTTOMCAT #看启动日志 #tail -f $tomcat_home/logs/catalina.out ;; logs) cd /mnt/alidata/apache-tomcat-7.0.68/logstail -f catalina.out ;; esac 服务启动展示系统主页如下图所示:文章详情如下图所示:归档页面如下图所示:系统后台管理如图所示:总结CODING 是一个面向开发者的云端开发平台,提供 Git/SVN 代码托管、任务管理、在线 WebIDE、Cloud Studio、开发协作、文件管理、Wiki 管理、提供个人服务及企业服务,其中实现了 DevOps 流程全自动化,为企业提供软件研发全流程管理工具,打通了从团队构建、产品策划、开发测试到部署上线的全过程。「CODING 持续集成」集成了 Jenkins 等主流企业开发流程工具,如上所示,这个以 SpringBoot 打造的 CMS 社区系统便可以在 CODING 上面实现团队协作开发,一键部署作为团队以及公司文档共享社区论坛等作用。本文适量引用:“持续集成”词条的百度百科 ...

February 20, 2019 · 2 min · jiezi

持续集成 Jenkins 简介

持续集成的定义大师 Martin Fowler 是这样定义持续集成的: 持续集成是一种软件开发实战, 即团队开发成员经常集成他们的工作. 通常, 每个成员每天至少集成一次, 也就意味着每天可能发生多次集成.持续集成并不能消除Bug, 而是让它们非常容易发现和改正.根据对项目实战的理解, 持续集成中的 “持续” 是指不间断的; “集成” 可分为广义和狭义, 广义的集成指软件各个过程的集成, 包括开发、部署、测试等. 狭义的集成即代码和代码之间的集成, 从而保证代码合并不冲突.每次集成都通过自动化的构建 (包括编译、发布和自动化测试) 来验证, 从而尽快的发现集成错误. 许多团队都发现这个过程可以大大减少代码集成的问题, 让团队更快的开发内聚的软件. 请注意, 持续集成不等于持续编译.当前软件开发过程存在的问题在没有应用持续集成之前,传统的开发模式是这样的:项目一开始是先划分好模块,分配模块给相应的开发人员;开发人员开发好一个模块就进行单元测试;等所有的模块都开发完成之后,由项目经理对所有代码进行集成;集成后的项目由项目经理部署到测试服务器上,被交由测试人员进行集成测试;测试过程中出现 Bug 就提把问题记录进行 Bug 列表中;项目经理分配 Bug 给相应的责任人进行修改;修改完成后,项目经理再次对项目进行集成,并部署到测试服务器上;测试人员在下一次的集成测试中进行回归测试;通过通过之后就部署到生产环境中;如果测试不通过,则重复上述“分配 Bug -> 修改 Bug -> 集成代码 -> 部署到测试服务器上 -> 集成测试”工作。这个过程中可能会出现如下问题:Bug 总是在最后才发现随着软件技术的发展, 软件规模也在扩大, 软件需求越来越复杂, 软件已经不能简单地通过划分模块的方式来开发, 往往需要在项目内部互相合作, 模块之间存在一定的依赖关系, 那么早期就存在的 Bug 往往会在最后集成的时候才被发现.越到项目后期, 问题越难解决很多开发者需要在集成阶段花费大量的时间来寻找 Bug 的根源, 加上软件的复杂性, 问题的根源很难定位. 而且我们都清楚, 间隔的时间越久, Bug 修复的成本越高, 因为连开发人员自己都忘了当初写得是什么鬼代码, 从而不得不从头阅读代码、理解代码.软件交付时机无法保障正是因为我们无法及时修复 Bug, 或者是没能在早期就修复 Bug, 从而令整个修复 Bug 的周期拉长了. 不管怎么样, 我们不可能把明知存在 Bug 的软件交付给客户.而且, 大量没有在前期预估到的工作量产生了——开发人员不得不花费大把时间在查找 Bug 上; 测试人员不断的需要进行回归测试; 项目经理不得不疲命于该死的代码的集成、部署这些重复性工作——最终导致整个项目的周期拉长, 交付时间点往后拖.程序经常需要变更某些项目, 程序会经常需要变更. 由于产品经理在与客户交流过程中, 往往实际的软件就是最好的原型, 所以软件会被当作原型作为跟客户交流的工具. 当然, 客户最希望的当然是客户的想法能够马上反映到原型上, 这会导致程序会经常被修改的. 那么也就意味着“分配 Bug -> 修改 Bug -> 集成代码 -> 部署到测试服务器上 -> 集成测试”工作无形又爆增了.无效的等待变多有可能开发在等集成其他人的模块; 测试人员在等待开发人员修复 Bug; 产品经理在等待新版本上线好给客户做演示; 项目经理在等待其他人提交代码. 不管怎么样, 等待意味低效.用户的满足度低这里的用户是广义的, 可以指最终的客户, 也可以是产品经理、公司领导、测试人员, 甚至可能是开发人员自己. 你想想看, 本来三个月做完的项目被拉长到了九个月甚至一年, 用户能满意吗! 产品经理、公司领导经常需要拿项目作为演示的原型, 结果告诉我在演示前一刻发现还有很多 Bug 没有解决, 项目启动不了无法访问, 这叫人情何以堪.怎么样才算是“持续”对于一天需要集成多少次数, 并没有一个明确的定义. 一般就是按照自己项目的实际需要来设置一定的频率, 少则可能几次, 多则可能达几十次. 可以设置按照代码的变更来触发集成, 或者设置一个固定时间周期来集成, 也可以手工点击集成的按钮来 “一键集成”.持续集成的工作流程当开始更改代码时,开发人员会从代码库(如 SVN、Git 等)获取当前代码库的副本.当其他开发人员将更改的代码提交到代码库时, 此副本将逐渐停止反映代码库中的代码. 代码分支保持检出的时间越长, 当开发人员分支重新集成到主线时, 多个集成冲突和故障的风险就越大.当开发人员向代码库提交代码时, 他们必须首先更新他们的代码, 以反映代码库中的最新更改.当存储库与开发人员的副本不同, 他们必须要花时间来先处理冲突.持续集成的好处解放了重复性劳动自动化部署工作可以解放了集成、测试、部署等重复性劳动, 而且机器集成的频率明显可以比手工的高很多.更快地修复问题由于持续集成更早的获取变更, 更早的进入测试, 也就能更早的发现问题, 解决问题的成本显著下降.更快地交付成果及早集成、及早测试减少了缺陷遗留到部署环节的机会. 在某些情况下, 更早地查找错误还会减少解决错误所需的工作量.如果集成服务器对代码进行构建过程中发现错误, 可以及时发送邮件或者短信提供给开发人员进行修复.如果集成服务器在部署环节发现当前版本有问题不可用, 集成服务器会将部署回退到上一个版本. 这样服务器上始终都会有一个可用的版本.减少手工的错误人与机器的一个最大的区别是, 在重复性动作上, 人容易犯错, 而机器犯错的几率几乎为零. 所以, 当我们搭建完成集成服务器后, 以后的事就交给集成服务器来打理吧.减少了等待时间持续集成缩短了从开发、集成、测试、部署各个环节的时间, 从而也就缩短了中间可以出现的等待时间. 持续集成, 意味着开发、集成、测试、部署也得以持续.更高的产品质量集成服务器往往提供 Code review、代码质量检测等功能. 对代码不规范或者有错误的地方会进行标识, 也可以设置邮件、短信等进行告警. 而开发人员通过 Code review 也可以持续提高编程的能力. ...

January 4, 2019 · 1 min · jiezi