一 Jenkins介绍
1.1 软件开发周期
软件开发生命周期叫做ASLC(Software Development Life Sycle),集成了计划,开发,测试和部署过程集合。
1.1.1 需求分析
这是生命周期的第一阶段,根据项目需求,团队执行一个可行性计划的分析。项目需求可能是公司内部或者客户提出的。这阶段主要是对信息的收集,也有可能是对现有项目的改善和重新做一个新的项目。还要分析项目的预算多长,可以从哪方面受益及布局,这也是项目创建的目标。
1.1.2 设计
第二阶段就是设计阶段,系统架构和满意状态(就是要做成什么样子,有什么功能),和创建一个项目计划。计划可以使用图表,布局设计或者文档的方式呈现。
1.1.3 实现
第三阶段就是实现阶段
1.1.4 测试
测试人员进行代码测试 ,包括功能测试、代码测试、压力测试等。
1.1.5 进化
最后进阶段就是对产品不断的进化改进和维护阶段,根据用户使用情况,可能需要对某功能进行修改和bug修复
1.2 瀑布模型
瀑布模型是最著名和最常使用的软件开发模型。瀑布模型就是一系列的软件开发过程。它是由制造业繁衍出来的。一个高度化的结构流程在一个方向上流动,有点像生产线一样。在瀑布模型创建之初,没有其它开发的模型,有很多东西全靠开发人员去猜测,去开发。这样的模型仅适用于那些简单的软件开发, 但是已经不适合现在的开发了。
- 缺点:各个阶段的划分完全固定,阶段之间产生大量的文档,极大地
增加了工作量。 - 由于开发模型是线性的,用户只有等到整个过程的末期才能见
到开发成果,从而增加了开发风险。 - 瀑布模型的突出缺点是不适应用户需求的变化。
1.3 敏捷开发
敏捷开发(Agile Development) 的核心是迭代开发(Iterative Development) 与 增量开发(Incremental Development) 。
1.3.1 何为迭代开发?
对于大型软件项目,传统的开发方式是采用一个大周期(比如一年)进行开发,整个过程就是一次"大开发";迭代开发的方式则不一样,它将开发过程拆分成多个小周期,即一次"大开发"变成多次"小开发",每次小开发都是同样的流程,所以看上去就好像重复在做同样的步骤。
举例来说,spacex公司想造一个大推力火箭,将人类送到火星。但是,它不是一开始就造大火箭,而是先造一个最简陋的小火箭 version1。结果,第一次发射就爆炸了,直到第四次发射,才成功进入轨道。然后,开发了中型火箭 version9,九年中发射了70次。最后,才开发重型火箭。如果spacex不采用迭代开发,它可能直到现在还无法上天。
1.3.2 何为增量开发?
软件的每个版本,都会新增一个用户可以感知的完整功能。也就是说,按照新增功能来划分迭代。
举例来说,房产公司开发一个10栋楼的小区。如果采用增量开发的模式,该公司第一个迭代就是交付一号楼,第二个迭代交付二号楼… 每个迭代都是完成一栋完整的楼。而不是第一个迭代挖好10栋楼的地基,第二个迭代建好每栋楼的骨架,第三个迭代架设屋顶…
敏捷开发如何迭代?
虽然敏捷开发将软件开发分成多个迭代,但是也要求,每次迭代都是一个完整的软件开发周期,必须按照软件工程的方法论,进行正规的流程管理。
敏捷开发有什么好处?
早期交付
敏捷开发的第一个好处,就是早期交付,从而大大降低成本。 还是以上一节的房产公司为例,如果按照传统的"瀑布开发模式",先挖10栋楼的地基、再盖骨架、然后架设屋顶,每个阶段都等到前一个阶段完成后开始,可能需要两年才能一次性交付10栋楼。也就是说,如果不考虑预售,该项目必须等到两年后才能回款。 敏捷开发是六个月后交付一号楼,后面每两个月交付一栋楼。因此,半年就能回款10%,后面每个月都会有现金流,资金压力就大大减轻了。
降低风险
敏捷开发的第二个好处是,及时了解市场需求,降低产品不适用的风险。 想一想,哪一种情况损失比较小:10栋楼都造好以后,才发现卖不出去,还是造好第一栋楼,就发现卖不出去,从而改进或停建后面9栋楼?
1.4 什么是持续集成
持续集成( Continuous integration , 简称 CI )指的是,频繁地(一天多次)将代码集成到主干。持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。通过持续集成, 团队可以快速的从一个功能到另一个功能,简而言之,敏捷软件开发很大一部分都要归功于持续集成。
持续集成的流程
根据持续集成的设计,代码从提交到生产,整个过程有以下几步。
-
提交
流程的第一步,是开发者向代码仓库提交代码。所有后面的步骤都始于本地代码的一次提交(commit)。 -
测试(第一轮)
代码仓库对commit操作配置了钩子(hook),只要提交代码或者合并进主干,就会跑自动化测试。
测试的种类:
单元测试:针对函数或模块的测试
集成测试:针对整体产品的某个功能的测试,又称功能测试
端对端测试:从用户界面直达数据库的全链路测试
第一轮至少要跑单元测试。 -
构建
通过第一轮测试,代码就可以合并进主干,就算可以交付了。
交付后,就先进行构建(build),再进入第二轮测试。所谓构建,指的是将源码转换为可以运行的实际代码,比如code—>jar,或者是服务器环节的准备等等。
常用的构建工具如下:
Jenkins
Travis
Codeship
Strider -
测试(第二轮)
第二轮是全面测试,单元测试和集成测试都会跑,也要做端对端测试。所有测试以自动化为主,少数无法自动化的测试用例,就要人工跑。
需要强调的是,新版本的每一个更新点都必须测试到。如果测试的覆盖率不高,进入后面的部署阶段后,很可能会出现严重的问题。 -
部署
过了第二轮测试,当前代码就是一个可以直接部署的版本(artifact)。将这个版本的所有文件打包(tar filename.tar *
)存档,发到生产服务器。 -
回滚
一旦当前版本发生问题,就要回滚到上一个版本的构建结果。最简单的做法就是修改一下符号链接,指向上一个版本的目录。
持续集成的组成要素
- 一个自动构建过程, 从检出代码、 编译构建、 运行测试、 结果记录、 测试统计等都是自动完成的, 无需人工干预。
- 一个代码存储库,即需要版本控制软件来保障代码的可维护性,同时作为构建过程的素材库,一般使用SVN或Git。
- 一个持续集成服务器, Jenkins 就是一个配置简单和使用方便的持续集成服务器。
持续集成的好处
- 降低风险,由于持续集成不断去构建,编译和测试,可以很早期发现问题,所以修复的代价就少;
- 对系统健康持续检查,减少发布风险带来的问题;
- 减少重复性工作;
- 持续部署,提供可部署单元包;
- 持续交付可供使用的版本;
- 增强团队信心;
1.5 Jenkins是什么
Jenkins 是一款流行的开源持续集成(Continuous Integration)工具,广泛用于项目开发,具有自动化构建、测试和部署等功能。官网: http://jenkins-ci.org/
Jenkins的特征:
开源的Java语言开发持续集成工具,支持持续集成,持续部署。
易于安装部署配置:可通过yum安装,或下载war包以及通过docker容器等快速实现安装部署,可方便web界面配置管理。
消息通知及测试报告:集成RSS/E-mail通过RSS发布构建结果或当构建完成时通过e-mail通知,生成JUnit/TestNG测试报告。
分布式构建:支持Jenkins能够让多台计算机一起构建/测试。
文件识别:Jenkins能够跟踪哪次构建生成哪些jar,哪次构建使用哪个版本的jar等。
丰富的插件支持:支持扩展插件,你可以开发适合自己团队使用的工具,如git,svn,maven,docker等。
二 Jenkins环境准备
2.1 Jenkins安装和持续集成环境配置
- 首先,开发人员每天进行代码提交,提交到Git仓库
- 然后,Jenkins作为持续集成工具,使用Git工具到Git仓库拉取代码到集成服务器,再配合JDK,Maven等软件完成代码编译,代码测试与审查,测试,打包等工作,在这个过程中每一步出错,都重新再执行一次整个流程。
- 最后,Jenkins把生成的jar或war包分发到测试服务器或者生产服务器,测试人员或用户就可以访问应用。
服务器列表
本博客虚拟机统一采用CentOS7
Gitlab安装步骤,参考:https://blog.csdn.net/qq_33417321/article/details/130365133
2.2 Jenkins服务器需要的环境
切换到192.168.0.109机器
- jdk:Jenkins使用java开发,首先必然需要安装jdk。
- tomcat:Jenkins是一个web应用程序,运行当然需要中间件;
Jenkins的war包中包含了一个叫winstone的应用服务器,所以可以直接运行,但在生产环境建议安装tomcat等独立中间件。下载解压即可。 - maven:Jenkins使用maven构建,所以也需要安装maven。下载解压即可。
2.3 JDK环境
这里是将环境变量配置在etc/profile,即为所有用户配置JDK环境。
sudo vi /etc/profile
#set java env
export JAVA_HOME= /usr/local/tools/jdk1.8.0_181
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
执行命令使之生效:source /etc/profile
javac测试好用即可
2.4 Maven环境
运行wget https://archive.apache.org/dist/maven/maven-3/3.6.1/binaries/apache-maven-3.6.1-bin.tar.gz
,下载maven安装文件
运行tar zvxf apache-maven-3.6.1-bin.tar.gz
,解压
编辑文件apache-maven-3.6.1/conf/settings.xml
,可以指定本地仓库或者私服(默认)
开始配置环境变量,编辑文件/etc/profile
在最下面添加以下内容(MAVEN_HOME是刚才解压maven的路径)
export MAVEN_HOME=/usr/local/tools/apache-maven-3.6.1
export PATH=$MAVEN_HOME/bin:$PATH
source /etc/profile
2.5 Git环境
2.5.1 yum方式安装
1、在Linux上是有yum安装Git,非常简单,只需要一行命令
yum -y install git
输入 git --version查看Git是否安装完成以及查看其版本号
顺便说一下,yum安装git被安装在/usr/libexec/git-core目录下
至此,yum安装git完成。
注意:yum安装的版本不能控制。默认的1.8.3,我们想自己指定版本就要通过源码下载安装。
2.5.2 自定义版本安装
1、 进入git在GitHub上发布版本页面https://github.com/git/git/tags,这个页面我们可以找到所有git已发布的版本。这里我们选择最新版的tar.gz包。
下载的源码是2.22:https://github.com/git/git/archive/v2.22.2.tar.gz
tar -zxvf git-2.22.0.tar.gz
进入到解压后的文件夹
cd git-2.22.0
拿到解压后的源码以后我们需要编译源码了,不过在此之前需要安装编译所需要的依赖
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker
耐心等待安装完成,中途出现提示的时候输入y并按回车。
提示,安装编译源码所需依赖的时候,yum自动帮你安装了git,这时候你需要先卸载这个旧版的git。
yum -y remove git
编译git源码
make prefix=/usr/local/git all
安装git至/usr/local/git路径
make prefix=/usr/local/git install
配置环境变量
vi /etc/profile
在底部加上
export PATH=$PATH:/usr/local/git/bin
( 输入 :wq! 保存修改)
刷新环境变量
source /etc/profile
11、查看Git是否安装完成
git --version
至此,从github上下载最新的源码编译后安装git完成。
三 Jenkins安装
下载地址:https://jenkins.io/download/
各个版本Jenkins下载
:http://updates.jenkins-ci.org/download/war/,浏览器下载慢,可以借助迅雷等下载。
3.1 jenkins访问
如果使用tomcat,那么在jenkins下载完后将war包直接复制到tomcat的webapps目录下,然后启动tomcat
启动完成后直接访问链接:http://192.168.0.108:8080/jenkins/
3.2 jenkins初始化配置
初次访问http://192.168.0.108:8080/jenkins/,出现如下界面。密码在启动控制台打印出来,如果没找到,那到图中提示的文件查看即可。
点击继续
注意注意注意!!!!选择第二个自定义安装,然后选择无。
创建用户并且实例配置
四 Jenkins配置
镜像配置
重点来啦:我们要修改Jenkins插件下载地址,否则Jenkins会让你怀疑人生。
以下的配置Json其实在Jenkins的工作目录中
$ cd {你的Jenkins工作目录}/updates #进入更新配置位置
tomcat安装的在/root/.jenkins里面updates
$ vim default.json #这个Json文件与上边的配置文件是相同的
使用vim的命令,如下,替换所有插件下载的url
:1,$s/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g
替换连接测试url
:1,$s/http:\/\/www.google.com/https:\/\/www.baidu.com/g
进入vim先输入:然后再粘贴上边的:后边的命令,注意不要写两个冒号!
修改完成保存退出:wq
修改URL为:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
提交
重启http://192.168.0.109:8080/jenkins/restart
测试镜像
下载中文汉化插件
Jenkins->Manage Jenkins->Manage Plugins,点击Available,搜索"Chinese"
安装。重启Jenkins后,就看到Jenkins汉化了!不同版本可能部分菜单汉化会失败。
五 Jenkins用户权限管理
5.1 插件安装和配置
我们可以利用Role-based Authorization Strategy 插件来管理Jenkins用户权限
开启权限全局安全配置
授权策略切换为"Role-Based Strategy",保存
5.2 创建角色
在系统管理页面进入
点击"Manage Roles"
Global roles(全局角色):管理员等高级用户可以创建基于全局的角色
item roles(项目角色):针对某个或者某些项目的角色
node roles(奴隶角色):节点相关的权限
我们添加以下三个角色:
tx_root:该角色为全局角色。这个角色需要绑定全部下面的Read权限,是为了给所有用户绑定最基本的Jenkins访问权限。注意:如果不给后续用户绑定这个角色,会报错误:用户名 ismissing the Overall/Read permission
架构师:该角色为项目角色。使用正则表达式绑定"tx.",意思是只能操作tx开头的项目。
测试组长:该角色也为项目角色。绑定"test.",意思是只能操作test开头的项目。
保存
5.3 创建用户
给用户分配角色
系统管理页面进入Manage and Assign Roles,点击Assign Roles
绑定规则如下:
张三用户分别绑定tx_root和架构师角色
李四用户分别绑定tx_root和测试组长角色
5.4 角色分配
创建项目测试权限
以root管理员账户创建两个项目,分别为tx_project01和test_project01
结果为:
zhangsan用户登录,只能看到tx_project01项目
lisi用户登录,只能看到test_project01项目
六 Jenkins凭证管理
凭据可以用来存储需要密文保护的数据库密码、Gitlab密码信息、Docker私有仓库密码等,以便Jenkins可以和这些第三方的应用进行交互。
安装Credentials Binding插件
要在Jenkins使用凭证管理功能,需要安装Credentials Binding插件
安装插件后,左边多了"凭证"菜单,在这里管理所有凭证.
可以添加的凭证有5种:
- Username with password:用户名和密码
- SSH Username with private key: 使用SSH用户和密钥
- Secret file:需要保密的文本文件,使用时Jenkins会将文件复制到一个临时目录中,再将文件路径设置到一个变量中,等构建结束后,所复制的Secret file就会被删除。
- Secret text:需要保存的一个加密的文本串,如钉钉机器人或Github的api token
- Certificate:通过上传证书文件的方式
常用的凭证类型有:Username with password(用户密码)和SSH Username with private key(SSH密钥)
接下来以使用Git工具到Gitlab拉取项目源码为例,演示Jenkins的如何管理Gitlab的凭证。
安装Git插件和Git工具为了让Jenkins支持从Gitlab拉取源码,需要安装Git插件以及在CentOS7上安装Git工具。
6.1 Git插件安装
6.2 用户密码凭证
创建凭证
Jenkins->凭证->系统->全局凭证->添加凭证
找到"源码管理"->“Git”,在Repository URL复制Gitlab中的项目URL
配置我们之前的tx_project01工程执行Gitlab的工程链接,同时选择用户密码的凭证。
这时会报错说无法连接仓库!在Credentials选择刚刚添加的凭证就不报错啦
保存配置后,点击构建”立即构建“ 开始构建项目,通过控制台查看可以看到代码已经拉取。
我们看到代码已经拉取下来/root/.jenkins/workspace/
6.3 ssh秘钥凭证
使用root用户生成公钥和私钥
ssh-keygen -t rsa
在/root/.ssh/目录保存了公钥和使用
id_rsa:私钥文件
id_rsa.pub:公钥文件
把生成的公钥放在Gitlab中
以root账户登录->点击头像->Settings->SSH Keys
复制刚才id_rsa.pub文件的内容到这里,点击"Add Key"
在Jenkins中添加凭证,配置私钥
在Jenkins添加一个新的凭证,类型为"SSH Username with private key",把刚才生成私有文件内容复制过来
测试凭证是否可用
新建"tx_project01_ssh"项目->源码管理->Git,这次要使用Gitlab的SSH连接,并且选择SSH凭证
到Gitlab上拷贝ssh凭证
同样尝试构建项目,如果代码可以正常拉取,代表凭证配置成功!
七 Maven安装和配置
下载解压,这些都省略
修改Maven的settings.xml
# 创建本地仓库目录
mkdir /root/repo
vi /opt/maven/conf/settings.xml
本地仓库改为:/root/repo/
添加阿里云私服地址:
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
测试Maven是否配置成功,使用之前的gitlab密码测试项目,修改配置
输入mvn clean package
构建完成
可以看到war包
在Jenkins中配置全局环境变量
八 Tomcat安装和配置
切换到192.168.0.110机器
准备好jdk,Tomcat
配置Tomcat用户角色权限,默认情况下Tomcat是没有配置用户角色权限的
后续Jenkins部署项目到Tomcat服务器,需要用到Tomcat的用户,所以修改tomcat以下配置,添加用户及权限
vi conf/tomcat-users.xml
注意:配置文件不要折行。
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<role rolename="manager-script"/>
<role rolename="manager-gui"/>
<role rolename="manager-status"/>
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<user username="tomcat" password="tomcat" roles="manager-gui,manager-script,tomcat,admin-gui,admin-script"/>
</tomcat-users>
用户和密码都是:tomcat
注意:为了能够刚才配置的用户登录到Tomcat,还需要修改以下配置
vi /webapps/manager/META-INF/context.xml
<!--
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
-->
把上面这行注释掉即可! 重启Tomcat,访问测试
九 Jenkins构建项目部署服务
Jenkins中自动构建项目的类型有很多,常用的有以下三种:
- 自由风格软件项目(FreeStyle Project)
- Maven项目(Maven Project)
- 流水线项目(Pipeline Project)
每种类型的构建其实都可以完成一样的构建过程与结果,只是在操作方式、灵活度等方面有所区别,在实际开发中可以根据自己的需求和习惯来选择。
9.1 自由风格项目构建
下面演示创建一个自由风格项目来完成项目的集成过程:
拉取代码->编译->打包->部署
- 创建项目
- 配置源码管理,从gitlab拉取代码
- 编译打包
echo "开始编译和打包"
mvn clean package
echo "编译和打包结束"
- 把项目部署到远程的Tomcat里面
Jenkins本身无法实现远程部署到Tomcat的功能,需要安装Deploy to container插件实现
(1)插件安装
(2) 添加Tomcat凭证
(3)添加构建后步骤
填入如下的对应内容
9.2 Maven项目构建
(1) 安装Maven Integration插件
(2) 创建Maven项目
配置同上,不过这里要输入pom.xml和Maven要执行的命令
然后配置好部署(同上)成功
十 Jenkins常用的构建触发器
Jenkins内置4种构建触发器:
- 触发远程构建
- 其他工程构建后触发(Build after other projects are build)
- 定时构建(Build periodically)
- 轮询SCM(Poll SCM)
10.1 触发远程构建
身份令牌最好是加密为好。
http://192.168.0.109:8080/jenkins/job/tx_project_pipeline/build?taken=6666
访问时候我们发现Jenkins要求使用post方式,点击Proceed即可
构建结构发生
10.2 其他工程构建后触发
创建前置工程并且配置
配置前置工程,保存。
我们构建pre_project完毕时候会触发tx_project_pipeline工程的构建。
10.3 定时构建
定时字符串从左往右分别为: 分 时 日 月 周
一些定时表达式的例子:
1. 每30分钟构建一次:H代表每隔(以当前时间为基准,如果H换成0就表示从整点开始) H/30 * * * * 10:02 10:32
2. 每2个小时构建一次: H H/2 * * *
3. 每天的8点,12点,22点,一天构建3次: (多个时间点中间用逗号隔开)
0 8,12,22 * * *
4. 每天中午12点定时构建一次 H 12 * * *
5. 每天下午18点定时构建一次 H 18 * * *
6. 在每个小时的前半个小时内的每10分钟 H(0-29)/10 * * * *
7. 每两小时一次,每个工作日上午9点到下午5点(也许是上午10:38,下午12:38,下午2:38,下午4:38) H H(9-16)/2 * * 1-5
我们对我们的工程设置为定时构建 H/2 * * * *
保存后,我们等2分钟即可看到结果
10.4 Git hook自动触发构建
利用Gitlab的webhook实现代码push到仓库,立即触发项目自动构建。
10.4.1 安装插件
安装Gitlab Hook插件,需要安装两个插件:Gitlab Hook和GitLab
10.4.2 Jenkins设置自动构建
Jenkins设置自动构建
等会需要把生成的webhook URL配置到Gitlab中。
10.4.3 Gitlab配置webhook
-
开启webhook功能
使用root账户登录到后台,点击Admin Area -> Settings
勾选"Allow requests to the local network from web hooks and services
-
在项目添加webhook
点击项目->Settings->Integrations
我们可以进行测试,我们发现会有错误。
注意:以下设置必须完成,否则会报错!
Jenkins->系统配置
去掉这个钩
回到Gitlab重新测试即可。
测试webhook,回到工程中添加一行代码,提交并且推送。
我们发现构建已经发生。
Tomcat也自动生效。
10.4.4 参数化构建
有时在项目构建的过程中,我们需要根据用户的输入动态传入一些参数,从而影响整个构建结果,这时们可以使用参数化构建。
Jenkins支持非常丰富的参数类型
- 设置参数化构建
选择字符参数,设置分支名字,我们来设置动态分支构建
我们可以在这里指的要构建的参数值。
- 修改Jenkinsfile脚本
通过设置读取变量的方式来动态获得分支名字
然后把把文件推送到Gitlab - 创建新的分支feature
并且自动切换到feature分支
修改代码并且提交到feature分支。
feature分支产生。
- 参数化构建动态分支
输入feature开始构建
可以看到成功的结果。
十一 Jenkins+Docker+SpringCloud微服务持续集成
11.1 Jenkins+Docker+SpringCloud持续集成流程说明
大致流程说明:
- 开发人员每天把代码提交到Gitlab代码仓库
- Jenkins从Gitlab中拉取项目源码,编译并打成jar包,然后构建成Docker镜像,将镜像上传到Harbor私有仓库。
- Jenkins发送SSH远程命令,让生产部署服务器到Harbor私有仓库拉取镜像到本地,然后创建容器。
- 所需服务器列表
服务器名称 | Ip地址 | 安装软件 |
---|---|---|
代码托管服务器 | 192.168.0.108 | Gitlab |
持续集成服务器 | 192.168.0.109 | Jdk,Maven,Tomcat,Jenkins,docker |
Docker仓库服务器 | 192.168.0.111 | Docker,harbor |
生产部署服务器 | 192.168.0.110 | Docker,Tomcat |
11.2 准备微服务代码
- Springcloud微服务Demo
springcloud-tx:父工程,存放基础配置
txservicecloud-common:通用工程,存放工具类和公共代码
txservicecloud-eureka_10001:端口是10001的SpringCloud的Eureka注册中心
txservicecloud-provider-dep-8001:端口是8001的服务提供者
txservicecloud-consumer-dep-80:端口是80的服务消费者
每个服务逐一测试,保证成功。
SpringBoot微服务项目打包必须导入该插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
打包后在target下产生jar包
- 本地运行微服务的jar包
java -jar xxx.jar
- 查看效果
11.3 Docker环境安装
主机:192.168.0.109
卸载旧版docker软件
名称一般为docker,docker-io或者docker-engine
卸载完成还需要查看并清理旧的docker数据目录,包含镜像,容器,网络等配置
sudo yum remove docker docker-engine docker-common \
docker-client docker-client-latest docker-latest docker-latest-logrotate \
docker-logrotate docker-selinux docker-engine-selinux
rpm -qa |grep docker*
ll /var/lib/docker/
rm -rf /var/lib/docker 删除docker的所有镜像和容
配置docker的yum仓库
yum install yum-utils lvm2 device-mapper-persistent-data -y
配置stable库
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
禁用edge和test库
yum-config-manager --disable docker-ce-edge docker-ce-test
1)yum-utils提供yum-config-manager和utility工具
2)lvm2和device-mapper-persistent-data提供devicemapper的存储驱动
3)即使不使用edge库或test库也必须安装
4)建议上午安装,如果下载超时可以手动下载然后上传到/etc/yum.repos.d/目录
5)Note: Starting with Docker 17.06, stable releases are also pushed to the edge and test repositories.
6)如果启用edge和test库,yum安装时会安装最新版的docker,一般为test测试版,如果要安装最新的稳定版需要禁用该选项
查看可安装的docker-ce列表
yum list docker-ce --showduplicates
安装最新版docker-ce
yum install docker-ce
要安装指定版本docker,可以从上面的列表选择对应的版本号
yum install docker-ce-<VERSION STRING>
yum install docker-ce-18.06.1.ce-3.el7
升级docker-ce
yum -y upgrade <包名>
启动docker配置开机自启动
systemctl start docker
systemctl enable docker
ps -ef |grep docker
阿里云镜像加速:
1.登录:https://dev.aliyun.com/search.html
2.登录阿里云
编辑配置文件
vi /etc/docker/daemon.json
拷贝下面的内容/etc/docker/daemon.json中
{ "registry-mirrors": ["https://tj3411jq.mirror.aliyuncs.com"] }
执行下面两条命令
sudo systemctl daemon-reload
sudo systemctl restart docker
在192.168.0.110机器执行
docker run -itd -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root docker.io/mysql:5.7
1.数据库脚本
DROP DATABASE IF EXISTS cloudDB;
CREATE DATABASE cloudDB CHARACTER SET UTF8;
USE cloudDB;
CREATE TABLE dept
(
deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
dname VARCHAR(60),
db_source VARCHAR(60)
);
INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('财务部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('市场部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE());
SELECT * FROM dept;
11.4 dockerfile制作镜像
使用Dockerfile制作微服务镜像
我们利用Dockerfile制作一个Eureka注册中心的镜像
1)上传Eureka的微服务jar包到linux
2)编写dockerfile01
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10001
ENTRYPOINT ["java","-jar","/app.jar"]
3)构建镜像
docker build -f dockerfile01 --build-arg JAR_FILE=txservicecloud-eureka-10001-1.0-SNAPSHOT.jar -t eureka:v1 .
4)查看镜像是否创建成功
docker images
5)创建容器
docker run -i --name=eureka -p 10001: 10001 eureka:v1
6)访问容器
11.5 Harbor镜像仓库安装及使用
Harbor简介
Harbor(港口,港湾)是一个用于存储和分发Docker镜像的企业级Registry服务器。
除了Harbor这个私有镜像仓库之外,还有Docker官方提供的Registry。相对Registry,Harbor具有很多优势:
- 提供分层传输机制,优化网络传输 Docker镜像是是分层的,而如果每次传输都使用全量文件(所以用FTP的方式并不适合),显然不经济。必须提供识别分层传输的机制,以层的UUID为标识,确定传输的对象。
- 提供WEB界面,优化用户体验 只用镜像的名字来进行上传下载显然很不方便,需要有一个用户界面可以支持登陆、搜索功能,包括区分公有、私有镜像。
- 支持水平扩展集群 当有用户对镜像的上传下载操作集中在某服务器,需要对相应的访问压力作分解。
- 良好的安全机制 企业中的开发团队有很多不同的职位,对于不同的职位人员,分配不同的权限,具有更好的安全性。
11.5.1 Harbor安装
Harbor需要安装在192.168.0.111上面, 同时安装docker
1)先安装Docker并启动Docker(已完成)
参考之前的安装过程
2)安装docker-compose
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
3)给docker-compose添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
4)查看docker-compose是否安装成功
docker-compose -version
5)下载Harbor的压缩包(本课程版本为:v1.9.2)
https://github.com/goharbor/harbor/releases
6)上传压缩包到linux,并解压
tar -xzf harbor-offline-installer-v1.9.2.tgz
mkdir /opt/harbor
mv harbor/* /opt/harbor
cd /opt/harbor
7)修改Harbor的配置
vi harbor.yml
修改hostname和port
hostname: 192.168.0.111
port: 85
8)安装Harbor
./prepare
./install.sh
9)启动Harbor
docker-compose up -d 启动
docker-compose stop 停止
docker-compose restart 重新启动
10)访问Harbor
http://192.168…111:85
默认账户密码:admin/Harbor12345
在Harbor创建用户和项目
1)创建项目
Harbor的项目分为公开和私有的:
公开项目:所有用户都可以访问,通常存放公共的镜像,默认有一个library公开项目。
私有项目:只有授权用户才可以访问,通常存放项目本身的镜像。
我们可以为微服务项目创建一个新的项目:
2)创建用户
用户密码:txjava Txjava123
3)给私有项目分配用户
进入springcloud-tx项目->成员
角色 | 权限说明 |
---|---|
访客 | 对于指定项目拥有只读权限 |
开发人员 | 对于指定项目拥有读写权限 |
维护人员 | 对于指定项目拥有读写权限,创建 Webhooks |
项目管理员 | 除了读写权限,同时拥有用户管理/镜像扫描等管理权限 |
4)以新用户登录Harbor设置注册中心
把Harbor地址加入到Docker作为私服中心,修改
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://tj3411jq.mirror.aliyuncs.com"]
,"insecure-registries": ["192.168.0.111:85"]
}
重启docker
systemctl restart docker
5)登录Harbor
docker login -u 用户名 -p 密码 192.168.0.111:85
docker login -u txjava -p Txjava123 192.168.0.111:85
6)把镜像上传到Harbor
打标签指定注册中心
docker tag eureka:v1 192.168.0.111:85/springcloud-tx/eureka:v1
上传镜像
docker push 192.168.0.111:85/springcloud-tx/eureka:v1
11.5.2 应用服务器拉取镜像
服务器环境192.168.0.110
从Harbor下载镜像
需求:在192.168.0.110服务器完成从Harbor下载镜像
1)安装Docker,并启动Docker(已经完成)
2)修改Docker配置
把Harbor地址加入到Docker作为私服中心,修改vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://tj3411jq.mirror.aliyuncs.com"]
,"insecure-registries": ["192.168.0.111:85"]
}
重启docker
systemctl restart docker
登录
docker login -u txjava -p Txjava123 192.168.0.111:85
拉取
docker pull 192.168.0.111:85/springcloud-tx/eureka:v1
容器运行
docker run -i --name=eureka -p 10001:10001 192.168.0.111:85/springcloud-tx/eureka:v1
11.6 持续构建
11.6.1 上传代码到Gitlab
Gitlab创建工程,上传代码。
11.6.2 Gitlab拉取项目源码
//注意:变量引用使用双引号
def git_auth = "108bc789-e1ee-4c1d-ac5a-54d5049b1cf7"
def project_url = "git@192.168.0.108:root/springcloud-tx.git"
node {
stage('拉取') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${project_url}"]]])
}
}
11.6.3 使用Dockerfile编译、生成镜像
我们可以先测试构建
//注意:变量引用使用双引号
def git_auth = "108bc789-e1ee-4c1d-ac5a-54d5049b1cf7"
def project_url = "git@192.168.0.108:root/springcloud-tx.git"
node {
stage('拉取') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${project_url}"]]])
}
stage('构建') {
sh "mvn -f txservicecloud-common clean install"
sh "mvn -f ${project_name} clean package"
}
}
测试构建保证成功
11.6.4 上传到Harbor镜像仓库
在每一个项目根目录下创建Dockerfile,注意修改对应工程的端口
#FROM java:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10001
ENTRYPOINT ["java","-jar","/app.jar"]
添加Harbor凭证
生成流水线脚本
完善Jenkins脚本
//注意:变量引用使用双引号
def git_auth = "108bc789-e1ee-4c1d-ac5a-54d5049b1cf7"
def project_url = "git@192.168.0.108:root/springcloud-tx.git"
//构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.0.111:85"
//Harbor的项目名称
def harbor_project_name = "springcloud-tx"
def harbor_auth = "06955aa2-c0dc-4c53-9bd6-5c563bd13666"
node {
stage('拉取') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${project_url}"]]])
}
stage('构建') {
//定义镜像名称
def imageName = "${project_name}:${tag}"
sh "mvn -f txservicecloud-common clean install"
//sh "mvn -f ${project_name} clean package"
//编译,构建本地镜像
sh "mvn -f ${project_name} clean package dockerfile:build"
//给镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}",
passwordVariable: 'password', usernameVariable: 'username')]) {
//登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}
//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
}
}
可以看到镜像上传完毕
11.6.5 拉取镜像和发布应用
- 安装 Publish Over SSH 插件
安装以下插件,可以实现远程发送Shell命令
配置远程部署服务器
1)拷贝公钥到远程服务器
ssh-copy-id 192.168.0.110
3)系统配置->添加远程服务器
修改Jenkinsfile构建脚本,生成远程调用模板代码
sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
构建之前要把springcloud-tx父工程打包拷贝(此时不要包含子模块)到192.168.0.110的仓库里面
完整Jenkins脚本
//注意:变量引用使用双引号
def git_auth = "108bc789-e1ee-4c1d-ac5a-54d5049b1cf7"
def project_url = "git@192.168.0.108:root/springcloud-tx.git"
//构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.0.111:85"
//Harbor的项目名称
def harbor_project_name = "springcloud-tx"
def harbor_auth = "06955aa2-c0dc-4c53-9bd6-5c563bd13666"
//定义镜像名称
def imageName = "${project_name}:${tag}"
node {
stage('代码拉取') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${project_url}"]]])
}
stage('工程镜像构建') {
sh "mvn -f txservicecloud-common clean install"
//编译,构建本地镜像
sh "mvn -f ${project_name} clean package dockerfile:build"
//给镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
}
stage('登录Harbor上传镜像') {
//登录Harbor,并上传镜像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}",
passwordVariable: 'password', usernameVariable: 'username')]) {
//登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}
}
stage('删除本地镜像') {
//删除本地镜像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
}
stage('远程触发镜像拉取') {
sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server',
transfers: [sshTransfer(cleanRemote: false, excludes: '',
execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $project_name $tag $port",
execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false,
patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')],
usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
在192.168.0.110机器部署脚本。
部署脚本
#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5
imageName=$harbor_url/$harbor_project_name/$project_name:$tag
echo "$imageName"
#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'`
if [ "$containerId" != "" ] ; then
#停掉容器
docker stop $containerId
#删除容器
docker rm $containerId
echo "成功删除容器"
fi
#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name | awk '{print $3}'`
if [ "$imageId" != "" ] ; then
#删除镜像
docker rmi -f $imageId
echo "成功删除镜像"
fi
# 登录Harbor
docker login -u txjava -p Txjava12345 $harbor_url
# 下载镜像
docker pull $imageName
# 启动容器
docker run -di -p $port:$port --net=host $imageName
echo "容器启动成功"
微服务运行结果。