Jenkins结合rancher进行项目的持续集成,这个流程其实跟之前的java项目、React项目、安卓项目的持续集成都差不多。但是相较之前的项目部署来说,在流程上多了很多的步骤,需要注意的地方比较多,所以在这里以部署一个java的demo项目进行演示和记录。
一、环境准备
本次实验的主机系统全部为CentOS Linux release 7.6.1810 (Core)
。
1、需要用到的服务
应用 | 版本 |
---|---|
Jenkins | 2.213 |
Gitlab | 11.9.9 |
Rancher | 2.3.5 |
Harbor | 1.10.0 |
2、准备rancher-cli
要想Jenkins能远程控制rancher,需要借助rancher-cli这个工具来实现。具体的配置方法可以参考:rancher-cli的使用。
3、准备rancher存储类(StrongClass)
在k8s中,关于存储的概念有3个:PV、PVC、StrongClass,在规划存储之前,最好想了解下这三个概念,可以参考下这篇文章:Kubernetes PV与PVC
前面已经搭建了一个3个节点的rancher集群,因为考虑应用的日志问题,所以这里准备一个存储类用于应用日志目录的挂载。
首先进入到将要部署应用的集群中,点击应用商店
,选择启动
,搜索nfs
,点击进去并拉到页面最下方点击启动
进行安装,操作流程如下图:
部署完成后,可以在集群的工作负载
中看到对应的服务。
在这里做一个小小的规划:后续所有应用的日志都通过这个nfs服务进行汇总到一台主机这个nfs共享目录中,这样开发人员在点击jenkins进行部署完成之后,不需要知道这中间复杂的过程,直接去一个统一的位置查看日志就行了。
所以我打算将rancher集群中的node2(192.168.0.52)
的/data
目录共享出来(当然比较好的做法是单独的挂载一块容量较大的硬盘到/data
目录)
注意:这个nfs共享的分区需要使用xfs
格式,否则后期可能会出现pod挂载失败的报错。报错的内容如下:
Unable to mount volumes for pod "isj-eureka-57fb65b885-wf77q_isj(b0b0594f-715e-11e9-884a-0050568fa4d0)": timeout expired waiting for volumes to attach or mount for pod "isj"/"isj-eureka-57fb65b885-wf77q". list of unmounted volumes=[eureka]. list of unattached volumes=[eureka default-token-9wmpb]
- 1
接着来对刚才在应用商店部署的nfs服务进行一些调整,来满足上面的这个小小规划的需求。点击右边三个小点,选择升级
,然后更改一些配置信息。
这里修改了两个地方:
1)主机调度:让pod绑定在node2(192.168.0.52)
上。
2)数据卷:卷名可以自定义,主机路径改成我们预设的/data
目录。
调整之后,点击最下方的升级
就生效了,这样一个nfs的存储类就创建完成了。后续需要用到存储的时候,可以直接从这个存储类中划分,非常方便。
4、添加持久卷声明(PVC)
上面的存储类配置之后不能直接应用,还需要添加持久卷声明(PVC)才能用。
来到集群的PVC
栏目中,点击添加PVC
配置如下:名称
:可以自定义。命名空间
:我这里是根据项目来规划命名空间的,所以选择demo。如果没有项目的命名空间,可以新建一个。来源
:选择使用存储类创建新的持久卷(PV)
存储类
:选择刚才创建的nfs-provisioner
。容量
:因为这里上面nfs共享的分区的空间不大,我这里就限制为20G。
点击创建,就能在PVC列表中看到一个20G大小的PVC了,后面的应用部署将会用到这个PVC。
二、相关服务安装
需要用到的各个服务的详细安装这里就不讲了,有需要的可以直接点击参考一下:
三、正式配置
先来整理下思路:首先在Jenkins上将代码克隆下来,进行编译打包,然后编写Dockerfile来构建镜像并将镜像推送到私服,接着就可以在rancher中部署项目了。
按照上面的思路,就可以一步步的把一个应用给部署好了。
1、克隆代码,构建镜像
Jenkins想必都是很熟悉的了,我这里选择了一个自由风格
的项目进行配置(我个人比较爱用自由风格的)。废话不多说,直接上Jenkins的配置。
其实这就是一般Jenkins的配置,这里就不讲了。
我这里要说的是在构建
中的执行shell
中要写的脚本,将需求具体化成步骤:
1)到项目的$WORKSPACE
目录中去执行打包命令。
2)进入到target
目录编写Dockerfile。
3)打镜像,并推送到Harbor上。
注意
:如果不是用的Harbor的默认自带项目library
的话,需要先在的Harbor上创建项目,我这里是在Harbor新建一个demo
项目。
先暂时到这里吧,上面步骤的shell脚本如下:
#!/bin/bash
source /etc/profile
##set color##
echoRed() { echo $'e[0;31m'"$1"$'e[0m'; }
echoGreen() { echo $'e[0;32m'"$1"$'e[0m'; }
echoYellow() { echo $'e[0;33m'"$1"$'e[0m'; }
##set color##
# 设置变量
project="demo"
version=`date +%Y%m%d%H%M%S`
port=9001
echo -------------------------------------
# mvn打包
cd $WORKSPACE
mvn clean install -DskipTests=true
if [ $? -eq 0 ];then
echoGreen "mvn package is success!"
else
echoRed "mvn package is Failed!" && exit 1
fi
sleep 2
# 进入target目录
cd $WORKSPACE/target/ && mv $project-0.0.1-SNAPSHOT.jar app.jar
# 创建docker镜像
cat > run.sh << EOF
#!/bin/bash
source /etc/profile
java -jar /opt/app.jar --server.port=${port}
EOF
chmod +x run.sh
cat >Dockerfile << EOF
FROM 192.168.0.153/public/jdk:1.8
MAINTAINER wc <123@qq.com>
ENV LANG en_US.UTF-8
ADD app.jar /opt
ADD run.sh /
EXPOSE 9001
ENTRYPOINT [ "sh", "-c", "/run.sh" ]
EOF
# 编译镜像
echoGreen "开始构建当次镜像!"
docker build -t 192.168.0.153/demo/$project:$version .
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
好了,Jenkins执行下构建,构建完成之后去Harbor上看一眼。
最下面这个镜像就是刚才推送到Harbor上的。
2、部署应用
好了,镜像已经打好了,下面的步骤就是要在rancher中进行应用的部署了,因为rancher集成了很友好的UI界面,所以常规应用的部署直接在UI中操作就可以了。
进入到集群中,在工作负载
中点击部署服务
,配置见下图:1
:定义将要部署应用的名称,这里最好与上面脚本中$project
的值相等,便于脚本上下文的调用。
2
:填入刚才生成的镜像的地址。
3
:选择应用要用的命名空间,如果没有想要的,可以新建一个。
4
:端口名称,自定义即可。
5
:填入容器中应用的端口。
6
:填入将要映射出来的端口,建议合理规划一下映射的端口。
7
:通过端口检查来做健康检查,后面的时间可以根据应用初始化情况进行合理调整。
8
:在添加卷
中选择使用现有PVC
,卷名自定义即可。
9
:选择之前创建的PVC。
10
:根据自己的需求挂载容器目录,我这里把应用的日志目录挂载出来。
11
:定义挂载在持久卷中的目录名称。
然后点击启动
,就完成应用的部署了。稍等一会,就可以在工作负载
中看到这个刚部署的应用了。
部署完成之后,可以访问下试试,点击应用名称下边的端口,就可以直接跳转访问。
再来看看应用的日志情况:
接着去我们一开始配置的存储类对应的节点(192.168.0.52)上看看是否有日志文件。
[root@node2 demo]# pwd
/data/pvc-33ac32cb-ff71-412b-98e5-bd4b5e16751f/demo
[root@node2 demo]# ls
demo.log
- 1
- 2
- 3
- 4
可以看到日志和一开始预期的一样出现了,其中pvc-33ac32cb-ff71-412b-98e5-bd4b5e16751f
就是上面创建的持久卷声明(PVC)的名称,demo
是刚才在rancher上部署应用时定义的。
3、完善脚本
OK,上面的都没问题。这样就完成了一个应用的部署,剩下的事情就是把刚才的shell脚本补充完整(刚才的shll脚本只写到推送镜像到Harbor为止),达到一键部署的效果。
这里之后的shell脚本的完整内容如下:
#!/bin/bash
source /etc/profile
##set color##
echoRed() { echo $'e[0;31m'"$1"$'e[0m'; }
echoGreen() { echo $'e[0;32m'"$1"$'e[0m'; }
echoYellow() { echo $'e[0;33m'"$1"$'e[0m'; }
##set color##
# 设置变量
project="demo"
version=`date +%Y%m%d%H%M%S`
port=9001
harbor_user="admin"
harbor_pwd="Harbor12345"
harbor_host="192.168.0.153"
echo ----------------------------------------------
# mvn打包
cd $WORKSPACE
mvn clean install -DskipTests=true
if [ $? -eq 0 ];then
echoGreen "mvn package is success!"
else
echoRed "mvn package is Failed!" && exit 1
fi
sleep 2
# 进入target目录
cd $WORKSPACE/target/ && mv $project-0.0.1-SNAPSHOT.jar app.jar
# 创建docker镜像
cat > run.sh << EOF
#!/bin/bash
source /etc/profile
java -jar /opt/app.jar --server.port=${port}
EOF
chmod +x run.sh
cat >Dockerfile << EOF
FROM 192.168.0.153/public/jdk:1.8
MAINTAINER wc <123@qq.com>
ENV LANG en_US.UTF-8
ADD app.jar /opt
ADD run.sh /
EXPOSE 9001
ENTRYPOINT [ "sh", "-c", "/run.sh" ]
EOF
# 编译镜像
echoGreen "开始构建本次镜像!"
docker build -t $harbor_host/demo/$project:$version .
[ $? != 0 ] && echoRed "请注意,打镜像时出错,故而退出!" && exit 1
# 登录远程Harbor仓库
echoGreen "开始登录远程Harbor仓库!"
docker login -u $harbor_user -p $harbor_pwd $harbor_host
[ $? != 0 ] && echoRed "请注意,登录Harbor时出错,故而退出!" && exit 1
# 上传到docker私服
echoGreen "开始push新镜像到私服!"
docker push $harbor_host/demo/$project:$version
[ $? != 0 ] && echoRed "请注意,在执行push上传时出错,故而退出!" && exit 1
docker rmi $harbor_host/demo/$project:$version
# 更新镜像
echoGreen "开始将新镜像部署到远端!"
rancher kubectl set image deployment/$project $project=192.168.0.153/demo/$project:$version -n demo
[ $? != 0 ] && echoRed "请注意,在执行镜像更新时出错,故而退出!" && exit 1
echoGreen "部署完成!"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
这里先说一下,因为应用时放在单独的容器中执行的,所以jar包的名称无关紧要,我这里直接把jar包的名称改为app.jar
,这样在写dockerfile和运行的时候都是用的app.jar
这个名称,以后即使不同的项目,都不需要对shell脚本中的jar包名称进行更改了。
把上面这个shell脚本放到Jenkins的执行shell
中,然后再点击一下构建,看看是不是能把新构建的镜像部署到rancher中去。
查看Jenkins的控制台输出,可以看到流程一切顺利。
然后来看rancher这边,可以看到新的应用已经开始部署了。
因为之前在rancher中配置应用时使用的缩放/升级策略
是滚动: 先启动新Pod,再停止旧Pod
,所以整个部署过程是不会影响到业务的正常访问的。
再来谈谈规范化的问题,整个过程中都在考虑规范化的问题,以后再新增应用的时候,直接Jenkins复制Job,仅仅需要更改一些git仓库的地址,以及shell脚本中的一些变量的值,然后rancher上复制应用,对应的更改一些地方,一个新的应用的部署就这么完成了, 其实并不复杂。
参考文章:
http://www.eryajf.net/2746.html
https://i4t.com/4467.html