一. 环境准备

实验环境说明

  • 本实验采用华为云 ECS 进行,模拟真实工作环境
  • 本地电脑环境配置达标的情况下,也可以在本地电脑使用 VMware 虚拟机完成
  • 本实验共需 4 台云主机,全部使用 Rocky Linux 8.5 操作系统,2vCPU,4G 内存
    至于如何购买配置华为云服务,详见:# 华为云服务及弹性公网IP购买配置全流程

主机规划

主机名 IP地址 配置 角色
windows 程序员(本地客户端)
develop 192.168.0.10(公网IP) 2vCPU, 4G内存 程序员开发机
gitlab 192.168.0.20(公网IP) 2vCPU, 4G内存 远程仓库服务器
jenkins 192.168.0.30(公网IP) 2vCPU, 4G内存 CI/CD 服务器
web1 192.168.0.40(公网IP) 2vCPU, 4G内存 Web 服务器

请添加图片描述

注意:实际连接时需要使用各主机的公网 IP 地址进行 SSH 远程连接。

所有主机都采用前文的方式在华为云创建

二. GitLab 部署

2.1 GitLab 概述

GitLab 是一个开源的 Git 仓库服务器,用于实现代码集中托管。

  • 分为企业版CE 社区版
  • 部署方式:软件包部署容器部署

本实验采用容器部署方式。

2.2 部署 GitLab 服务器

操作主机:gitlab(192.168.0.20),远程连接时需使用其公网 IP 地址

前置准备:

  • gitlab_zh.tar 拷贝到 gitlab 服务器的 /root
  • docker 文件夹拷贝到 gitlab 服务器的 /root

通过容器部署GitLab服务

安装 Docker
[root@gitlab ~]# cd /root/docker
[root@gitlab docker]# dnf -y localinstall *.rpm      # 安装容器管理软件 docker
[root@gitlab docker]# dnf -y install bash-completion # 安装 tab 键补全(刷新生效)
[root@gitlab ~]# systemctl start docker              # 启动 docker 服务
[root@gitlab ~]# systemctl enable docker             # 将服务设置为开机自启
修改 SSH 端口(避免与容器端口冲突)

GitLab 容器也要用到 22 端口,宿主机 SSH 服务会与容器产生端口冲突,因此需要修改宿主机的 SSH 端口。

# vim +17 表示打开配置文件时,光标直接定位到第 17 行
[root@gitlab ~]# vim +17 /etc/ssh/sshd_config
# 修改配置文件
17 Port 8022

[root@gitlab ~]# systemctl restart sshd
# 重启之后需要使用远程工具重新连接 gitlab 服务器,并且指定 8022 端口号
创建 resolv.conf 文件

GitLab 容器运行需要 /etc/resolv.conf 文件,如果该文件已存在则无需创建。

[root@gitlab ~]# touch /etc/resolv.conf
导入 Docker 镜像

一个镜像可以创建很多容器。镜像是只读的,容器是可以改变的。 容器相当于精简的虚拟机,可以像虚拟机一样对外提供服务。

[root@gitlab ~]# docker load < /root/gitlab_zh.tar
[root@gitlab ~]# docker images       # 查看镜像是否导入
创建持久化目录

为了删除容器时不丢失数据,需要把容器产生的数据保存在宿主机上。在哪台主机上启动容器,哪台主机就是宿主机。

[root@gitlab ~]# mkdir -p /srv/gitlab/{config,logs,data}   # 创建持久化目录
[root@gitlab ~]# ls /srv/gitlab/
config  data  logs
创建并运行 GitLab 容器
[root@gitlab ~]# docker run -d \
> -h gitlab \
> --name gitlab \
> -p 443:443 -p 80:80 -p 22:22 \
> --restart always \
> -v /srv/gitlab/config:/etc/gitlab \
> -v /srv/gitlab/logs:/var/log/gitlab \
> -v /srv/gitlab/data:/var/opt/gitlab \
> gitlab_zh

#直接复制粘贴:docker run -d -h gitlab --name gitlab -p 443:443 -p 80:80 -p 22:22 --restart always -v /srv/gitlab/config:/etc/gitlab -v /srv/gitlab/logs:/var/log/gitlab -v/srv/gitlab/data:/var/opt/gitlab gitlab_zh


Docker run 参数说明:

参数 说明
-d 后台运行容器
-h gitlab 设置容器的主机名
--name gitlab 容器名称(docker ps 查看到的名称)
-p 端口映射,访问宿主机端口时转发给容器的对应端口
--restart always 开机自启
-v 数据卷映射,将容器中的路径映射到宿主机,以便持久化保存容器产生的数据
gitlab_zh 镜像名
[root@gitlab ~]# docker ps       # 查看正在运行的容器

如果一切正常,几分钟后可以访问 http://gitlab服务器的公网IP/,例如:http://121.36.66.101/

请添加图片描述

容器启动失败的处理

如果容器启动失败,再次创建时可能出现以下错误:

Error: error creating container storage: the container name "gitlab" is already in use by "ca425e...". You have to remove that container to be able to reuse that name.

解决方法:删除旧容器后重新创建

[root@gitlab ~]# docker rm gitlab
[root@gitlab ~]# docker run -d -h gitlab --name gitlab -p 443:443 -p 80:80 -p 22:22 --restart always -v /srv/gitlab/config:/etc/gitlab -v /srv/gitlab/logs:/var/log/gitlab -v /srv/gitlab/data:/var/opt/gitlab gitlab_zh

2.3 配置 GitLab

  • 第一次登录时要求修改密码,密码需要是复杂密码(如 1234.com
  • 修改后,登录的用户名是 root
登录与修改密码
  1. 浏览器访问 http://gitlab服务器公网IP/
  2. 首次访问会进入密码修改页面
  3. 设置新密码(如 1234.com
  4. 修改成功后,使用用户名 root 和新密码登录
    请添加图片描述
    请添加图片描述

请添加图片描述

修改外观设置(可选)

登录后可以根据需要修改 GitLab 的外观设置。

请添加图片描述

点击头像 → 退出,查看效果

请添加图片描述

2.4 GitLab 主要概念

概念 说明
用户 为使用 GitLab 的用户创建的账号
用户的集合,可以为部门创建组。将来可以在项目上为组授权,组中所有用户都会得到相应权限
项目 用于保存代码文件的空间

用户、组、项目之间的关系:

请添加图片描述

2.5 创建用户

操作用户: root(管理员)

  1. 登录 GitLab Web 界面
  2. 进入管理后台
  3. 创建用户:
    • 用户名:jerry
    • 密码:1234.com
  4. 填写截图上的几项后,其他使用默认配置,点击保存

点击扳手:
请添加图片描述
点击newuser
请添加图片描述
这里姓名仅用来标识用户,可以随意定义。
请添加图片描述

点击创建用户

请添加图片描述

创建完用户,点击右上角编辑可以编辑用户信息,设置密码
请添加图片描述

密码设置为1234.com,点击保存修改
请添加图片描述

2.6 验证新用户登录

  1. 退出 root 账号
  2. 使用新账号 jerry 和密码 1234.com 登录测试
  3. 第一次登录时也要求修改密码,新密码可以设置与旧密码一样
  4. 新建的 jerry 用户权限较小,看到的界面没有 root 的功能多

点击右上角退出
请添加图片描述
使用用户名和设置的密码重新登录

请添加图片描述
这里已经登录成功。(新用户第一次登录依旧要求重置密码,新密码可以设置与旧密码一样)
请添加图片描述

重新登录。新建的jerry用户因为权限较小,所以看到的界面,没有root的功能多。

请添加图片描述

2.7 创建组

操作用户: root(管理员)

  1. 登录 GitLab Web 界面(root 账号)
  2. 进入管理后台 → 创建组
  3. 组名:devops
  4. jerry 用户添加到 devops 组中,角色设置为 “主程序员”

点击扳手,点击new group
请添加图片描述
设置群组名和描述,其余默认即可,点击创建
请添加图片描述

添加用户jerry,身份为主程序员
请添加图片描述

这里的身份解读:
报告者:测试人员
开发人员:开发者,程序员
主程序员:项目经理等领导角色

2.8 创建项目

操作用户: root(管理员)

  1. 进入管理后台 → 创建项目
  2. 项目名:myproject
  3. 项目由 devops 组负责

创建新项目:
请添加图片描述这里表示myproject项目由devops组负责
请添加图片描述

创建完毕。显示我们的项目地址
请添加图片描述

切换为 jerry 用户登录,可以查看项目是否已经分配给该组。

请添加图片描述
点击进入项目仓库
请添加图片描述
向下滑动,是一些命令

请添加图片描述

三. 客户端上传代码到 GitLab 服务器

Git 全局配置(首次使用)

首次使用Git都需要配置用户名和邮箱,Linux和Windows都是

git config --global user.name "jerry"
git config --global user.email "jerry@test.com"

3.1 在 develop 服务器上下载项目

操作主机:develop(192.168.0.10),连接其公网 IP 地址

http://gitlab/devops/myproject.git是你的项目仓库地址,但是我们没有做dns域名解析,所以要把其中的gitlab改成你的GitLab主机的公网IP

[root@develop ~]# dnf -y install git       # 安装 git 工具
#注意这里IP改成你自己GitLab主机的公网IP
[root@develop ~]# git clone http://119.3.164.250/devops/myproject.git
Cloning into 'myproject'...
Warning: You appear to have cloned an empty repository.

3.2 编写代码并提交

[root@develop ~]# cd myproject/
#初始化用户信息,否则后续提交内容会报错
[root@develop myproject]# git config --global user.name "jerry"
[root@develop myproject]# git config --global user.email "jerry@test.com"
[root@develop myproject]# vim README.md
Welcome to my beautiful world!

[root@develop myproject]# git add .           # 保存到暂存区
[root@develop myproject]# git commit -m "init data"   # 提交至本地仓库

# 将 master 分支推送到 origin 仓库(origin 是默认仓库名)
[root@develop myproject]# git push -u origin master
Username for 'http://192.168.4.20': jerry      # 输入用户名
Password for 'http://jerry@192.168.4.20': 1234.com   # 输入密码(不显示)
#这里的用户名和密码就是我们在GitLab页面创建的用户名和密码

刷新 GitLab Web 页面,可以看到仓库中已经多出了 README.md 文件。

请添加图片描述

3.3 持续提交代码

# 后续操作可以重复:写代码 → 提交到版本库 → 上传到服务器
[root@develop myproject]# cp /etc/hosts .
[root@develop myproject]# git add .
[root@develop myproject]# git commit -m "add hosts"
[root@develop myproject]# git push             # 不再需要使用 -u 选项
Username for 'http://192.168.4.20': jerry
Password for 'http://jerry@192.168.4.20': 1234.com

刷新 GitLab Web 页面,可以看到仓库中已经多出了 hosts 文件。

3.4 Windows 客户端操作

前提: Windows 需要提前安装 Git 客户端。

在对应目录右键,即可显示Gil项,点击Open Git Bash here 即可在当前目录打卡操作台。

请添加图片描述

操作台中的指令操作和Linux上的命令操作完全一致
请添加图片描述

拉取代码

如果是刚刚安装的git软件需要首先定义全局配置,方可继续使用(执行一次即可)

#初始化用户和邮箱
$ git config --global user.name "jerry"
$ git config --global user.email "jerry@test.com"
#克隆仓库
$ git clone http://119.3.164.250/devops/myproject.git
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), 515 bytes | 0 bytes/s, done.
From http://121.36.66.101/devops/myproject
   * [new branch]      master -> origin/master

请添加图片描述

上传代码

注意要在myproject文件夹内进行操作

# 编写 win.txt 文件,内容为 "Here is Windows file."
$ git add .                    # 提交暂存区
$ git commit -m 'add win.txt'  # 提交本地仓库
$ git push -u origin master    # 将 master 分支推送到 origin 仓库

同样的,也需要我们输入用户名和密码
请添加图片描述

请添加图片描述

刷新 GitLab Web 页面,可以看到仓库中已经多出了 win.txt 文件。

请添加图片描述

3.5 develop 服务器拉取新代码

[root@develop myproject]# git pull
# 查看是否同步到 win.txt 文件
[root@develop myproject]# ls
README.md  hosts  win.txt

四. CICD 概述

CI-CD 定义

术语 全称 说明
CI Continuous Integration 持续集成:频繁将代码集成到主干,自动构建和测试
CD Continuous Delivery/Deployment 持续交付/部署:自动将代码部署到生产环境

请添加图片描述

软件程序上线流程

  1. 程序员将代码上传到 GitLab 服务器
  2. SRE 工程师通过 Jenkins 服务器自动下载 GitLab 上的代码
  3. SRE 工程师编写自动部署到服务器上的脚本

五. Jenkins 服务器部署

操作主机:jenkins(192.168.0.30),远程连接其公网 IP 地址

5.1 安装依赖包

# Jenkins 需要通过 git 下载代码 → 安装 git
# Jenkins 是 Java 程序 → 安装 Java
# postfix 和 mailx 是邮件程序 → Jenkins 可通过它们给管理员发邮件
[root@jenkins ~]# dnf -y install git postfix mailx java-11-openjdk

5.2 安装 Jenkins

前置准备:

  • jenkins-2.263.1-1.1.1.noarch.rpmjenkins_plugins.tar.gz 上传至 jenkins 服务器的 /root
[root@jenkins ~]# ls
jenkins-2.263.1-1.1.noarch.rpm  jenkins_plugins.tar.gz

[root@jenkins ~]# dnf -y localinstall jenkins-2.263.1-1.1.noarch.rpm
[root@jenkins ~]# systemctl start jenkins
[root@jenkins ~]# systemctl enable jenkins
[root@jenkins ~]# ss -nutpl | grep :8080     # 查看端口 8080 是否正常

5.3 Jenkins 初始化

访问 http://jenkins服务器公网IP:8080 进行初始化。

这里要我们输入密码,并给我们初始化的密码路径。我们复制路径,到jenkins主机对应路径查找即可
请添加图片描述

获取初始化密码
# 每个人的密码都不一样,请以自己的为准
[root@jenkins ~]# cat /var/lib/jenkins/secrets/initialAdminPassword
b9d26edeeef714940ab10aaa541081d90

将查看到的密码粘贴到文本框中,点击继续。

自定义 Jenkins

不要安装推荐插件,选第二个
请添加图片描述

点击无,跳过插件安装(使用离线插件包)

请添加图片描述

创建管理员用户
  • 本次实验不创建管理员,使用自带的 admin 用户
  • 默认管理员密码为初始化密码

请添加图片描述
直接点击保存
请添加图片描述

Jenkins 就绪

安装完成后,默认以用户名 admin 和初始化密码登录 Jenkins。

请添加图片描述

修改 admin 密码

登录后,在设置中修改 admin 用户的密码为 123456

点击右上角用户名,点击左侧齿轮:
请添加图片描述
设置密码为123456,并保存

请添加图片描述

重新登录:

请添加图片描述

5.4 配置 Jenkins

安装插件: Jenkins 的很多功能都是通过插件实现的(如发邮件、中文支持)。

[root@jenkins ~]# tar -xf jenkins_plugins.tar.gz
# 拷贝文件时注意:-r 拷贝目录,-p 保留权限
[root@jenkins ~]# cp -rp jenkins_plugins/* /var/lib/jenkins/plugins/
[root@jenkins ~]# systemctl restart jenkins      # 重启 Jenkins 服务

刷新 Web 页面,如果出现中文则说明插件安装成功。

请添加图片描述

请添加图片描述

六. 软件版本管理

6.1 Git Tag 打标签

操作主机:develop

可以使用 git tag 将某一次 commit 提交标识为某一版本。

打标签顺序:修改文件–>把文件添加到暂存区–>提交到本地仓库–>打标签–>上传到远程仓库

打标签在 git commit 之后

[root@develop ~]# cd myproject/                     # 进入项目目录
[root@develop myproject]# git tag                   # 查看标记,默认没有标记
[root@develop myproject]# git tag 1.0               # 将当前提交标识为 1.0
[root@develop myproject]# git tag                   # 查看标记
1.0

[root@develop myproject]# echo 'hello world' > index.html
[root@develop myproject]# git add .
[root@develop myproject]# git commit -m "add index.html"
[root@develop myproject]# git tag 1.1               # 将当前提交标识为 1.1

# 将本地文件和 tag 推送到 GitLab 服务器
[root@develop myproject]# git push                  # 只推送文件,不推送标记
[root@develop myproject]# git push --tags           # 推送所有标签

6.2 在 GitLab 上查看标记

刷新 GitLab Web 页面,在项目 → Tags 中可以查看所有标签。

请添加图片描述

七. 配置 Jenkins 访问 GitLab 远程仓库

7.1 新建任务

  1. 登录 Jenkins Web 界面
  2. 点击 新建任务(New Item)
  3. 任务名称:myproject
  4. 选择 构建一个自由风格的软件项目(Freestyle project)
  5. 点击确定

请添加图片描述
注意这里项目名称一定要和我们的仓库项目名一致
请添加图片描述

7.2 配置参数化构建

在任务配置页面:

  1. 勾选 参数化构建过程
  2. 添加参数 → Git参数
    • 名称:web(自定义变量名,用于标识 tag 或分支)

参数化构建选择Git参数

请添加图片描述

请添加图片描述

7.3 配置 Git 源码管理

  1. 源码管理 中,选择 Git
  2. Repository URL:http://gitlab服务器IP/devops/myproject.git
  3. 指定分支:*$web(使用上面步骤创建的变量 $web

输入我们GitLab仓库的地址
请添加图片描述
点击保存即可。

回到首页,就能看见我们的项目了
请添加图片描述

7.4 构建测试

请添加图片描述

点击 开始构建,选择构建参数(如 1.01.1,即我们在仓库上传代码的版本号)。

请添加图片描述

在 Jenkins 服务器查看下载的内容:

[root@jenkins ~]# ls /var/lib/jenkins/workspace/myproject/
hosts  index.html  README.md  win.txt

八、下载到子目录

8.1 问题背景

当前配置下,不同版本的代码会覆盖同一目录,无法实现多个版本代码并存。例如 1.1 版本的代码会覆盖 1.0 版本。

8.2 解决方案

使用 Jenkins 的 “Checkout to a sub-directory”(子目录) 功能,将不同版本的代码下载到不同的子目录,不共享相同目录

8.3 配置方法

在任务配置页面:

  1. 找到 Additional Behaviours

请添加图片描述
请添加图片描述

  1. 点击构建触发器, 新增检出到子目录(Checkout to a sub-directory)

请添加图片描述

  1. Local subdirectory for repository 中输入:myproject-$web,并保存配置

请添加图片描述

8.4 测试

# 删除之前下载的内容
[root@jenkins ~]# rm -rf /var/lib/jenkins/workspace/myproject/

按照之前的构建方法执行多次构建,构建不同版本(1.01.1):

请添加图片描述
请添加图片描述

返回jenkins主机验证:

[root@jenkins ~]# ls /var/lib/jenkins/workspace/myproject/
myproject-1.0  myproject-1.1
#可以看到,不同版本导出到不同目录了

九、部署代码到 Web 服务器

9.1 自动化部署流程

  1. 程序员编写代码,推送到 GitLab 服务器
  2. Jenkins 服务器从 GitLab 上下载代码
  3. Jenkins 处理下载的代码:
    • 删除下载目录的版本库(.git 本地仓库)
    • 将下载的代码打包
    • 计算程序压缩包的 md5 值
    • 在 Jenkins 上安装 httpd 服务,共享程序压缩包
  4. Web 服务器下载软件包,并应用(通过脚本实现)
  5. 访问测试

9.2 配置共享服务器

在 Jenkins 上安装和配置 httpd 共享服务器:

#安装apache的软件包
[root@jenkins ~]# dnf -y install httpd
[root@jenkins ~]# systemctl start httpd
[root@jenkins ~]# systemctl enable httpd
#创建jenkins从gitlab上下载的打包代码存放的目录
[root@jenkins ~]# mkdir -p /var/www/html/deploy/packages
#修改权限,因为是jenkins自动下载的,需要修改存放的权限
[root@jenkins ~]# chown -R jenkins:jenkins /var/www/html/deploy/ 

9.3 配置 Jenkins 把 GitLab 下载的代码打包

在 Jenkins 的 myproject 工程页,点击配置
请添加图片描述
点击构建,添加构建步骤(Build Steps)
请添加图片描述

选择 执行 Shell(Execute shell),添加以下脚本:

pkg_dir=/var/www/html/deploy/packages
#将 Jenkins 从 GitLab 拉取的代码目录(myproject-1.0 等)复制到打包目录中,准备进行加工
cp -r myproject-$web $pkg_dir
#删除复制的代码目录中的 .git 子目录,删除后,部署的是纯业务代码
rm -rf $pkg_dir/myproject-$web/.git
cd $pkg_dir
#将 myproject-$web 目录打包为 .tar.gz 压缩包
tar -zcf myproject-$web.tar.gz myproject-$web
#压缩完成后,删除源码目录,只保留压缩包
rm -rf myproject-$web
#计算压缩包的 MD5 校验值,并保存到 .md5 文件中。Web 服务器下载后可通过比对 MD5 来验证文件完整性,避免因网络传输损坏导致部署失败
md5sum myproject-$web.tar.gz | awk '{print $1}' > myproject-$web.tar.gz.md5
cd ..
echo -n $web > ver.txt

请添加图片描述

脚本解析:

命令 说明
pkg_dir=/var/www/html/deploy/packages 定义打包目录
cp -r myproject-$web $pkg_dir 复制代码到打包目录
rm -rf $pkg_dir/myproject-$web/.git 删除 .git 目录(减小体积)
cd $pkg_dir 进入打包目录
tar -zcf myproject-$web.tar.gz myproject-$web 打包成 tar.gz
rm -rf myproject-$web 删除源码目录(只保留压缩包)
md5sum ... > myproject-$web.tar.gz.md5 计算并保存 md5 值
echo -n $web > ver.txt 记录当前版本号

保存配置后,点击立即构建进行测试。

请添加图片描述

9.4 验证共享目录

浏览器访问:http://jenkins公网IP/deploy/packages/

可以看到打包的代码文件列表:

请添加图片描述

十、Web 服务自动部署

10.1 Web 服务器环境配置

操作主机:web1(192.168.0.40)

[root@web1 ~]# dnf -y install httpd wget
[root@web1 ~]# mkdir /var/www/download      # 存储 jenkins 主机上下载的应用代码
[root@web1 ~]# mkdir /var/www/deploy        # 部署应用代码
[root@web1 ~]# systemctl start httpd
[root@web1 ~]# systemctl enable httpd
[root@web1 ~]# ss -ntulp | grep :80         # 查看 80 端口是否正常

10.2 编写自动上线脚本

操作主机:web1

[root@web1 ~]# vim web.py
web.py 完整脚本

切记!脚本中的IP地址换成自己的jenkis的弹性公网IP

import os
import requests
import hashlib
import tarfile


def has_new_ver(web1_ver_path, ver_url):
    # web1_ver_path 为应用服务器web1主机的当前版本文件路径
    # 如果文件不存在,返回True, 提示没有新版本
    if not os.path.exists(web1_ver_path):
        return True
    # 当web1_ver_path存在时,先获取当前应用的版本号
    with open(web1_ver_path, mode="r") as fr:
        local_ver = fr.read()
    # 通过requests获取jenkins服务器上的最新版本号
    r = requests.get(ver_url)
    # 当web1上的版本号和Jenkins服务器上的版本号不相等时,返回True, 即有新的版本
    if local_ver != r.text:
        return True
    return False


# 声明函数file_ok(), 功能:如果下载的包文件未损坏,则返回True,否则返回False
def file_ok(web1_tar_path, jenkins_tar_md5_url):
    m = hashlib.md5()
    with open(web1_tar_path, mode="rb") as fw:
        while True:
            data = fw.read(4096)
            if len(data) == 0:
                break
            m.update(data)
    # jenkins_tar_md5_url 为jenkins服务器上的压缩包的md5值文件链接地址
    r = requests.get(jenkins_tar_md5_url)
    if m.hexdigest() == r.text.strip():
        # 相等,代表文件未损坏,返回True
        return True
    return False


# 声明函数deploy(), 功能:用于部署软件到 web1 服务器
def deploy(web1_tar_path, web1_deploy_dir, dest):
    tar = tarfile.open(web1_tar_path)  # 打开压缩包web1_tar_path
    tar.extractall(path=web1_deploy_dir)  # 解压到web1_deploy_dir目录下
    tar.close()  # 关闭tar
    # 获取web1_tar_path变量中,最后一个'/',右边的内容,然后做切片,去除".tar.gz",只留下文件名
    file_name = os.path.basename(web1_tar_path)[:-7]
    # 将变量web1_deploy_dir和变量file_name拼接在一起
    app_dir = os.path.join(web1_deploy_dir, file_name)
    # 创建链接,如果软链接dest存在,删除软连接,然后为app_dir创建新的软链接
    if os.path.exists(dest):
        os.remove(dest)
    os.symlink(app_dir, dest)


if __name__ == "__main__":
    ### 判断jenkins服务器上是否有新版本
    # ver_url 为jenkins服务器的当前版本文件路径
    # web1_ver_path 为应用服务器web1主机的当前版本文件路径
    # 这里的地址需要求改为自己的IP地址
    ver_url = "http://1.92.111.106/deploy/ver.txt"
    web1_ver_path = "/var/www/deploy/ver.txt"
    if not has_new_ver(web1_ver_path, ver_url):
        print("no new version~")
        exit(1)
    # ==========================================
    # 如果服务器上有新版本,则下载新版本
    # r.text 为jenkins服务器的当前版本内容
    # jenkins_tar_url 为jenkins服务器上的压缩包链接地址
    # web1_tar_path 为应用服务器web1主机的压缩包路径
    # 这里的地址需要修改为自己的IP地址
    r = requests.get(ver_url)
    jenkins_tar_url = f"http://1.92.111.106/deploy/packages/myproject-{r.text}.tar.gz"
    web1_tar_path = f"/var/www/download/myproject-{r.text}.tar.gz"
    with open(web1_tar_path, mode="wb") as fw:
        fw.write(requests.get(jenkins_tar_url).content)
    # 校验下载的软件包是否损坏,如果损坏则删除 os.remove()
    # jenkins_tar_md5_url 为jenkins服务器上的压缩包的md5值文件链接地址
    jenkins_tar_md5_url = jenkins_tar_url + ".md5"
    if not file_ok(web1_tar_path, jenkins_tar_md5_url):
        print("File has been broken~")
        os.remove(web1_tar_path)
        exit(2)
    # =========================================
    web1_deploy_dir = '/var/www/deploy'
    dest = '/var/www/html/current'
    deploy(web1_tar_path, web1_deploy_dir, dest)
    # 更新本地的版本文件
    if os.path.exists(web1_ver_path):
        os.remove(web1_ver_path)
    with open(web1_ver_path, mode="w") as fw:
        fw.write(requests.get(ver_url).text)

脚本核心功能:

  1. 检查新版本:对比本地版本文件和 Jenkins 服务器上的版本文件
  2. 下载新版本:从 Jenkins 服务器下载压缩包
  3. 校验完整性:通过 md5 值验证压缩包是否完整
  4. 部署应用:解压并创建软链接指向当前版本
  5. 更新版本号:更新本地版本文件
[root@web1 ~]# python3 web.py
[root@web1 html]# ls /var/www/deploy
myproject-1.1 ver.txt

浏览器访问http://web服务器公网IP/current 可以看到部署的文件页面

请添加图片描述

十一、全流程测试

程序员 push 代码 → GitLab 存储代码 → Jenkins 打包 → httpd 共享压缩包
                                                          │
                                                          ▼
                                              web.py 在 Web 服务器上执行
                                                          │
                                                          ▼
                                          下载 → 校验 → 解压 → 部署上线

11.1 测试一:更新 index.html

develop 服务器操作
[root@develop ~]# cd myproject
[root@develop myproject]# vim index.html
<marquee>welcome to tedu.</marquee>

[root@develop myproject]# git add .                     # 提交暂存区
[root@develop myproject]# git commit -m 'update index.html'   # 提交本地仓库
[root@develop myproject]# git tag 2.0                   # 打标签 2.0 版本

[root@develop myproject]# git push
Username for 'http://121.36.66.101': jerry
Password for 'http://jerry@121.36.66.101': 1234.com

[root@develop myproject]# git push --tags
Username for 'http://121.36.66.101': jerry
Password for 'http://jerry@121.36.66.101': 1234.com
Jenkins 操作
  1. 登录 Jenkins Web 界面
  2. 进入 myproject 任务
  3. 点击 Build with Parameters
  4. 输入版本号:2.0
  5. 点击构建

请添加图片描述

Web 服务器执行部署
[root@web1 ~]# python3 web.py
验证

浏览器访问 http://web服务器公网IP/current/,可以看到更新后的页面:

请添加图片描述

11.2 测试二:添加 cube.html

develop 服务器操作
# 将 cube.html 上传至 develop 服务器的 /root
[root@devlop myproject]# cp /root/cube.html . #复制新代码至工作区
[root@devlop myproject]# git add . #提交至暂存区
[root@devlop myproject]# git commit -m 'add cube.html' #提交至本地仓库
[root@devlop myproject]# git tag 3.0 #打标签3.0 版本

[root@develop myproject]# git push    #推送代码至gitlab远程仓库
Username for 'http://121.36.66.101': jerry
Password for 'http://jerry@121.36.66.101': 1234.com

[root@develop myproject]# git push --tags    #推送标签至gitlab远程仓库
Username for 'http://121.36.66.101': jerry
Password for 'http://jerry@121.36.66.101': 1234.com
Jenkins 操作
  1. 进入 myproject 任务

请添加图片描述

  1. 点击 Build with Parameters
  2. 输入版本号:3.0
  3. 点击构建

请添加图片描述

Web 服务器执行部署
[root@web1 ~]# python3 web.py
验证

浏览器访问 http://web服务器公网IP/current/cube.html,可以看到 cube.html 页面。

请添加图片描述

11.3 测试三:更新坦克大战游戏代码

Windows 客户端操作

将 game01 复制到 Windows 的 myproject 工作目录下(我们之前在windows导入的仓库)
请添加图片描述

右键打开Git工作台


# 先拉取最新代码,同步一下版本
git pull

# 提交游戏代码
git add .
git commit -m 'add game01'
git tag 4.0

# 推送代码和标签
git push
git push --tags

如果之前输入过用户名和密码,后续就不用再输入

Jenkins 操作
  1. 进入 myproject 任务

请添加图片描述

  1. 点击 Build with Parameters
  2. 输入版本号:4.0
  3. 点击构建

请添加图片描述

Web 服务器执行部署
[root@web1 ~]# python3 web.py
验证

浏览器访问 http://web服务器公网IP/current/game01/,可以看到坦克大战游戏页面。

develop 服务器拉取最新代码
[root@develop myproject]# git pull
[root@develop myproject]# ls
cube.html  game01  hosts  index.html  README.md  win.txt

请添加图片描述

十二、总结

掌握要点

技能 说明
GitLab 远程仓库 掌握使用容器构建 GitLab 服务的方法
GitLab 使用方法 掌握用户、组、项目的创建和管理
Jenkins 工作原理 理解 CI/CD 流程中 Jenkins 的角色
Jenkins 使用方法 掌握任务创建、参数化构建、源码管理、构建步骤配置
CI/CD 全流程 掌握从代码提交到自动化部署的完整流程

核心命令速查

操作 命令
Docker 导入镜像 docker load < /path/to/image.tar
Docker 运行容器 docker run -d -h hostname --name container -p port:port ...
创建 Git tag git tag <version>
推送 tag git push --tags
克隆仓库 git clone <repo_url>
查看 Jenkins 密码 cat /var/lib/jenkins/secrets/initialAdminPassword
重启 Jenkins systemctl restart jenkins

CI/CD 流程图

程序员 (develop)
    │
    │ git push + git push --tags
    ▼
GitLab 远程仓库 (gitlab: 80)
    │
    │ Jenkins 拉取 (通过 Git Plugin)
    ▼
Jenkins CI/CD 服务器 (jenkins: 8080)
    │
    │ 1. 下载代码到子目录
    │ 2. 删除 .git
    │ 3. 打包 tar.gz
    │ 4. 计算 md5
    │ 5. 通过 httpd 共享 (deploy/packages/)
    ▼
共享服务器 (jenkins: httpd)
    │
    │ Web 服务器执行 web.py 脚本
    ▼
Web 服务器 (web1: 80)
    │
    │ 1. 检查新版本
    │ 2. 下载压缩包
    │ 3. 校验 md5
    │ 4. 解压部署
    │ 5. 更新软链接
    ▼
用户访问 http://web服务器IP/current/
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐