一、安装gitlab服务
Ubuntu20.04
1.1 安装依赖包
apt update
apt install -y iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server nfs-common \
lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev gcc openssh-server \
zlib1g-dev iotop unzip zip ipmitool
1.2 下载gitlab并安装
cd /opt
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu/pool/focal/main/g/gitlab-ce/gitlab-ce_14.5.0-ce.0_amd64.deb
dpkg -i gitlab-ce_14.5.0-ce.0_amd64.deb
1.3 配置gitlab
[root@gitlab opt]#grep '^[a-zA-Z]' /etc/gitlab/gitlab.rb
external_url 'http://10.0.0.163'
1.4 初始化服务
# 执行配置重新设置并启动服务
gitlab-ctl reconfigure
gitlab相关目录
/etc/gitlab # 配置文件目录
/run/gitlab # pid目录
/opt/gitlab # 安装目录
/var/opt/gitlab # 数据目录
/var/log/gitlab # 日志目录
1.5 gitlab常用命令
- gitlab-rails
用于启动控制台进行特殊操作,如修改管理员密码、打开数据库控制台(gitlab-rails dbconsole)等
- gitlab-psql
数据库命令行
示例:
[root@gitlab opt]#gitlab-psql
psql (12.7)
Type "help" for help.
gitlabhq_production=#
gitlabhq_production=# \db
List of tablespaces
Name | Owner | Location
------------+-------------+----------
pg_default | gitlab-psql |
pg_global | gitlab-psql |
(2 rows)
gitlabhq_production=#
- gitlab-rake
数据备份恢复等数据操作
- gitlab-ctl
客户端命令行操作行
gitlab-ctl stop #停止gitlab
gitlab-ctl start #启动gitlab
gitlab-ctl restart #重启gitlab
gitlab-ctl status #查看组件运行状态
gitlab-ctl tail nginx #查看某个组件的日志
1.6 验证gitlab启动完成
[root@gitlab ~]#gitlab-ctl status
run: alertmanager: (pid 16525) 156s; run: log: (pid 16280) 205s
run: gitaly: (pid 16539) 155s; run: log: (pid 15562) 303s
run: gitlab-exporter: (pid 16491) 158s; run: log: (pid 16191) 224s
run: gitlab-workhorse: (pid 16476) 159s; run: log: (pid 15976) 244s
run: grafana: (pid 16548) 155s; run: log: (pid 16429) 173s
run: logrotate: (pid 15478) 316s; run: log: (pid 15488) 315s
run: nginx: (pid 16015) 239s; run: log: (pid 16051) 236s
run: node-exporter: (pid 16485) 159s; run: log: (pid 16068) 232s
run: postgres-exporter: (pid 16533) 155s; run: log: (pid 16316) 200s
run: postgresql: (pid 15724) 298s; run: log: (pid 15736) 296s
run: prometheus: (pid 16504) 157s; run: log: (pid 16251) 212s
run: puma: (pid 15920) 257s; run: log: (pid 15927) 256s
run: redis: (pid 15518) 310s; run: log: (pid 15531) 309s
run: redis-exporter: (pid 16498) 158s; run: log: (pid 16218) 218s
run: sidekiq: (pid 15939) 251s; run: log: (pid 15957) 248s
1.7 验证端口及状态
默认监听tcp80端口
[root@gitlab ~]#lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 16015 root 7u IPv4 113086 0t0 TCP *:http (LISTEN)
nginx 16016 gitlab-www 7u IPv4 113086 0t0 TCP *:http (LISTEN)
nginx 16017 gitlab-www 7u IPv4 113086 0t0 TCP *:http (LISTEN)
1.8 登录gitlab web界面
默认用户名:root
密码在/etc/gitlab/initial_root_password
文件中
1.9 设置中文
进入首页-->个人用户-->Perferences
Localization-->Language,选择简体中文
查看中文
1.10 gitlab使用说明
常用git命令
使用git命令下载代码和提交代码等操作
git config --global user.name "name" # 设置全局用户名
git config --global user.email xxx@xx.com # 设置全局邮箱
git config --global --list # 列出用户全局设置
git add index.html / . # 添加指定文件、目录或当前目录下所有数据到暂存区
git commit -m "11" # 提交文件到工作区
git status # 查看工作区的状态
git push # 提交代码到服务器
git pull # 获取代码到本地
git log # 查看操作日志
vim . gitignore # 定义忽略文件上传至gitlab
git reset --hard HEAD^^ # git版本回滚,HEAD为当前版本,加一个^为上一个版本,^^为上上一个版本
git reflog # 获取每次提交的 ID,可以使用--hard根据提交的ID进行版本回退
git reset --hard 5ae4b06 # 回退到指定id的版本
git branch # 查看当前所处的分支
git checkout -b develop # 创建并切换到一个新分支
git checkout develop # 切换分支
工作流程
概念说明
-
工作区
clone的代码或者开发自己编写的代码文件所在的目录,通常是代码所在的一个服务的目录名称
-
暂存区
用于存储在工作区中对代码进行修改后的文件所保存的地方,使用
git add
添加 -
本地仓库
用于提交存储在工作区和暂存区中改过的文件地方,使用
git commit
提交 -
远程仓库
多个开发共同协作提交代码的仓库,即gitlab服务器,使用
git push
推送
流程图如下
1.11 数据备份与恢复
1.11.1 数据备份
- 停止gitlab数据服务
gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
- 备份数据
gitlab-rake gitlab:backup:create # 在任意目录即可备份当前gitlab数据
- 启动数据服务
gitlab-ctl start
- 查看备份数据
/var/opt/gitlab/backups/ # 数据备份目录,需要使用命令备份
/var/opt/gitlab/nginx/conf # nginx配置文件
/etc/gitlab/gitlab-secrets.json # key文件
/etc/gitlab/gitlab.rb # gitlab配置文件
备份数据
[root@gitlab data]#ll /var/opt/gitlab/backups/
total 336
drwx------ 2 git root 60 Mar 17 00:20 ./
drwxr-xr-x 21 root root 4096 Mar 17 00:08 ../
-rw------- 1 git git 337920 Mar 17 00:20 1678994459_2023_03_17_14.5.0_gitlab_backup.tar
1.11.2 数据恢复
- 停止服务
#gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
- 执行恢复
gitlab-rake gitlab:backup:restore BACKUP=1678994459_2023_03_17_14.5.0 # 备份文件名,无需加后缀名_gitlab_backup.tar
如果是恢复到新的机器上需要将 gitlab.rb 和 gitlab-secrets.json 手动复制到相应路径下
- 启动服务
gitlab-ctl start sidekiq
#gitlab-ctl start unicorn
1.12 常见代码部署方式
1.12.1 蓝绿发布
蓝绿发布指的是不停老版本代码(不影响上一个版本访问),而是在另外一套环境部署新版本然后进行测试,测试通过后将用户流量切到新版本,其特点为业务无中断,升级风险相对较小。
具体过程
- 当前版本业务正常访问(V1)
- 在另外一套环境部署新代码(V2),代码可能是增加了功能或修复了BUG
- 测试通过后将用户请求流量切到新版本环境
- 观察一段时间,如有异常直接切换旧版本
- 下次升级,将旧版本升级到新版本(V3)
蓝绿发布适用场景
- 不停止老版本,额外部署一套新版本,等新版本通过测试后,删除老版本
- 蓝绿发布时一种用于升级与更新的发布策略,部署的最小维度是容器,而发布最小维度时应用
- 蓝绿发布对场景升级有比较好的支持,但是对于涉及数据表结构变更等不可逆的升级,并不完全适用蓝绿发布来实现,需要结合一些业务的逻辑以及数据迁移与回滚的策略才可以完全满足需求
1.12.2 金丝雀发布
金丝雀发布也叫灰度发布,是指在黑与白之间,能够平滑过渡的一种发布方式,灰度发布是增量发布的一种类型,灰度发布是在原版本可用的情况下,同时部署一个新版本应用作为“金丝雀/小白鼠”,测试新版本的性能和表现,以保障整体系统稳定的情况下,尽早发现、调整问题。
金丝雀/灰度发布步骤:
-
准备好部署各个阶段的工件,包括:构建工件,测试脚本,配置文件和部署清单文件
-
从负载均衡列表中移除掉“金丝雀”服务器
-
升级“金丝雀”应用(排掉原有流量并进行部署)
-
对应用进行自动化测试
-
将“金丝雀”服务器重新添加到负载均衡列表中(连通性和健康检查)
-
如果“金丝雀”在线使用测试成功,升级剩余的其他服务器(否则就回滚)
灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度
金丝雀/灰度发布适用场景:
-
不停止老版本,额外搞一套新版本,不同版本应用共存。
-
灰度发布中,常常按照用户设置路由权重,例如90%的用户维持使用老版本,10%的用户尝鲜新版本。
-
经常与A/B测试一起使用,用于测试选择多种方案。
1.12.3 滚动发布
滚动发布一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。
1.12.4 A/B测试
A/B测试也是同时运行两个APP环境,但与蓝绿部署完全是两码事,A/B测试是用来测试应用功能表现的方法,例如可用性、受欢迎程度、可见性等,蓝绿部署目的是安全稳定地发布新版本应用,并在必要时回滚,即蓝绿部署是一套正式环境在线,而A/B测试是两套正式环境在线。
二、安装jenkins服务
2.1 部署Jenkins
2.1.1 准备java环境,安装jdk
apt install openjdk-11-jdk -y
查看java版本
[root@jenkins ~]#java -version
openjdk version "11.0.18" 2023-01-17
OpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu120.04.1)
OpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu120.04.1, mixed mode, sharing)
2.1.2 安装Jenkins
https://mirrors.tuna.tsinghua.edu.cn/jenkins/debian-stable/
方式一:deb包方式
wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/debian-stable/jenkins_2.375.1_all.deb
dpkg -i jenkins_2.375.1_all.deb
查看配置
[root@jenkins ~]#grep "^[a-zA-Z]" /etc/default/jenkins
NAME=jenkins
JAVA_ARGS="-Djava.awt.headless=true"
PIDFILE=/var/run/$NAME/$NAME.pid
JENKINS_USER=$NAME
JENKINS_GROUP=$NAME
JENKINS_WAR=/usr/share/java/$NAME.war
JENKINS_HOME=/var/lib/$NAME
RUN_STANDALONE=true
JENKINS_LOG=/var/log/$NAME/$NAME.log
JENKINS_ENABLE_ACCESS_LOG="no"
MAXOPENFILES=8192
HTTP_PORT=8080
PREFIX=/$NAME
JENKINS_ARGS="--webroot=/var/cache/$NAME/war --httpPort=$HTTP_PORT"
修改root启动服务
vim /lib/systemd/system/jenkins.service
...
[Service]
User=root
Group=root
# 解决控制台输出中文为乱码问题
Environment="JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8"
systemctl daemon-reload
systemctl restart jenkins.service
启动参数
[root@jenkins ~]#cat /etc/default/jenkins |egrep -v "^#|^$"
NAME=jenkins
JAVA_ARGS="-Djava.awt.headless=true"
PIDFILE=/var/run/$NAME/$NAME.pid
JENKINS_USER=$NAME
JENKINS_GROUP=$NAME
JENKINS_WAR=/usr/share/java/$NAME.war
JENKINS_HOME=/var/lib/$NAME
RUN_STANDALONE=true
JENKINS_LOG=/var/log/$NAME/$NAME.log
JENKINS_ENABLE_ACCESS_LOG="no"
MAXOPENFILES=8192
HTTP_PORT=8080
PREFIX=/$NAME
JENKINS_ARGS="--webroot=/var/cache/$NAME/war --httpPort=$HTTP_PORT"
可选启动参数
JENKINS_JAVA_OPTIONS="--server -xms1g -Xmx1g -Xss512k -Xmn1g
-XX:CMSInitiatingOccupancyFraction=65
-XX:+UseFastAccessorMethods
-XX:+AggressiveOpts -XX:+UseBiasedLocking
-XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10
-XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2
-XX:PermSize=128m -XX: MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5
-XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled -Djava.awt.headless=true
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname="10.0.0.164"
方式二:war包方式
wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war-stable/2.375.1/jenkins.war
jar包启动Jenkins
java -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname="10.0.0.164" \
-jar jenkins.war &
2.1.3 访问Jenkins页面
2.1.4 安装Jenkins插件
配置国内插件地址,解决插件安装慢问题
- 修改/
var/lib/jenkins/hudson.model.UpdateCenter.xml
配置文件国内地址
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<!---清华源地址-->
<url>https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</url>
</site>
</sites>
- 重启服务
systemctl restart jenkins.service
插件下载地址:http://updates.jenkins-ci.org/download/plugins/
可将插件下载至本地/var/lib/jenkins/plugins/
目录,手动安装
说明:部分插件安装出错时可先忽略
2.1.5 创建用户
- 配置用户名信息
- 配置URL
- 配置完成
2.1.6 登录jenkins
进入首页
2.1.7 升级jenkins
# 下载war包
wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.395/jenkins.war
# 替换
\cp jenkins-2.395.war /usr/share/java/jenkins.war
# 重启服务
systemctl restart jenkins.service
验证版本
2.2 插件管理
2.2.1 插件安装目录
插件下载地址:http://updates.jenkins-ci.org/download/plugins/
[root@jenkins ~]#ll /var/lib/jenkins/plugins/
total 104616
drwxr-xr-x 86 jenkins jenkins 8192 Mar 18 18:10 ./
drwxr-xr-x 12 jenkins jenkins 4096 Mar 18 18:17 ../
drwxr-xr-x 4 jenkins jenkins 56 Mar 18 18:05 ant/
-rw-r--r-- 1 jenkins jenkins 84600 Mar 18 18:05 ant.jpi
drwxr-xr-x 4 jenkins jenkins 56 Mar 18 18:03 antisamy-markup-formatter/
-rw-r--r-- 1 jenkins jenkins 244168 Mar 18 18:03 antisamy-markup-formatter.jpi
drwxr-xr-x 4 jenkins jenkins 56 Mar 18 18:07 apache-httpcomponents-client-4-api/
-rw-r--r-- 1 jenkins jenkins 1774698 Mar 18 18:07 apache-httpcomponents-client-4-api.jpi
drwxr-xr-x 6 jenkins jenkins 77 Mar 18 18:05 bootstrap5-api/
-rw-r--r-- 1 jenkins jenkins 507001 Mar 18 18:05 bootstrap5-api.jpi
2.2.2 安装gitlab插件
- 查找gitlab、Blue Ocean插件并安装:
选择gitlab等插件
选择Blue Ocean
- 下载安装过程
- 进入Blue Ocean
创建流水线
2.3 配置jenkins权限
基于角色的权限管理,先创建角色和用户,给角色授权,然后把用户管理到角色。
2.3.1 安装Role-bases插件
基于角色的认证策略
2.3.2 创建新用户
Dashboard-->系统管理-->管理用户
2.3.3 更改认证方式
Dashboard-->系统管理-->全局安全配置
更改授权策略为Role-Based Strategy
2.3.4 管理角色
- Dashboard-->系统管理-->Manage and Assign Roles
- Manage Roles
添加角色名称并点击add,对用户进行授权
- 创建Global roles
- 创建Item roles
2.3.5 将用户分配角色
Dashboard-->系统管理-->Manage and Assign Roles-->Assign Roles
给不同用户分配不同角色权限
2.3.6 普通用户登录测试
用户成功登录后,没有系统管理权限
三、配置jenkins和gitlab关联
3.1 gitlab配置ssh key
配置Jenkins ssh免认证拉取gitlab代码
3.1.1 Jenkins服务器生成ssh key
查看并复制Jenkins服务器公钥
[root@jenkins ~]#cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDNm5clKGRrp6H6TRF0eCwu+3VQqv4uqlzUwp7SwDHu7L2zTEEQt4
FMLjHNgq4H13snWuAcBRww3gwI1i1oUjK6HR/86GmmVd189DnyZB8UoRbCuq+OhJB6cK2TipJpr5nKc1lXuABWsjHP
R7MEFsDvxwi49MZW0SgePnHbUDPNTaFpabxQw2pASv3oCjLiEcMGcZd/ndV4gKzoZQMd2jmCrbmttaiLvss7Jfnain
Pw15XOE8fcgNMdKJJEXtHnzlfKATe2nlbBq2fcB2L2NvGKGwBAtNu86ysV6EPz2OdVaLoOuv2J+gRwyQxsKRrclYxx
AE3CY/tz+bvDzxOryeiT5m8gu0rwDRepsI9iLLkXVe6No/T5Bg9L9PHTpVrBvDRnCodnCYbVhmpY1opKK7cz6iN+B1
70Z+C5xW+J7ecBHisyuiE7Itfs13ikemqx2uKv+oMFKOVnY9dNh7IiekCTMXP5o2eRdZKXp5MmBiWe1UdCVp1s6uVc
SvlNK6Jj3xs= root@jenkins
注意:设置忽略远程访问告警
echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config
3.1.2 登录gitlab页面
3.1.3 粘贴Jenkins服务器公钥
3.1.4 测试ssh key
免密拉取gitlab代码
[root@jenkins opt]#git clone git@10.0.0.163:test-service/test-project.git
Cloning into 'test-project'...
time="2023-03-18T22:44:20+08:00" level=info msg="SSL_CERT_DIR is configured" ssl_cert_dir=/opt/gitlab/embedded/ssl/certs/
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 9 (delta 0), reused 9 (delta 0), pack-reused 0
Receiving objects: 100% (9/9), done.
3.2 Jenkins配置ssh key
Dashboard-->系统管理-->Manage Credentials-->全局-->Add Credentials
添加Jenkins server服务器私钥
2.2.1 查看凭据
3.3 验证Jenkins关联gitlab
3.3.1 Jenkins创建project
3.3.2 配置gitlab仓库
填写gitlab 仓库URL,使用ssh认证,根据实际选择分支
3.3.3 立即构建
3.3.4 Jenkins服务器验证数据
Jenkins自动下载gitlab仓库代码,存放目录为/var/lib/jenkins/workspace/
[root@jenkins opt]#tree /var/lib/jenkins/workspace/
/var/lib/jenkins/workspace/
└── test-project
├── README.md
└── index.html
1 directories, 2 files
3.3.5 将代码部署至后端服务器
# backend server
tomcat1 10.0.0.165
tomcat2 10.0.0.166
- 编写shell
Build Steps
shell内容:
cd /var/lib/jenkins/workspace/test-project
tar czvf code.tar.gz ./*
scp code.tar.gz 10.0.0.165:/var/lib/tomcat9/webapps/
scp code.tar.gz 10.0.0.166:/var/lib/tomcat9/webapps/
ssh 10.0.0.165 "systemctl stop tomcat9.service && rm -rf /var/lib/tomcat9/webapps/myapp/* && cd /var/lib/tomcat9/webapps && tar xvf code.tar.gz -C /var/lib/tomcat9/webapps/myapp/"
ssh 10.0.0.166 "systemctl stop tomcat9.service && rm -rf /var/lib/tomcat9/webapps/myapp/* && cd /var/lib/tomcat9/webapps && tar xvf code.tar.gz -C /var/lib/tomcat9/webapps/myapp/"
ssh 10.0.0.165 "systemctl start tomcat9.service"
ssh 10.0.0.166 "systemctl start tomcat9.service"
- 执行构建
- 配置haproxy
...
listen tomcat_8080
mode http
bind 10.0.0.167:80
server 10.0.0.165 10.0.0.165:8080 check inter 3s fall 3 rise 5
server 10.0.0.166 10.0.0.166:8080 check inter 3s fall 3 rise 5
- 浏览器验证
更新index.html为3333,执行构建
后端网页同步更新
注意:若Jenkins控制台输出中文为乱码
在jenkins.service中添加Environment="JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8"
,重启Jenkins服务
3.4 构建触发器(钩子)
构建触发器(webhook),是一个HTTP回调,其用于在向gitlab提交代码后能够触发Jenkins自动执行代码构建操作。
以下为新建一个develop分支,只有开发人员向develop分支提交代码时才会触发代码构建,而向主分支提交的代码不会自动构建,需要运维人员手动部署代码到生成环境。
3.4.1 gitlab新建develop分支
3.4.2 gitlab新建分支
3.4.3 Jenkins安装插件
下载安装插件Gitlab Webhook和Gitlab Authentication
注意事项:https://www.jenkins.io/security/advisories/
3.4.4 Jenkins修改登录认证方式
授权策略为登录用户可以做任何事
若Jenkins新版本没有配置CSRF(跨站请求伪造保护)禁用的选项,则需要在脚本命令行执行下面代码:
hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true
3.4.5 Jenkins新建develop job
3.4.6 Jenkins构建shell命令
配置shell脚本
执行输出
3.4.7 Jenkins配置构建触发器
生成token认证
[root@jenkins ~]#openssl rand -hex 12
0e2db834fe246a8df61f030a
3.4.8 Jenkins验证分支job配置文件
[root@jenkins ~]#vim /var/lib/jenkins/jobs/develop/config.xml
...
<authToken>0e2db834fe246a8df61f030a</authToken>
<triggers/>
<concurrentBuild>false</concurrentBuild>
<builders>
<hudson.tasks.Shell>
<command>echo $USER && pwd
cd /opt
pwd</command>
3.4.9 测试触发并验证远程触发构建
更新index.html文件
浏览器访问或curl命令访问测试
curl http://10.0.0.164:8080/job/develop/build?token=0e2db834fe246a8df61f030a
3.4.10 Jenkins验证job自动构建
index.html内容更新
[root@jenkins jenkins]#cat /var/lib/jenkins/workspace/develop/index.html
<h1>11111111</h1>
<h1>22222222</h1>
<h1>33333333</h1>
<h1>44444444</h1>
3.4.11 gitlab配置系统钩子
gitlab配置URL
3.4.12 测试钩子可用性
测试结果
说明:若测试不成功,在脚本命令行执行下面代码:
hudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true
3.4.13 Jenkins执行shell命令
配置shell脚本内容
cd /var/lib/jenkins/workspace/develop
tar czvf code.tar.gz ./*
scp code.tar.gz 10.0.0.165:/var/lib/tomcat9/webapps/
scp code.tar.gz 10.0.0.166:/var/lib/tomcat9/webapps/
ssh 10.0.0.165 "systemctl stop tomcat9.service && rm -rf /var/lib/tomcat9/webapps/myapp/* && cd /var/lib/tomcat9/webapps && tar xvf code.tar.gz -C /var/lib/tomcat9/webapps/myapp/"
ssh 10.0.0.166 "systemctl stop tomcat9.service && rm -rf /var/lib/tomcat9/webapps/myapp/* && cd /var/lib/tomcat9/webapps && tar xvf code.tar.gz -C /var/lib/tomcat9/webapps/myapp/"
ssh 10.0.0.165 "systemctl start tomcat9.service"
ssh 10.0.0.166 "systemctl start tomcat9.service"
执行构建,查看结果
3.4.14 gitlab develop分支测试提交代码
# 克隆代码至本地
git clone -b develop http://10.0.0.163/test-service/test-project.git
# 修改代码
cd test-project/
echo "<h1>55555555</h1>" >> index.html
# 提交代码至暂存区
git add index.html
# 提交代码至本地仓库
[root@gitlab test-project]#git commit -m 'v5'
[develop 5d79393] v5
1 file changed, 1 insertion(+)
# 上传代码至仓库,同时触发Jenkins自动构建
[root@gitlab test-project]#git push
Username for 'http://10.0.0.163': areke
Password for 'http://areke@10.0.0.163':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 301 bytes | 301.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote:
remote: To create a merge request for develop, visit:
remote: http://10.0.0.163/test-service/test-project/-/merge_requests/new?merge_request%5Bsource_branch%5D=develop
remote:
To http://10.0.0.163/test-service/test-project.git
0fd95a9..5d79393 develop -> develop
3.4.15 Jenkins验证develop job自动构建
验证后端网页版本更新
3.5 构建后项目关联
用于多个job相互关联,需要串行执行多个job的场景,可以安装插件触发执行其他project
3.5.1 安装插件
Parameterized Trigger plugin
3.5.2 配置构建后操作
需先创建test-job1的Project
3.5.3 验证构建后操作
四、创建一个pipeline项目实现自动构建并部署
4.1 pipeline
官网:https://www.jenkins.io/2.0/
pipline:https://www.jenkins.io/zh/doc/book/pipeline/
pipeline是帮助Jenkins实现CI到CD转变的重要角色,是运行在Jenkins 2.X 版本的核心插件,pipeline是一套运行于Jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程,从而实现单个任务很难实现的复杂流程编排和任务可视化,Pipeline的实现方式是一套Groovy DSL,任何发布流程都可以表述为一段Groovy脚本。
4.1.1 pipeline语法
- Stage
阶段,一个pipeline可以划分为若干个stage,每个stage都是一个操作步骤,如clone代码、代码编译、代码测试和代码部署,stage是一个逻辑分组,可以跨多个node执行。
- Node
节点,每个node都是一个Jenkins节点,可以是Jenkins master,也可以是Jenkins agent,node是执行step的具体服务器。
- Step
步骤,step是Jenkins pipeline最基本的操作单元,从在服务器创建目录到构建容器镜像,由各类Jenkins插件提供实现,一个stage中可以有多个step,如:sh、make
4.1.2 pipeline优势
- 可持续性
Jenkins的重启或者中断后不影响已经执行的pipeline job
- 支持暂停
pipeline可以选择停止并等待人工输入或批准后再继续执行
- 可扩展
通过groovy的编程更容易的扩展插件
- 并行执行
通过grovy脚本可以实现step、stage间的并行执行,和更复杂的相互依赖关系
4.1.3 pipeline示例
- 生成流水线脚本语法
- 流水线脚本
node {
stage("colne代码"){
echo "clone代码"
git branch: 'develop', credentialsId: 'ff41be5b-c016-45da-938c-9b738cc1ce9d', url: 'git@10.0.0.163:test-service/test-project.git'
}
stage("代码构建"){
echo "代码构建"
}
stage("代码测试"){
echo "代码测试"
}
stage("代码部署"){
echo "代码部署"
}
}
- 流水线执行结果
查看日志
4.2 准备环境
4.2.1 项目示例
将代码部署到web服务器
主机清单
10.0.0.160 Gitlab
10.0.0.164 Jenkins
10.0.0.165 Jenkins-node1
10.0.0.166 Jenkins-node2
10.0.0.167 Maven
10.0.0.168 Sonarqube
10.0.0.175 Web1
10.0.0.176 Web2
10.0.0.177 Web3
10.0.0.189 LB1
10.0.0.190 LB2
4.2.2 gitlab服务器
10.0.0.160
参考第一章节部分:一、安装gitlab服务
4.2.3 Jenkins服务器
10.0.0.164
参考第二章节部分:二、安装jenkins服务
4.2.4 web服务器
10.0.0.175-177
- 安装tomcat
apt install -y tomcat9
- 测试
hostname -I > /var/lib/tomcat9/webapps/ROOT/index.html
访问网页
[root@lb1 ~]#curl 10.0.0.175:8080
10.0.0.175
[root@lb1 ~]#curl 10.0.0.176:8080
10.0.0.176
[root@lb1 ~]#curl 10.0.0.177:8080
10.0.0.177
4.2.5 LoadBalance服务器
10.0.0.189-190
- 安装haproxy、keepalived、socat
apt install -y haproxy socat keepalived
- 配置
- 启用内核参数
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# 配置生效
sysctl -p
- 配置keepalived
# 配置keepalived.conf
[root@lb1 ~]#cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id 10.0.0.189 # 本机IP,LB2为10.0.0.190
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.0.18
}
vrrp_script chk_haproxy {
script "/etc/keepalived/chk_haproxy.sh"
interval 1
timeout 2
weight -30
fall 3
rise 5
}
vrrp_instance haproxy {
state MASTER # LB2设置为BACKUP
interface eth0
virtual_router_id 51
priority 100 # LB2可设置优先级80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.188/24 dev eth0 label eth0:1
}
track_script {
chk_haproxy
}
}
# 编写haproxy检测脚本
[root@lb1 ~]#cat /etc/keepalived/chk_haproxy.sh
#!/bin/bash
/usr/bin/killall -0 haproxy
#添加执行权限
[root@lb1 ~]# chmod a+x /etc/keepalived/chk_haproxy.sh
- 配置haproxy
[root@lb1 ~]#cat /etc/haproxy/haproxy.cfg
# 在global配置应该如下
# stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
# 末尾增加如下配置
listen Web_80
bind 10.0.0.188:80
mode http
log global
server 10.0.0.175 10.0.0.175:8080 check inter 3s fall 3 rise 5
server 10.0.0.176 10.0.0.176:8080 check inter 3s fall 3 rise 5
server 10.0.0.177 10.0.0.177:8080 check inter 3s fall 3 rise 5
重启
systemctl restart keepalived.service haproxy.service
- 测试
[root@jenkins ~]#curl 10.0.0.188
10.0.0.175
[root@jenkins ~]#curl 10.0.0.188
10.0.0.176
[root@jenkins ~]#curl 10.0.0.188
10.0.0.177
# 将175服务器下线
[root@lb1 ~]#echo "set weight Web_80/10.0.0.175 0"|socat stdio /run/haproxy/admin.sock
# 测试访问后端服务器
[root@lb1 ~]#curl 10.0.0.188
10.0.0.176
[root@lb1 ~]#curl 10.0.0.188
10.0.0.177
4.2.6 Sonarqube服务器
部署sonarqube 10.0版本(10.0.0.168)
官网:https://www.sonarsource.com/products/sonarqube/
4.2.6.1 基础环境依赖
https://docs.sonarqube.org/10.0/requirements/prerequisites-and-overview/
- Java
- Database:
PostgreSQL
.
Oracle
说明:7.9.x 版本以上不支持MySQL
- 系统及内核参数
# 使用普通账户启动sonarqube
useradd -s /bin/bash -m sonarqube
# 修改内核参数
echo "vm.max_map_count=524288" >> /etc/sysctl.conf
echo "fs.file-max=131072" >> /etc/sysctl.conf
# 执行生效
sysctl -p
# 修改limits.conf
echo "sonarqube - nofile 131072" >> /etc/security/limits.conf
echo "sonarqube - nproc 8192" >> /etc/security/limits.conf
# 重启服务器后,切换sonarqube用户查看
sonarqube@sonarqube:~$ ulimit -n
131072
sonarqube@sonarqube:~$ ulimit -u
8192
4.2.6.2 安装JDK17
apt-cache madison openjdk-17-jdk
apt install -y openjdk-17-jdk
#查看java版本
[root@sonarqube ~]#java -version
openjdk version "17.0.7" 2023-04-18
OpenJDK Runtime Environment (build 17.0.7+7-Ubuntu-0ubuntu120.04)
OpenJDK 64-Bit Server VM (build 17.0.7+7-Ubuntu-0ubuntu120.04, mixed mode, sharing)
4.2.6.3 部署PostgreSQL服务器
apt-cache madison postgresql-12
apt install -y postgresql-12
# 初始化并启动
[root@sonarqube ~]#su - postgres
postgres@sonarqube:~$ /usr/lib/postgresql/12/bin/pg_ctl init -D /var/lib/postgresql/12/main
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "C.UTF-8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".
Data page checksums are disabled.
creating directory /var/lib/postgresql/12/main ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Asia/Shanghai
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
initdb: warning: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
Success. You can now start the database server using:
/usr/lib/postgresql/12/bin/pg_ctl -D /var/lib/postgresql/12/main -l logfile start
# 启动服务
postgres@sonarqube:~$ /usr/lib/postgresql/12/bin/pg_ctl -D /var/lib/postgresql/12/main -l logfile start
# 登录数据库
postgres@sonarqube:~$ psql
psql (12.15 (Ubuntu 12.15-0ubuntu0.20.04.1))
Type "help" for help.
#创建数据库并进行授权普通用户访问
##创建数据库
postgres=# create database sonar;
CREATE DATABASE
## 创建用户
postgres=# create user sonar with encrypted password '123456';
CREATE ROLE
## 授权
postgres=# grant all privileges on database sonar to sonar;
GRANT
## 执行变更
postgres=# alter database sonar owner to sonar;
ALTER DATABASE
## 退出
postgres=# \q
postgres@sonarqube:~$
# 修改监听地址
postgres@sonarqube:~$ vim /var/lib/postgresql/12/main/postgresql.conf
...
listen_addresses = '*'
# 开启远程访问
postgres@sonarqube:~$ vim /var/lib/postgresql/12/main/pg_hba.conf
# IPv4 local connections:
host all all 127.0.0.1/32 trust
host all all 0.0.0.0/0 md5 # 新增一条配置
# 配置环境变量
postgres@sonarqube:~$ cd ~
postgres@sonarqube:~$ cat >> .profile <<EOF
PATH=\$PATH:/usr/lib/postgresql/12/bin
export PATH
EOF
postgres@sonarqube:~$ source .profile
# 重启服务
## 重启
postgres@sonarqube:~$ /usr/lib/postgresql/12/bin/pg_ctl -D /var/lib/postgresql/12/main -l logfile restart
## 关闭
postgres@sonarqube:~$ /usr/lib/postgresql/12/bin/pg_ctl -D /var/lib/postgresql/12/main -l logfile stop
## 启动
postgres@sonarqube:~$ /usr/lib/postgresql/12/bin/pg_ctl -D /var/lib/postgresql/12/main -l logfile start
# 远程连接测试
[root@sonarqube ~]#psql -U sonar -h 10.0.0.168
Password for user sonar:
psql (12.15 (Ubuntu 12.15-0ubuntu0.20.04.1))
Type "help" for help.
sonar=>
设置开机自启动
[root@sonarqube ~]#cat /etc/rc.local
#!/bin/bash
su - postgres -c "/usr/lib/postgresql/12/bin/pg_ctl -D /var/lib/postgresql/12/main -l logfile start"
exit 0
4.2.6.4 部署sonarqube
下载地址: https://www.sonarsource.com/products/sonarqube/downloads/
# 下载
mkdir /apps
cd /apps
wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-10.0.0.68432.zip
unzip sonarqube-10.0.0.68432.zip
ln -s sonarqube-10.0.0.68432 sonarqube
chown -R sonarqube:sonarqube /apps/
# 配置postgresql数据库连接信息
su - sonarqube
echo "sonar.jdbc.username=sonar" >> /apps/sonarqube/conf/sonar.properties
echo "sonar.jdbc.password=123456" >> /apps/sonarqube/conf/sonar.properties
echo "sonar.jdbc.url=jdbc:postgresql://10.0.0.168/sonar" >> /apps/sonarqube/conf/sonar.properties
# 启动sonar
sonarqube@sonarqube:~$ /apps/sonarqube/bin/linux-x86-64/sonar.sh start
/usr/bin/java
Starting SonarQube...
Started SonarQube.
# 查看日志
sonarqube@sonarqube:/apps/sonarqube$ tail -f /apps/sonarqube/logs/nohup.log
2023.07.02 11:24:45 INFO app[][o.s.a.ProcessLauncherImpl] Launch process[COMPUTE_ENGINE] from [/apps/sonarqube-10.0.0.68432]: /usr/lib/jvm/java-17-openjdk-amd64/bin/java -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/apps/sonarqube-10.0.0.68432/temp -XX:-OmitStackTraceInFastThrow --add-opens=java.base/java.util=ALL-UNNAMED --add-exports=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.management/sun.management=ALL-UNNAMED --add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED -Dcom.redhat.fips=false -Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError -Dhttp.nonProxyHosts=localhost|127.*|[::1] -cp ./lib/sonar-application-10.0.0.68432.jar:/apps/sonarqube-10.0.0.68432/lib/jdbc/postgresql/postgresql-42.5.1.jar org.sonar.ce.app.CeServer /apps/sonarqube-10.0.0.68432/temp/sq-process3897498440763538588properties
2023.07.02 11:24:45 WARN app[][startup] ####################################################################################################################
2023.07.02 11:24:45 WARN app[][startup] Default Administrator credentials are still being used. Make sure to change the password or deactivate the account.
2023.07.02 11:24:45 WARN app[][startup] ####################################################################################################################
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by org.sonar.process.PluginSecurityManager (file:/apps/sonarqube-10.0.0.68432/lib/sonar-application-10.0.0.68432.jar)
WARNING: Please consider reporting this to the maintainers of org.sonar.process.PluginSecurityManager
WARNING: System::setSecurityManager will be removed in a future release
2023.07.02 11:24:49 INFO app[][o.s.a.SchedulerImpl] Process[ce] is up
2023.07.02 11:24:49 INFO app[][o.s.a.SchedulerImpl] SonarQube is operational
验证sonarqube
设置开机自启
[root@sonarqube ~]#vim /etc/rc.local
#!/bin/bash
su - postgres -c "/usr/lib/postgresql/12/bin/pg_ctl -D /var/lib/postgresql/12/main -l logfile start"
su - sonarqube -c "/apps/sonarqube/bin/linux-x86-64/sonar.sh start"
exit 0
4.2.6.5 访问Sonarqube Web页面
http://10.0.0.168:9000,用户名、密码都是admin
进入首页
安装中文插件
查看中文
4.2.7 部署sonar-scanner扫描器
官方文档:https://docs.sonarqube.org/latest/analyzing-source-code/scanners/sonarscanner/
下载地址:https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/
4.2.7.1 Jenkins服务器部署sonar-scanner
cd /usr/local/src
wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856-linux.zip
unzip sonar-scanner-cli-4.8.0.2856-linux.zip
ln -s sonar-scanner-4.8.0.2856-linux /usr/local/src/sonar-scanner
ln -s /usr/local/src/sonar-scanner/bin/sonar-scanner* /usr/local/bin/
# 添加sonarqube服务器信息
[root@jenkins src]#vim /usr/local/src/sonar-scanner/conf/sonar-scanner.properties
#----- Default SonarQube server
sonar.host.url=http://10.0.0.168:9000
#----- Default source code encoding
sonar.sourceEncoding=UTF-8
4.2.7.2 准备测试项目
- 关闭强制认证
- 准备测试项目
cd /opt
unzip sonar-examples-master.zip
cd /opt/sonar-examples-master/projects/languages/php/php-sonar-runner
# 编辑配置项目信息
[root@jenkins php-sonar-runner]#cat sonar-project.properties
# Required metadata
sonar.projectKey=org.sonarqube:php-simple-sq-scanner # 自定义key
sonar.projectName=PHP::SimpleProject::SonarQubeScanner # 项目名称,需要提前在web创建该项目
sonar.projectVersion=1.0 # 项目版本
# Comma-separated paths to directories with sources (required)
sonar.sources=src # 源代码目录
# Language
sonar.language=php # 代码语言
# Encoding of the source files
sonar.sourceEncoding=UTF-8 # 编码格式
- 新建项目
- 创建项目
- 创建项目令牌
- 设置令牌过期时间
- 选择分析代码语言,生成sonar-scanner执行命令
4.2.7.3 执行扫描分析命令
# 进入待扫描目录,复制sonar-scanner执行命令进行扫描
[root@jenkins php-sonar-runner]#pwd
/opt/sonar-examples-master/projects/languages/php/php-sonar-runner
[root@jenkins php-sonar-runner]#sonar-scanner \
-Dsonar.projectKey=PHP::SimpleProject::SonarQubeScanner \
-Dsonar.sources=. \
-Dsonar.host.url=http://10.0.0.168:9000 \
-Dsonar.token=sqp_af5455edc6430bf9c6065e300d758441c7be2589
查看执行结果
...
INFO: ------------- Run sensors on project
INFO: Sensor Analysis Warnings import [csharp]
INFO: Sensor Analysis Warnings import [csharp] (done) | time=1ms
INFO: Sensor Zero Coverage Sensor
INFO: Sensor Zero Coverage Sensor (done) | time=30ms
INFO: SCM Publisher No SCM system was detected. You can use the 'sonar.scm.provider' property to explicitly specify it.
INFO: CPD Executor Calculating CPD for 1 file
INFO: CPD Executor CPD calculation finished (done) | time=30ms
INFO: Analysis report generated in 90ms, dir size=142.4 kB
INFO: Analysis report compressed in 9ms, zip size=24.1 kB
INFO: Analysis report uploaded in 36ms
INFO: ANALYSIS SUCCESSFUL, you can find the results at: http://10.0.0.168:9000/dashboard?id=PHP%3A%3ASimpleProject%3A%3ASonarQubeScanner
INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
INFO: More about the report processing at http://10.0.0.168:9000/api/ce/task?id=AYkVbgu4jnYPb4OTsyQA
INFO: Analysis total time: 13.567 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 15.584s
INFO: Final Memory: 19M/67M
INFO: ------------------------------------------------------------------------
4.2.7.4 验证Web页面扫描结果
4.2.8 Jenkins执行代码扫描
4.2.8.1 安装SonarQube Scanner插件
4.2.8.2 添加Sonarqube Server URL
自定义SonarQube Server名称,配置Server URL
4.2.8.3 添加sonarqube scanner扫描器
- 手动添加scanner扫描器
自定义名称,sonar-scanner目录路径
- 自动安装
也可选择自动安装
4.2.8.4 配置扫描
sonarqube网页新建job1-web项目,生成token信息,配置信息参考如下:
sonar.projectKey=job1-web
sonar.projectName=job1-web
sonar.projectVersion=1.0
sonar.sources=./
sonar.language=php
sonar.sourceEncoding=UTF-8
sonar.token=sqp_f051847ec08d00e6b057af64327858a7e77adf61
Jenkins选择项目,增加配置步骤选择Execute SonarQube Scanner,配置扫描信息
4.2.8.5 验证扫描结果
构建项目,查看构建日志
查看项目构建历史,可跳转SonarQube查看扫描结果
扫描结果
4.3 创建自动构建项目
4.3.1 编写部署脚本
对不同代码分支、不同分组的web服务器进行自动部署或回退操作
#!/bin/bash
DATE=`date +%Y-%m-%d_%H-%M-%S`
METHOD=$1
BRANCH=$2
GROUP_LIST=$3
function IP_list(){
if [[ ${GROUP_LIST} == "GROUP1" ]];then
Server_IP="10.0.0.175"
echo ${Server_IP}
ssh root@10.0.0.189 ""echo set weight Web_80/10.0.0.175 0" | socat stdio /run/haproxy/admin.sock"
ssh root@10.0.0.190 ""echo set weight Web_80/10.0.0.175 0" | socat stdio /run/haproxy/admin.sock"
elif [[ ${GROUP_LIST} == "GROUP2" ]];then
Server_IP="10.0.0.176 10.0.0.177"
echo ${Server_IP}
ssh root@10.0.0.189 ""echo set weight Web_80/10.0.0.175 0" | socat stdio /run/haproxy/admin.sock"
ssh root@10.0.0.190 ""echo set weight Web_80/10.0.0.175 0" | socat stdio /run/haproxy/admin.sock"
elif [[ ${GROUP_LIST} == "GROUP3" ]];then
Server_IP="10.0.0.175 10.0.0.176 10.0.0.177"
echo ${Server_IP}
fi
}
function clone_code(){
echo "即将开始clone ${BRANCH}分支的代码"
cd /data/git/web/ && rm -rf test-project && git clone -b ${BRANCH} git@10.0.0.160:test-service/test-project.git
echo "${BRANCH}分支代码cllone完成,即开始代码扫描"
#tar czvf myapp.tar.gz ./index.html
#echo "代码编译完成,即将开始分发部署包"
}
function scanner_code(){
cd /data/git/web/test-project && /usr/local/src/sonar-scanner/bin/sonar-scanner \
-Dsonar.projectKey=job1-web \
-Dsonar.sources=. \
-Dsonar.host.url=http://10.0.0.168:9000 \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.token=sqp_f051847ec08d00e6b057af64327858a7e77adf61
echo "代码扫描完成,请打开sonarqube查看扫描结果"
}
function code_maven(){
echo "cd /data/git/web/test-project && mvn clean package -Dmaven.test.skip=true"
echo "代码编译完成"
}
function make_zip(){
cd /data/git/web/test-project && zip -r code.zip ./index.html
echo "代码打包完成"
}
down_node(){
for node in ${Server_IP};do
ssh root@10.0.0.189 ""echo set weight Web_80/${node} 0" | socat stdio /run/haproxy/admin.sock"
echo "${node} 从负载均衡10.0.0.189下线成功"
ssh root@10.0.0.190 ""echo set weight Web_80/${node} 0" | socat stdio /run/haproxy/admin.sock"
echo "${node} 从负载均衡10.0.0.190下线成功"
done
}
function scp_zipfile(){
for node in ${Server_IP};do
scp /data/git/web/test-project/code.zip root@${node}:/var/lib/tomcat9/webdir/code-${DATE}.zip
ssh root@${node} "unzip /var/lib/tomcat9/webdir/code-${DATE}.zip -d /var/lib/tomcat9/webdir/code-${DATE} && rm -rf /var/lib/tomcat9/webapps/myapp && ln -sv /var/lib/tomcat9/webdir/code-${DATE} /var/lib/tomcat9/webapps/myapp && rm -rf /var/lib/tomcat9/webdir/code-${DATE}.zip"
done
}
function stop_tomcat(){
for node in ${Server_IP};do
ssh root@${node} "systemctl stop tomcat9"
done
}
function start_tomcat(){
for node in ${Server_IP};do
ssh root@${node} "systemctl start tomcat9"
#sleep 5
done
}
function web_test(){
sleep 10
for node in ${Server_IP};do
NUM=`curl -s -I -m 10 -o /dev/null -w %{http_code} http://${node}:8080/myapp/index.html`
if [[ ${NUM} -eq 200 ]];then
echo "${node} myapp URL 测试通过,即将添加到负载"
add_node ${node}
else
echo "${node} 测试失败,请检查该服务器是否成功启动tomcat"
fi
done
}
function add_node(){
node=$1
if [[ ${GROUP_LIST} == "GROUP3" ]];then
ssh root@10.0.0.189 ""echo set weight Web_80/10.0.0.175 1" | socat stdio /run/haproxy/admin.sock"
echo ${node},"-----> 10.0.0.189"
ssh root@10.0.0.190 ""echo set weight Web_80/10.0.0.175 1" | socat stdio /run/haproxy/admin.sock"
echo ${node},"-----> 10.0.0.190"
fi
##########################################
if [ ${node} == "10.0.0.175" ];then
echo "灰度部署环境服务器-->10.0.0.175 部署完毕,请进行代码测试!"
else
ssh root@10.0.0.189 ""echo set weight Web_80/${node} 1" | socat stdio /run/haproxy/admin.sock"
echo ${node},"-----> 10.0.0.189"
ssh root@10.0.0.190 ""echo set weight Web_80/${node} 1" | socat stdio /run/haproxy/admin.sock"
echo ${node},"-----> 10.0.0.190"
fi
}
function rollback_last_version(){
for node in ${Server_IP};do
echo $node
NOW_VERSION=`ssh root@${node} ""/bin/ls -l -rt /var/lib/tomcat9/webapps/ | awk -F"->" '{print $2}' | tail -n1""`
NOW_VERSION=`basename ${NOW_VERSION}`
echo $NOW_VERSION,"NOW_VERSION"
NAME=`ssh root@${node} ""ls -l -rt /var/lib/tomcat9/webdir/ | grep -B 1 ${NOW_VERSION} | head -n1 | awk '{print $9}'""`
echo $NAME,""NAME
ssh root@${node} "rm -rf /var/lib/tomcat9/webapps/myapp && ln -sv /var/lib/tomcat9/webdir/${NAME} /var/lib/tomcat9/webapps/myapp"
done
}
function delete_history_version(){
for node in ${Server_IP};do
NUM=`ssh root@${node} ""/bin/ls -l -d -rt /var/lib/tomcat9/webdir/code-* | wc -l""`
echo "${node} --> ${NUM}"
if [ ${NUM} -gt 5 ];then
NAME=`ssh root@${node} ""/bin/ls -l -d -rt /var/lib/tomcat9/webdir/code-* | head -n1 | awk '{print $9}'""`
ssh root@${node} "rm -rf ${NAME}"
echo "${node} 删除历史版本${NAME}成功!"
fi
done
}
main(){
case $1 in
deploy)
IP_list;
clone_code;
scanner_code;
make_zip;
down_node;
stop_tomcat;
scp_zipfile;
start_tomcat;
web_test;
delete_history_version;
;;
rollback_last_version)
IP_list;
#echo ${Server_IP}
down_node;
stop_tomcat;
rollback_last_version;
start_tomcat;
web_test;
;;
esac
}
main $1 $2 $3
4.3.2 设置构建参数
3.4.13
4.3.3 设置代码仓库路径,访问凭证
凭证设置可参考:3.1 gitlab配置ssh key
4.3.4 编写构建步骤
编写shell执行命令
4.4 自动构建测试
4.4.1 clone代码至本地
[root@deploy opt]#git clone -b develop git@10.0.0.160:test-service/test-project.git
Cloning into 'test-project'...
time="2023-07-05T10:45:14+08:00" level=info msg="SSL_CERT_DIR is configured" ssl_cert_dir=/opt/gitlab/embedded/ssl/certs/
remote: Enumerating objects: 46, done.
remote: Counting objects: 100% (37/37), done.
remote: Compressing objects: 100% (32/32), done.
remote: Total 46 (delta 10), reused 17 (delta 5), pack-reused 9
Receiving objects: 100% (46/46), 5.33 KiB | 5.33 MiB/s, done.
Resolving deltas: 100% (10/10), done.
4.4.2 修改代码并上传仓库
[root@deploy test-project]#cd test-project
[root@deploy test-project]#echo "<h1>1111111111</h1>" >> index.html
[root@deploy test-project]#git add index.html
[root@deploy test-project]#git commit -m 'v1'
[develop deac327] v1
1 file changed, 1 insertion(+), 13 deletions(-)
[root@deploy test-project]#git push
time="2023-07-05T11:01:34+08:00" level=info msg="SSL_CERT_DIR is configured" ssl_cert_dir=/opt/gitlab/embedded/ssl/certs/
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 289 bytes | 289.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for develop, visit:
remote: http://10.0.0.160/test-service/test-project/-/merge_requests/new?merge_request%5Bsource_branch%5D=develop
remote:
To 10.0.0.160:test-service/test-project.git
3e85554..deac327 develop -> develop
查看gitlab仓库
4.4.3 升级测试服务器
选择构建参数,执行构建
查看构建日志
4.4.4 验证web测试服务器
访问升级后的web服务器(10.0.0.175)
测试服务器已下线
4.4.5 访问web网页
配置hots域名解析
10.0.0.188 www.web.com
4.4.6 升级其他web服务器
构建参数,选择GROUP2
完成升级,后端服务器已全上线
4.4.7 验证web页面
4.5 实现pipeline构建
编写Jenkinsfile,将所有web服务器进行升级部署,可根据其他需求进行修改
pipeline {
agent any
environment {
Server_IP = '10.0.0.175,10.0.0.176,10.0.0.177'
DATE = sh(script: 'date +%Y-%m-%d_%H-%M-%S', returnStdout: true).trim()
}
stages {
stage('clone代码') {
steps {
echo "即将开始clone 代码"
git branch: 'develop', credentialsId: '0cab95c5-cb24-4bb6-b03e-bc6576f8dd08', url: 'git@10.0.0.160:test-service/test-project.git'
}
}
stage('代码扫描') {
steps {
echo "代码扫描"
sh '''cd /var/lib/jenkins/workspace/test-pipline && /usr/local/src/sonar-scanner/bin/sonar-scanner \\
-Dsonar.projectKey=job1-web \\
-Dsonar.sources=. \\
-Dsonar.host.url=http://10.0.0.168:9000 \\
-Dsonar.sourceEncoding=UTF-8 \\
-Dsonar.token=sqp_f051847ec08d00e6b057af64327858a7e77adf61'''
}
}
stage('代码打包') {
steps {
echo "代码打包"
sh 'cd /var/lib/jenkins/workspace/test-pipline && zip -r code.zip ./index.html'
}
}
stage('后端服务器下线') {
steps {
echo '后端服务器下线'
script {
for (def node in Server_IP.split(',')){
sh """
ssh root@10.0.0.189 ""echo set weight Web_80/${node} 0" | socat stdio /run/haproxy/admin.sock"
echo "${node} 从负载均衡10.0.0.189下线成功"
ssh root@10.0.0.190 ""echo set weight Web_80/${node} 0" | socat stdio /run/haproxy/admin.sock"
echo "${node} 从负载均衡10.0.0.190下线成功"
"""
}
}
}
}
stage('stop tomcat') {
steps {
echo 'stop tomcat'
script {
for (def node in Server_IP.split(',')){
sh """
ssh root@${node} "systemctl stop tomcat9"
"""
}
}
}
}
stage('scp_zipfile') {
steps {
echo 'scp_zipfile'
script {
for (def node in Server_IP.split(',')){
sh """
scp /var/lib/jenkins/workspace/test-pipline/code.zip root@${node}:/var/lib/tomcat9/webdir/code-${env.DATE}.zip
ssh root@${node} "unzip /var/lib/tomcat9/webdir/code-${env.DATE}.zip -d /var/lib/tomcat9/webdir/code-${env.DATE} && rm -rf /var/lib/tomcat9/webapps/myapp && ln -sv /var/lib/tomcat9/webdir/code-${env.DATE} /var/lib/tomcat9/webapps/myapp && rm -rf /var/lib/tomcat9/webdir/code-${env.DATE}.zip"
"""
}
}
}
}
stage('start tomcat') {
steps {
echo 'start tomcat'
script {
for (def node in Server_IP.split(',')){
sh """
ssh root@${node} "systemctl start tomcat9"
"""
}
}
}
}
stage('web_test') {
steps {
echo 'web_test'
sleep 10
script {
for (def node in Server_IP.split(',')){
sh """
NUM=\$(curl -s -I -m 10 -o /dev/null -w %{http_code} http://${node}:8080/myapp/index.html)
if [ \${NUM} -eq 200 ];then
echo "${node} myapp URL 测试通过,即将添加到负载"
ssh root@10.0.0.189 ""echo set weight Web_80/${node} 1" | socat stdio /run/haproxy/admin.sock"
echo "10.0.0.189"
ssh root@10.0.0.190 ""echo set weight Web_80/${node} 1" | socat stdio /run/haproxy/admin.sock"
echo "10.0.0.190"
else
echo "${node} 测试失败,请检查该服务器是否成功启动tomcat"
fi
"""
}
}
}
}
stage('delete_history_version') {
steps {
echo 'delete history version'
script {
for (def node in Server_IP.split(',')){
sh """
NUM=\$(ssh root@${node} ""/bin/ls -l -d -rt /var/lib/tomcat9/webdir/code-* | wc -l"")
echo "${node} --> \${NUM}"
if [ \${NUM} -gt 5 ];then
NAME=`ssh root@${node} ""/bin/ls -l -d -rt /var/lib/tomcat9/webdir/code-* | head -n1 | awk '{print \$9}'""`
ssh root@${node} "rm -rf \${NAME}"
echo "${node} 删除历史版本\${NAME}成功!"
fi
"""
}
}
}
}
}
}
创建项目,复制脚本
运行结果
查看每个阶段日志