6. Gitlab集成Jenkins-静态页面发布
4 Jenkins
4.1 Jenkins介绍
- Jenkins是一个开源的CI/CD工具, 由java语言编写
- 其本质就是一个调度平台, 本身不处理任何事情, 而是调用插件来完成所有的工作
4.2 Jenkins部署
4.2.1 环境
CentOS-7
10.0.0.237 - Gitlab - gitlab-ce-12.0.3
10.0.0.227 - Jenkins - Jenkins-2.176.1
CentOS-8
10.0.0.82 - 开发机-developer-2 / websrv-2
10.0.0.81 - 开发机-developer-1 / websrv-1
4.2.2 安装Jenkins
[18:52:58 root@jenkins ~]#yum localinstall jenkins-2.176.1-1.1.noarch.rpm -y
[19:03:12 root@jenkins ~]#yum -y install java-1.8.0-openjdk.x86_64 # Jenkins需要Java环境
yum -y install git
[19:03:30 root@jenkins ~]#systemctl start jenkins
[19:03:37 root@jenkins ~]#systemctl status jenkins
● jenkins.service - LSB: Jenkins Automation Server
Loaded: loaded (/etc/rc.d/init.d/jenkins; bad; vendor preset: disabled)
Active: active (running) since Wed 2020-12-30 19:03:37 CST; 6s ago
4.2.2.1 Jenkins监听8080端口
LISTEN 0 50 [::]:8080 [::]:*
4.2.3 配置Windows客户端和jenkins服务器本地域名解析
10.0.0.237 gitlab.abc.com
10.0.0.227 jenkins.abc.com
10.0.0.237 gitlab.abc.com
10.0.0.227 jenkins.abc.com
4.2.4 访问jenkins
图片.png- 从文件中获得jenkins密码
[19:09:04 root@jenkins ~]#cat /var/lib/jenkins/secrets/initialAdminPassword
f19096b3376b48b8a8bb2f45183fc963
- 跳过插件安装, 稍后手动安装
- 修改admin密码
4.2.5 插件安装
图片.png 图片.png 图片.png4.2.5.1 调整jenkins插件源, 使用清华源
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
图片.png4.2.5.2 在线安装插件
如需在线安装, 只要进到Available然后再搜索栏搜索即可
图片.png4.2.5.3 从清华源下载.hpi文件后安装插件
实例: 安装jenjins的git插件
- 下载插件
https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/
- 上传插件
- 安装插件
上传后, 点Upload即可, 之后会在线安装
4.2.5.4 离线安装插件
- 停止jenkins服务
[19:17:30 root@jenkins ~]#systemctl stop jenkins
- jenkins插件目录
[19:44:59 root@jenkins ~]#ll /var/lib/jenkins/plugins/
total 0
- 移走现有的plugins目录, 如果里面有内容, 然后把本地的插件包解压, 移动到/var/lib/jenkins/目录下
[19:45:27 root@jenkins ~]#rm -rf /var/lib/jenkins/plugins
[19:47:30 root@jenkins ~]#tar xf jenkins_2.176_plugins.tar.gz
[19:47:52 root@jenkins ~]#mv plugins/ /var/lib/jenkins/
[19:48:49 root@jenkins ~]#chown -R jenkins.jenkins /var/lib/jenkins
- 启动jenkins
[19:50:50 root@jenkins ~]#systemctl start jenkins
- 查看日志
[19:53:02 root@jenkins ~]#tail -f /var/log/jenkins/jenkins.log
INFO: Completed initialization
Dec 30, 2020 7:53:34 PM hudson.WebAppMain$3 run
INFO: Jenkins is fully up and running # 看到这句话就说明启动成功
-
登录jenkins
-
配置警告信息
- 把所有警告信息取消, 保存即可
4.2.6 Jenkins自由风格软件项目简单测试
-
创建项目
图片.png -
设置保留最近10个构建项目
图片.png -
构建操作, 执行Shell, 这里的Shell命令会在Jenkins拉取Gitlab代码后, 在Jenkins服务器上执行
- 立即构建
- 查看控制台输出
图片.png 图片.png
- 通过这种构建方法, 只要登录到jenkins上, 操作立即构建, 即可完成项目构建, 把代码从Gitlab拉取到Jenkins服务器, 之后在推送到后端服务器, 这样就无需登录到Jenkins服务器了
- Jenkins可以实现权限控制, 不同人访问不同的项目
- 构建后的文件
构建后的内容都会存在jenkins服务器上的, /var/lib/jenkins/workspace目录, 以项目名为目录做区分
[19:54:39 root@jenkins ~]#ll /var/lib/jenkins/workspace/
total 0
drwxr-xr-x 2 jenkins jenkins 31 Dec 30 20:24 test-project
[20:30:11 root@jenkins ~]#ll /var/lib/jenkins/workspace/test-project/
total 0
-rw-r--r-- 1 jenkins jenkins 0 Dec 30 20:24 file_from_jenkins
4.3 Jenkins集成Gitlab
4.3.1 Gitlab创建项目
用developer-2管理员用户
图片.png4.3.2 将项目包拷贝到developer-2用户的git客户端, 并解压
[13:51:18 root@developer-2 ~]#ls
monitor_html.tar.gz
[13:51:56 root@developer-2 ~]#tar xf monitor_html.tar.gz
[13:52:16 root@developer-2 ~]#ls
monitor monitor_html.tar.gz
[13:52:17 root@developer-2 ~]#ls monitor
404.html charts.html dianfei.html form-components.html img LICENSE messages.html QHME.iml typography.html
alerts.html components.html efficiencyAnalysis.html form-elements.html index.html list-view.html mstp_105_SuperAdmin.iml readme.md userMng.html
assets content-widgets.html energy_consumption.html form-examples.html js login.html mstp_map.html real-time.html
buttons.html css file-manager.html form-validation.html keyInfo.html media other-components.html sa.html
calendar.html deviceManager.html fonts images-icons.html labels.html media.html profile-page.html tables.html
buttons.html css file-manager.html form-validation.html keyInfo.html media other-components.html sa.html
calendar.html deviceManager.html fonts images-icons.html labels.html media.html profile-page.html tables.html
4.3.3 关联远程仓库, 推送本地现有文件夹
# 先将原有的仓库信息删除, 如果已有
[13:52:33 root@developer-2 ~]#cd monitor/
[13:53:17 root@developer-2 ~/monitor]#git remote -v
origin https://gitee.com/kangjie1209/monitor.git (fetch)
origin https://gitee.com/kangjie1209/monitor.git (push)
[13:53:21 root@developer-2 ~/monitor]#git remote remove origin
[13:53:28 root@developer-2 ~/monitor]#git init
Reinitialized existing Git repository in /root/monitor/.git/
[13:53:45 root@developer-2 ~/monitor]#git remote add origin git@gitlab.abc.com:devops/monitor.git
[13:54:00 root@developer-2 ~/monitor]#git add .
[13:54:03 root@developer-2 ~/monitor]#git commit -m "第一次提交代码"
On branch master
nothing to commit, working tree clean
[13:54:15 root@developer-2 ~/monitor]#git push origin master
Enumerating objects: 435, done.
Counting objects: 100% (435/435), done.
Compressing objects: 100% (372/372), done.
Writing objects: 100% (435/435), 8.78 MiB | 6.19 MiB/s, done.
Total 435 (delta 53), reused 435 (delta 53), pack-reused 0
remote: Resolving deltas: 100% (53/53), done.
To gitlab.abc.com:devops/monitor.git
* [new branch] master -> master
4.3.4 Gitlab验证
图片.png4.3.5 jenkins安装gitlab插件
这里前期已经统一离线导入了插件, 所以无需再安装
image.png- Credential: 允许Jenkins中存储认证的凭据
- Git Client: 允许Jenkins使用Git
- Git: 允许Jenkins集成Git
- Gitlab: 允许Gitlab触发Jenkins构建, 并在Gitlab中显示
- Gitlab Hook Plugin: 允许Gitlab自动触发Jenkins构建项目
- Gitlab Authentication: Gitlab身份验证插件
4.3.6 Jenkins创建freestyle项目, 然后配置gitlab仓库项目对应地址
image.png image.png添加git仓库地址后, 如果出现以下报错, 可能是jenkins服务器没有装git, 需要安装
图片.png安装git后, 如果出现如下报错, 是因为没有配置验证
- 在jenkins服务器生成root账号的ssh秘钥
[21:31:57 root@jenkins ~]#ssh-keygen
-
把公钥放到gitlab上, 公钥放到任何一个对项目有权限的用户的账户里即可
-
添加jenkins凭据
这里要把jenkins上用root用户创建的私钥添加进去, 因为我们把root的公钥放到了gitlab上, jenkins连接gitlab时, gitlab会用拿到的公钥做认证
图片.png 图片.png- 保存后点击构建
- 构建成功后, 返回工程, 进入工作区
[21:44:23 root@jenkins ~]#ll /var/lib/jenkins/workspace/
total 4
drwxr-xr-x 9 jenkins jenkins 4096 Dec 30 21:40 freestyle-monitor
drwxr-xr-x 2 jenkins jenkins 6 Dec 30 21:40 freestyle-monitor@tmp
drwxr-xr-x 2 jenkins jenkins 31 Dec 30 20:24 test-project
[21:44:24 root@jenkins ~]#ll /var/lib/jenkins/workspace/freestyle-monitor
total 1364
-rw-r--r-- 1 jenkins jenkins 1208 Dec 30 21:40 404.html
-rw-r--r-- 1 jenkins jenkins 27249 Dec 30 21:40 alerts.html
drwxr-xr-x 5 jenkins jenkins 64 Dec 30 21:40 assets
-rw-r--r-- 1 jenkins jenkins 34972 Dec 30 21:40 buttons.html
...
到此, 完成了jenkins从gitlab拉取代码, 下面实现项目发布
4.4 手动实现集群架构代码上线
环境:
CentOS 7
----------------------------------
Gitlab - 10.0.0.237 - gitlab.abc.com
Jenkins - 10.0.0.227 - jenkins.abc.com
SonarQube - 10.0.0.207 - sonarqube.abc.com
Nginx-LB - 10.0.0.217 nginx负载均衡服务器后端代理 web服务器 - html.abc.com, 和tomcat服务器, java.abc.com, 需要在windows做域名解析 512MB
CentOS-8
10.0.0.82 - 开发机-developer-2 / websrv-2
10.0.0.81 - 开发机-developer-1 / websrv-1
----------------------------------
4.4.1 配置负载均衡服务器 10.0.0.217
[21:57:44 root@lb ~]#yum -y install nginx
[21:58:02 root@lb ~]#cd /etc/nginx/conf.d
[21:59:45 root@lb /etc/nginx/conf.d]#vim proxy_html.abc.com.conf
upstream html {
server 10.0.0.81;
server 10.0.0.82;
}
server {
listen 80;
server_name html.abc.com;
location / {
proxy_pass http://html;
proxy_set_header Host $http_Host; # 如果后端nginx配置了单独的虚拟主机, 并且指定了主机头为访问的域名html.abc.com, 那么就需要再反向代理加上proxy_set_header, 把用户请求报文的Host字段传给后端服务器, 否则因为upstream定义的是ip地址, 那么转给后端服务器后, 就是转给了默认的虚拟主机, 这样就访问不到子配置文件中的虚拟主机
}
[22:07:27 root@lb /etc/nginx/conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[22:07:33 root@lb /etc/nginx/conf.d]#systemctl restart nginx
4.4.2 配置web1
[22:09:39 root@web1 ~]#yum -y install nginx
[22:11:55 root@web1 ~]#vim /etc/nginx/conf.d/html.abc.com.conf
server {
listen 80;
server_name html.abc.com;
root /code/web;
location / {
index index.html;
}
}
~
[22:17:31 root@web1 ~]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[22:17:36 root@web1 ~]#systemctl restart nginx
[22:18:14 root@web1 ~]#mkdir /code/web -pv
mkdir: created directory ‘/code’
mkdir: created directory ‘/code/web’
4.4.2 配置web2
[22:09:52 root@web2 ~]#yum -y install nginx
[22:11:56 root@web2 ~]#vim /etc/nginx/conf.d/html.abc.com.conf
server {
listen 80;
server_name html.abc.com;
root /code/web;
location / {
index index.html;
}
}
[22:19:26 root@web2 ~]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[22:19:28 root@web2 ~]#systemctl restart nginx
[22:19:33 root@web2 ~]#mkdir -pv /code/web
mkdir: created directory ‘/code’
mkdir: created directory ‘/code/web’
这时访问html.abc.com会有403报错, 因为后端web服务器还没有代码上线
image.png4.4.3 将jenkins服务器上workspace里的代码手动拷贝到两台web服务器上
[22:29:52 root@jenkins ~]#cd /var/lib/jenkins/workspace/freestyle-monitor
[22:29:52 root@jenkins /var/lib/jenkins/workspace/freestyle-monitor]#scp -r * 10.0.0.81:/code/web
[22:31:27 root@jenkins /var/lib/jenkins/workspace/freestyle-monitor]#scp -r * 10.0.0.82:/code/web
再次访问html.abc.com验证负载均衡成功
image.png这样就实现了Jenkins集成Gitlab, 通过构建一个freestyle静态项目, 从Gitlab拉取代码到Jenkins, 再手动把代码从Jenkins复制到后端服务器, 实现代码部署
4.5 实现自动集群架构代码上线
思路:
- 手动搭建nginx集群架构
- 开发提交代码至gitlab, Jenkins手动构建拉取代码
- 在jenkins上编写shell构建脚本, 由jenkins调用, 并推送代码至web服务器组
4.5.1 编写jenkins推送代码脚本
[22:59:49 root@jenkins /data/scripts]#cat html_deploy.sh
#!/bin/bash
DATE=`date +%Y-%m-%d-%H-%M-%S`
web_server="10.0.0.81 10.0.0.82"
#代码打包路径
sdir="/opt" # 把workspace目录下的代码打包到jenkins的/opt目录
#代码部署路径
ddir="/code"
#1. 进入到项目目录, 将内容进行打包
get_code(){
cd ${WORKSPACE} && \ # WORKSPACE变量会返回当前Jenkins项目的目录, 也就是/var/lib/jenkins/workspace/freestyle-monitor
tar czf ${sdir}/web-${DATE}.tar.gz ./*
}
#2. 将内容通过scp拷贝至web集群组
scp_web_server(){
for host in $web_server; do
scp ${sdir}/web-${DATE}.tar.gz root@$host:${sdir}
ssh root@$host "mkdir -p ${ddir}/web-${DATE} && \
tar xf ${sdir}/web-${DATE}.tar.gz -C ${ddir}/web-${DATE} && \
rm -rf ${ddir}/web && \
#/code/web指向真正的代码目录, 因此. 每次构建都要把软连接删除, 重新添加软连接到新的代码目录, 这样静态页面的代码上线就是自动变成新的版本了
ln -s ${ddir}/web-${DATE} ${ddir}/web"
done
}
deploy(){
get_code
scp_web_server
}
deploy
4.5.2 将脚本添加到jenkins
image.png image.png image.png将jenkins设置成以root用户运行, 避免脚本执行过程中由于默认的jenkins用户没有权限导致脚本执行失败, 把jenkins设置为sudo也行
vim /etc/sysconfig/jenkins
JENKINS_USER="root"
systemctl restart jenkins
将jenkins的公钥推送到后端web服务器, 实现ssh免秘钥认证
ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.0.0.81
ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.0.0.82
4.5.3 构建工程, 查看控制台输出
image.png构建如果出现报错, 要配合控制台输出进行排错后再次构建, 构建成功后要去web服务器目录下把错误的输出文件都删除
图片.png 图片.png静态页面自动上线思路:
- 开发将代码推送到gitlab
- jenkins需要事先配置好集成gitlab, 通过构建项目, 添加gitlab项目的目录, Jenkins私钥认证, 以及jenkins公钥添加到Gitlab, 以及构建脚本
- 进到项目工作区, 通过手动点击构建. jenkins会到gitlab上把代码拉取到jenkins本地/var/lib/jenkins/workspace/项目目录, 然后执行sh脚本, 把代码在部署到后端服务器
- 这种方式适用于静态页面上线, 因为不需要编译, 直接把代码部署到后端服务器即可
- 对于php也适用, 不过部署完代码后需要重启php-fpm, 并且删除之前的缓存
4.5.4 实现项目代码升级的发布
测试小案例
- 直接修改gitlab上的index.html页面, 省去开发将项目拉取到本地修改, 在推送到gitlab的过程
- 构建, 验证修改
4.6 Jenkins实现基于版本tag发布
- 让项目基于tag的方式发布
4.6.1 为什么要让项目支持tag版本方式上线?
由于之前上线方式是直接获取最新代码, 那么会造成后期回退变困难. 如果采用tag的方式, 比如第一次上线 tag v1.1, 第二次上线 tag v1.2. 如果上线v1.2出现问题, 那么我们可以快速回退至上一个版本v1.1
4.6.2 实现tag版本上线方式思路
- 开发如果需要发布新版本, 必须将当前的版本打上一个标签
- Jenkins需要让其脚本支持传参, 比如用户传递v1.1则拉取项目v1.1的标签
4.6.3 Jenkins参数化构建介绍
-
定义文本参数
image.png -
定义选项参数
image.png -
修改构建Shell命令, 测试文本参数和选项参数功能
- 这时工作区不会显示立即构建, 而是Build with Parameter
- 手动指定git_version变量值, 选择部署还是发布, 点击开始构建
- 测试结果
从构建结果可以看出, git_version 和 deploy_env可以作为变量, 在构建Shell命令的脚本里调用, 实现从Jenkins界面在构建时指定参数, 传给脚本, 这样Jenkins在拉取代码时可以基于tag版本拉取, 同时, 也可以指定, 本次构建是拉取还是回退操作.
4.7 实战Jenkins部署tag版本
- 首先安装Git Parameter插件, 然后配置Jenkins参数化构建, 让用户在构建时选择对应的tag版本
[01:08:33 root@jenkins ~]#tail -f /var/log/jenkins/jenkins.log
Dec 31, 2020 1:15:45 AM jenkins.InitReactorRunner$1 onAttained
INFO: Augmented all extensions
Dec 31, 2020 1:15:45 AM jenkins.InitReactorRunner$1 onAttained
INFO: Loaded all jobs
Dec 31, 2020 1:15:45 AM jenkins.InitReactorRunner$1 onAttained
INFO: Completed initialization
Dec 31, 2020 1:15:46 AM hudson.PluginManager dynamicLoad
INFO: Plugin git-parameter:0.9.13 dynamically installed
Dec 31, 2020 1:15:46 AM hudson.model.UpdateCenter$DownloadJob run
INFO: Installation successful: Git Parameter
image.png
- 配置参数化构建, 选择Git Parameter
- Jenkins会根据构建时, 选择的版本号, 去Git拉取对应的版本
- 修改构建脚本, 把参数加进去
[12:32:33 root@jenkins /data/scripts]#vim html_deploy_tag.sh
DATE=`date +%Y-%m-%d-%H-%M-%S`
web_server="10.0.0.81 10.0.0.82"
#代码打包路径
sdir="/opt"
#代码部署路径
ddir="/code"
#1. 进入到项目目录, 将内容进行打包
get_code(){
cd ${WORKSPACE} && \
tar czf ${sdir}/web-${DATE}-${git_version}.tar.gz ./*
}
#2. 将内容通过scp拷贝至web集群组
scp_web_server(){
for host in $web_server; do
scp ${sdir}/web-${DATE}-${git_version}.tar.gz root@$host:${sdir}
ssh root@$host "mkdir -p ${ddir}/web-${DATE}-${git_version} && \
tar xf ${sdir}/web-${DATE}-${git_version}.tar.gz -C ${ddir}/web-${DATE}-${git_version} && \
rm -rf ${ddir}/web && \
ln -s ${ddir}/web-${DATE}-${git_version} ${ddir}/web"
done
}
deploy(){
get_code
scp_web_server
}
deploy
图片.png
- 执行构建
-
可以看到此时没有tag可供选择, 因为Gitlab代码还没有加tag
- Gitlab上给代码加tag
- 用10.0.0.82, developer-2的开发机, 拉取代码到本地, 添加tag, 重新上传
[19:51:29 root@developer-2 ~]#ls
monitor monitor_html.tar.gz
[19:51:31 root@developer-2 ~]#cd monitor/
[19:51:45 root@developer-2 ~/monitor]#git pull origin master
[19:51:51 root@developer-2 ~/monitor]#git tag -a "v1.1" -m "测试tag-v1.1"
[19:52:39 root@developer-2 ~/monitor]#git tag
v1.1
[19:52:41 root@developer-2 ~/monitor]#git push origin v1.1
- 修改index.html文件, 推送v1.2版本
[19:52:50 root@developer-2 ~/monitor]#vim index.html
[19:53:49 root@developer-2 ~/monitor]#git add .
[19:53:52 root@developer-2 ~/monitor]#git commit -m "v1.2"
[master dbebf09] v1.2
1 file changed, 1 insertion(+), 1 deletion(-)
[19:53:58 root@developer-2 ~/monitor]#git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 307 bytes | 307.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
To gitlab.abc.com:devops/monitor.git
26cd3d5..dbebf09 master -> master
[19:54:08 root@developer-2 ~/monitor]#git tag -a "v1.2" -m "提交v1.2版本"
[19:54:20 root@developer-2 ~/monitor]#git push origin v1.2
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 182 bytes | 182.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To gitlab.abc.com:devops/monitor.git
* [new tag] v1.2 -> v1.2
- 再修改index.html, 推送v1.3版本
[19:54:39 root@developer-2 ~/monitor]#vim index.html
[19:55:37 root@developer-2 ~/monitor]#git add .
[19:55:43 root@developer-2 ~/monitor]#git commit -m "提交v1.3版本"
[master 747844f] 提交v1.3版本
1 file changed, 1 insertion(+), 1 deletion(-)
[19:55:55 root@developer-2 ~/monitor]#git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 328 bytes | 328.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
To gitlab.abc.com:devops/monitor.git
dbebf09..747844f master -> master
[19:56:06 root@developer-2 ~/monitor]#git tag -a "v1.3" -m "提交v1.3版本"
[19:56:21 root@developer-2 ~/monitor]#git push origin v1.3
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 181 bytes | 181.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To gitlab.abc.com:devops/monitor.git
* [new tag] v1.3 -> v1.3
现在有三个版本,v1.1,v1.2,v1.3, 可以基于tag部署
- 回到jenkins, 验证tag可用, 构建v1.3版本
[10:56:13 root@web1 ~]#ll /code
total 16
lrwxrwxrwx 1 root root 34 Dec 31 12:59 web -> /code/web-2020-12-31-12-59-05-v1.3
- 测试回退到v1.2
但是, 此时, 每次构建, 项目代码都会拷贝到web服务器的项目目录下, 之后要解决这个问题
[13:00:51 root@web1 ~]#ll /code
total 20
lrwxrwxrwx 1 root root 34 Dec 31 13:04 web -> /code/web-2020-12-31-13-04-52-v1.2
drwxr-xr-x 8 root root 4096 Dec 30 23:28 web-2020-12-30-23-28-26
drwxr-xr-x 8 root root 4096 Dec 30 23:59 web-2020-12-30-23-59-56
drwxr-xr-x 2 root root 6 Dec 31 00:21 web-2020-12-31-00-21-46
drwxr-xr-x 5 root root 80 Dec 31 00:23 web-2020-12-31-00-23-42
drwxr-xr-x 2 root root 6 Dec 31 00:24 web-2020-12-31-00-24-20
drwxr-xr-x 8 root root 4096 Dec 31 00:25 web-2020-12-31-00-25-47
drwxr-xr-x 8 root root 4096 Dec 31 12:59 web-2020-12-31-12-59-05-v1.3
drwxr-xr-x 8 root root 4096 Dec 31 13:04 web-2020-12-31-13-04-52-v1.2
到此为止, 只是实现了利用tag, 部署不同的版本, 但是每次都会再web目录下,生成新的项目代码, 下面实现回退功能
- 添加选项参数
- 修改构建脚本, 这里先把deploy_env传进去, 实现deploy功能, rollback稍后实现
[13:12:42 root@jenkins /data/scripts]#cp html_deploy_tag.sh html_deploy_tag_deploy.sh
[13:12:55 root@jenkins /data/scripts]#vim html_deploy_tag_deploy.sh
DATE=`date +%Y-%m-%d-%H-%M-%S`
web_server="10.0.0.81 10.0.0.82"
#代码打包路径
sdir="/opt"
#代码部署路径
ddir="/code"
#1. 进入到项目目录, 将内容进行打包
get_code(){
cd ${WORKSPACE} && \
tar czf ${sdir}/web-${DATE}-${git_version}.tar.gz ./*
}
#2. 将内容通过scp拷贝至web集群组
scp_web_server(){
for host in $web_server; do
scp ${sdir}/web-${DATE}-${git_version}.tar.gz root@$host:${sdir}
ssh root@$host "mkdir -p ${ddir}/web-${DATE}-${git_version} && \
tar xf ${sdir}/web-${DATE}-${git_version}.tar.gz -C ${ddir}/web-${DATE}-${git_version} && \
rm -rf ${ddir}/web && \
ln -s ${ddir}/web-${DATE}-${git_version} ${ddir}/web"
done
}
deploy(){
get_code
scp_web_server
}
rollback(){
echo "rollback"
}
if [ ${deploy_env} == "deploy" ]; then
deploy
elif [ ${deploy_env} == "rollback" ]; then
rollback
fi
- 修改构建
- 重新构建, 测试部署v1.3
- 此时, 选择tag后, 还可以选择选项, deploy还是rollback
当前版本:
图片.png
构建v1.3后:
图片.png- 可以看到, 拉取的tag是v1.3
- 增加回退功能, 编写回退脚本
- 先把两台web服务器上, 重复的版本目录删除
[13:07:28 root@web1 ~]#ll /code
total 24
lrwxrwxrwx 1 root root 34 Dec 31 13:31 web -> /code/web-2020-12-31-13-31-36-v1.3
drwxr-xr-x 8 root root 4096 Dec 30 23:28 web-2020-12-30-23-28-26
drwxr-xr-x 8 root root 4096 Dec 30 23:59 web-2020-12-30-23-59-56
drwxr-xr-x 2 root root 6 Dec 31 00:21 web-2020-12-31-00-21-46
drwxr-xr-x 5 root root 80 Dec 31 00:23 web-2020-12-31-00-23-42
drwxr-xr-x 2 root root 6 Dec 31 00:24 web-2020-12-31-00-24-20
drwxr-xr-x 8 root root 4096 Dec 31 00:25 web-2020-12-31-00-25-47
drwxr-xr-x 8 root root 4096 Dec 31 12:59 web-2020-12-31-12-59-05-v1.3
drwxr-xr-x 8 root root 4096 Dec 31 13:04 web-2020-12-31-13-04-52-v1.2
drwxr-xr-x 8 root root 4096 Dec 31 13:31 web-2020-12-31-13-31-36-v1.3
[13:42:12 root@web1 ~]#rm -rf /code/web-2020-12-31-12-59-05-v1.3
[10:56:09 root@web2 ~]#ll /code
total 24
lrwxrwxrwx 1 root root 34 Dec 31 13:31 web -> /code/web-2020-12-31-13-31-36-v1.3
drwxr-xr-x 8 root root 4096 Dec 30 23:28 web-2020-12-30-23-28-26
drwxr-xr-x 8 root root 4096 Dec 30 23:59 web-2020-12-30-23-59-56
drwxr-xr-x 2 root root 6 Dec 31 00:21 web-2020-12-31-00-21-46
drwxr-xr-x 5 root root 80 Dec 31 00:23 web-2020-12-31-00-23-42
drwxr-xr-x 2 root root 6 Dec 31 00:24 web-2020-12-31-00-24-20
drwxr-xr-x 8 root root 4096 Dec 31 00:25 web-2020-12-31-00-25-47
drwxr-xr-x 8 root root 4096 Dec 31 12:59 web-2020-12-31-12-59-05-v1.3
drwxr-xr-x 8 root root 4096 Dec 31 13:04 web-2020-12-31-13-04-52-v1.2
drwxr-xr-x 8 root root 4096 Dec 31 13:31 web-2020-12-31-13-31-36-v1.3
[13:46:58 root@web2 ~]#rm -rf /code/web-2020-12-31-12-59-05-v1.3
- 修改脚本
DATE=`date +%Y-%m-%d-%H-%M-%S`
web_server="10.0.0.8110.0.0.82"
#代码打包路径
sdir="/opt"
#代码部署路径
ddir="/code"
#1. 进入到项目目录, 将内容进行打包
get_code(){
cd ${WORKSPACE} && \
tar czf ${sdir}/web-${DATE}-${git_version}.tar.gz ./*
}
#2. 将内容通过scp拷贝至web集群组
scp_web_server(){
for host in $web_server; do
scp ${sdir}/web-${DATE}-${git_version}.tar.gz root@$host:${sdir}
ssh root@$host "mkdir -p ${ddir}/web-${DATE}-${git_version} && \
tar xf ${sdir}/web-${DATE}-${git_version}.tar.gz -C ${ddir}/web-${DATE}-${git_version} && \
rm -rf ${ddir}/web && \
ln -s ${ddir}/web-${DATE}-${git_version} ${ddir}/web"
done
}
deploy(){
get_code
scp_web_server
}
rollback(){
rollback_file=`ssh root@10.0.0.81 "find /code/ -maxdepth 1 -type d -name "web-*-${git_version}""` # 找到需要回退到的那个目录的目录名, 这样回退时就可以把当前的软连接删除, 重新连接到这个版本上, 这样就不会再重新生成一个目录了
for host in $web_server; do
ssh root@$host "rm -rf ${ddir}/web && \
ln -s ${rollback_file} ${ddir}/web" # 删除当前的软连接后, 重新创建软连接, 指向上面找到的要回退的那个版本, 这样回退就不用jenkins去拉代码, 然后重复部署到web服务器了.
done
}
if [ ${deploy_env} == "deploy" ]; then
deploy
elif [ ${deploy_env} == "rollback" ]; then
rollback
fi
- 配置构建
- 构建, 回退到1.2版本
[13:50:28 root@web1 ~]#ll /code
total 20
lrwxrwxrwx 1 root root 34 Dec 31 14:01 web -> /code/web-2020-12-31-13-04-52-v1.2 # 重新把软连接指向v1.2版本, 而且并没有重新部署一次代码.
drwxr-xr-x 8 root root 4096 Dec 30 23:28 web-2020-12-30-23-28-26
drwxr-xr-x 8 root root 4096 Dec 30 23:59 web-2020-12-30-23-59-56
drwxr-xr-x 2 root root 6 Dec 31 00:21 web-2020-12-31-00-21-46
drwxr-xr-x 5 root root 80 Dec 31 00:23 web-2020-12-31-00-23-42
drwxr-xr-x 2 root root 6 Dec 31 00:24 web-2020-12-31-00-24-20
drwxr-xr-x 8 root root 4096 Dec 31 00:25 web-2020-12-31-00-25-47
drwxr-xr-x 8 root root 4096 Dec 31 13:04 web-2020-12-31-13-04-52-v1.2
drwxr-xr-x 8 root root 4096 Dec 31 13:31 web-2020-12-31-13-31-36-v1.3
注意:回退一定要是之前部署过的版本才能回退
- 重复构建
-
相同的版本, 多次部署构建, 就是重复构建, 这时, 这个版本就会被拉取到web服务器多次, 这时通过find命令查找到了指定版本号的目录就是多个了, 需要再次取最后一行才能拿到想要的版本, 所以, 多次构建相同的版本时, 不能每次都部署代码到后端服务器
-
对于重复构建, 只要在构建历史中把成功构建的记录删除, 就可以重复构建了, 因为GIT_PREVIOUS_SUCCESSFUL_COMMIT对比的就是本次构建的commit id是否在构建历史中存在
- Jenkins的环境变量
GIT_COMMIT
The commit hash being checked out.
GIT_PREVIOUS_SUCCESSFUL_COMMIT # 该变量会记录上一次成功提交的信息(commit ID). 如果是第一次提交, 这个变量的值就是个空值. 如果上一次提交成功, 那么这个previous变量就会记录上一次提交的信息(commit ID). 我们可以实现, 如果重复提交就会报错. 可以通过变量判断实现
The hash of the commit last successfully built on this branch, if any.
if [ ${GIT_COMMIT} == ${GIT_PREVIOUS_SUCCESSFUL_COMMIT} ];
说明项目已经部署过
举例:
假设第一次提交, commit id是123456, 这时两个变量值是不相等的, 如果不相等, 我们就执行部署. 如果成功, 那么123456就会存到previous变量
如果第二次又提交123456这个ID号, 那么这时两个变量的值就是相当的, 我们就认为这个commit已经部署过了, 就不在部署了
- 修改构建脚本, 静态页面最终版
vim html_deploy_tag_rollback.sh
DATE=`date +%Y-%m-%d-%H-%M-%S`
web_server="10.0.0.81 10.0.0.82"
#代码打包路径
sdir="/opt"
#代码部署路径
ddir="/code"
#1. 进入到项目目录, 将内容进行打包
get_code(){
cd ${WORKSPACE} && \
tar czf ${sdir}/web-${DATE}-${git_version}.tar.gz ./*
}
#2. 将内容通过scp拷贝至web集群组
scp_web_server(){
for host in $web_server; do
scp ${sdir}/web-${DATE}-${git_version}.tar.gz root@$host:${sdir}
ssh root@$host "mkdir -p ${ddir}/web-${DATE}-${git_version} && \
tar xf ${sdir}/web-${DATE}-${git_version}.tar.gz -C ${ddir}/web-${DATE}-${git_version} && \
rm -rf ${ddir}/web && \
ln -s ${ddir}/web-${DATE}-${git_version} ${ddir}/web"
done
}
deploy(){
get_code
scp_web_server
}
rollback(){
rollback_file=`ssh root@10.0.0.81 "find /code/ -maxdepth 1 -type d -name "web-*-${git_version}""`
for host in $web_server; do
ssh root@$host "rm -rf ${ddir}/web && \
ln -s ${rollback_file} ${ddir}/web"
done
}
if [ ${deploy_env} == "deploy" ]; then
# 如果选择了deploy部署, 就要判断这次部署的commit id, 是否在历史成功记录中有记录, 如果有就提示已经部署过了. GIT_COMMIT是jenkins拉取某个版本的代码后, 返回其commit id, 而GIT_PREVIOUS_SUCCESSFUL_COMMIT返回的是, 当前要部署的这个代码的COMMIT ID在整个jenkins部署成功历史中有没有记录, 如果没有记录就会返回空, 那么说明这个版本没有部署过, 如果有记录, 就会返回这个commit id, 通过条件判断, 因为这时这个commit id和当前要部署的id是相等的, 就会提示已经部署过
if [ ${GIT_COMMIT} == ${GIT_PREVIOUS_SUCCESSFUL_COMMIT} ]; then
echo "已经部署过该版本, ${git_version}"
exit 1
else
deploy
fi
elif [ ${deploy_env} == "rollback" ]; then
rollback
fi
- 测试脚本, 部署此前部署过的版本
- v1.3已经部署过了, 如果再次部署, 会按照构建脚本的定义不再部署, 直接退出
- 测试部署新的版本
- 开发机修改index.html
[20:49:18 root@developer-2 ~/monitor]#vim index.html
<a class="logo pull-left" href="index.html" style="width: 233px">哈哈哈-v.1.4/a>
[20:49:37 root@developer-2 ~/monitor]#git add .
[20:49:40 root@developer-2 ~/monitor]#git commit -m "v1.4"
[master a6f547f] v1.4
1 file changed, 1 insertion(+), 1 deletion(-)
[20:49:45 root@developer-2 ~/monitor]#git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 304 bytes | 304.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
To gitlab.abc.com:devops/monitor.git
747844f..a6f547f master -> master
[20:49:54 root@developer-2 ~/monitor]#git tag -a "v1.4" -m "v1.4"
[20:50:04 root@developer-2 ~/monitor]#git push origin v1.4
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 159 bytes | 159.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To gitlab.abc.com:devops/monitor.git
* [new tag] v1.4 -> v1.4
- 此时v1.4版本是没有部署过的, 因此肯定部署会成功
- 如果再次部署v1.4就会提示已经部署过了