Jenkins+Rancher+Harbor+Gitlab部署应用到生产环境

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

posted on 2020-11-10 17:58  ExplorerMan  阅读(1818)  评论(0编辑  收藏  举报

导航