在上一篇文章 作为前端 leader,怎么快速搭建多环境CICD自动化部署? 中,介绍了 阿里云效
、Github Actions
两种自动化部署方案,为了可以有更多的选择,这里我们再来看一下 gitlab 的 多环境 CI/CD 自动化部署。本文除了 gitlab 共享 runner 涉及的 docker 配置外,暂不涉及 docker、JenKins 等内容
大致内容如下
- 通过部署一个简单的项目到 gitlab pages 初步了解 gitlab CI/CD
- 了解 gitlab CI/CD 基础概念、运行机制等
- 使用 gitlab 自带 runner 进行自动化部署、使用 ssh 命令操作部署远程服务器
- 在自己服务器安装 gitlab runner 进行自动化部署
- 两种 runner 部署耗时对比
gitlab runner 类型 | 部署方式(自动触发/手动一键部署等) | 环境 |
---|---|---|
gitlab 共享 runner | 部署 vitepress 项目到 gitlab pages | --- |
gitlab 共享 runner | 部署 vitepress 静态站点到 oss | 测试/正式 |
gitlab 共享 runner | 部署 vue3+vite 项目到腾讯云 | 测试/正式 |
gitlab 共享 runner | 部署 koa 接口服务器到腾讯云 | 测试/正式 |
阿里云2c4g服务器安装 runner | 部署 vitepress 静态站点到 oss | 测试/正式 |
阿里云2c4g服务器安装 runner | 部署 vue3+vite 项目到腾讯云 | 测试/正式 |
阿里云2c4g服务器安装 runner | 部署 vue3+vite 项目到当前 runner 所在机器 | 测试/正式 |
阿里云2c4g服务器安装 runner | 部署 koa 接口服务器到腾讯云 | 测试/正式 |
部署 vitepress 项目到 gitlab pages
先通过一个简单、容易上手的实践来了解 gitlab 自动化部署大致流程
在 VitePress 官网中有一个 部署 vitepress 项目到 gitlab pages 的教程,比较简单,分两步
- 1、修改 docs/.vitepress/config.ts 配置文件,将 vitepress 构建后的生成文件放到项目根目录 public 文件夹中(gitlab pages 有这个要求)。相关demo vitepress-new
- 2、在项目根目录新建 .gitlab-ci.yml 写入如下内容
yml
image: node:16
pages:
cache:
paths:
- node_modules/
script:
- npm install
- npm run docs:build
artifacts: # 制品 /ˈɑːtɪfækt/
paths:
- public
only:
- main
Gitlab pages 仓库配置问题
理论上,经过上面两个步骤后,只要修改代码推送到 gitlab 远程仓库,就会触发 gitlab CICD 自动部署。但实际操作中,对于新创建的 gitlab 仓库,需要在仓库 - 设置中开启 gitlab pages,不然就算写好了 .gitlab-ci.yml 内容,也无法触发 gitlab pages 自动化部署。
如下图,在 Settings - Pages 设置中,会引导你填写内容,自动生成 .gitlab-ci.yml。这里 build image 填 node:16,勾选 build 输出目录为 public,下一步直到完成。
设置完成后之前填写的 .gitlab-ci.yml 内容可能会被覆盖,需要修改为上面提到过的 vitepress 官网提供的部署配置文件。提交后,会触发自动化部署流程。如下图
部署成功后,可以通过 https://<username>.gitlab.io/<repository>/
来访问部署后的内容,比如我的 username 是 zuoxiaobai, 项目仓库为 vitepress-new,即可通过 zuoxiaobai.gitlab.io/vitepress-n... 来访问部署到 gitlab pages 后的内容,如下图
修改代码测试自动化部署更新
为了测试提交代码自动化部署,这里提交一个文案改动,push 到远程
可以看到,如下图 Build - Pipelines 流水线中自动触发最新代码的 CI/CD 流程
43s 后部署完成,再次访问页面,就是最新的内容了,如下图
其他注意点
1、vitepress 项目部署到 github pages 时,项目结构要规范,内容根据官网文档使用 docs 目录包裹,不要省去,不然 public 目录会冲突
2、针对 gitlab pages 部署到的页面,如果项目仓库是私有的需要登录才能访问,因此一般这种页面如果需要所有人能看到,需要将仓库设置为 public
Gitlab 基础概念
上面我们初步体验了 gitlab 的自动化部署流程,为了更好的进行后续的内容,这里建议大家先把 Gitlab-ci:从零开始的前端自动化部署 - 知乎 这篇文章大致看一遍,对gitlab 基础概念有一个大致的了解。
下面概括内容就是来自该文章,如果你对以下概念比较熟悉,可以跳过 Gitlab 基础概念 这部分内容
- gitlab CI/CD 运行机制、.gitlab-ci.yml 配置文件
- Pipelines、Stage、Job、Artifacts
- GitLab runners(Shared runners、Project runners、Group runners)、Executors
Gitlab CI/CD 运行机制
当 Gitlab 仓库出现 push/merge 操作时,会检测当前项目根目录是否有 .gitlab-ci.yml 文件,如果有就执行该配置文件中的 CICD 自动化部署脚本。(这点和 Github Actions 有点类似,只是 Github 检测路径是 .github/workflows/*.yml )
.gitlab-ci.yml 配置文件 用于指定 CI/CD 构建部署逻辑,比如 npm install、build、ssh 部署等。
这些步骤像流水线操作一样,一般会把这个过程叫做 Pipelines(流水线) 。
每一个流水线包含多个 Stage(阶段/步骤) ,每个阶段/步骤可以有 1 个或多个 Job(任务)
上面图中对应 .gitlab-ci.yml 配置如下
Runners 与 Executors
Runners 可以简单理解为运行 .gitlab-ci.yml 部署脚本所使用的机器,参考 What is GitLab Runner?,一般分为两种
- Gitlab 自有的 Shared runners(默认),可免费使用,会有使用时长限制,构建部署过程运行在 Gitlab 提供的云服务器上。 可以用于所有 group 和 project,每个 CI/CD Job 都运行在一个隔离、独立的虚拟机上。
- 自定义 runner(Project runners、Group runners) ,在自己的服务器上安装 gitlab runner 程序,指定用这个 runner 来执行 .gitlab-ci.yml 部署构建流程。
如下图,可以在仓库的 Settings - CI/CD - Runners 中进行设置,关联自定义 runner 服务器
一般在自己的服务器上安装 gitlab runner,会让你选择一个 executors (执行器/执行程序),用于指定这个 runner 中每个 Job 运行的环境,如下图,有多种选择
一般选择 shell 会简单一点,docker 也不错,可能对服务器内存要求高点,更多细节、区别参见官方文档 Runner executors | GitLab
Artifacts 制品
.gitlab-ci.yml 配置中的 artifacts 用于指定制品(也就是 npm run build 构建生成的文件)所在路径,在 Pipelines 下面的菜单中有对应的制品菜单,可以下载/查看历史制品文件。
yml
# .gitlab-ci.yml
build-job:
stage: build
script:
- npm run build
artifacts: # 制品目录 /ˈɑːtɪfækt/
paths:
- dist
deploy-job:
stage: deploy
script:
# - ls; pwd; # 查看运行路径
- ssh root@$CUSTOM_IP "rm -rf /root/demo.zuo11.com"
- scp -r ./dist root@$CUSTOM_IP:/root/demo.zuo11.com
不同用户不同的菜单/页面
另外不同的用户、权限看到的 gitlab 页面可能不一样,如下图,公共仓库中所有者、未登录访客菜单会有一些区别,部署相关的一个是 Build - Pipelines ,一个是 CI/CD - Pipelines
使用 gitlab 自带 runner 进行部署
下面依次用三个项目使用 gitlab 自带 runner 来进行多环境 CICD 自动化部署
- 部署 vitepress 静态站点到阿里云 oss(测试/正式)
- 部署 vue3+vite 前端项目到腾讯云服务器(测试/正式)
- 部署 koa+ mongodb 接口服务到腾讯云服务器(测试/正式)
部署 vitepress 静态站点到 oss
使用 blog - gitlab vitepress 项目用来进行测试,在项目根目录添加 .gitlab-ci.yml 文件,内容如下,分三个阶段
- npm install
- npm run build
- 安装阿里云 OSS 命令行工具 ossutil64、配置秘钥、部署 .vitepress/dist 到 OSS 指定 bucket
yml
image: node:16
stages:
- install
- build
- deploy
cache: # 缓存
paths:
- node_modules
- build
install-job:
stage: install
script:
- npm install
build-job:
stage: build
script:
- npm run build
artifacts: # 制品目录 /ˈɑːtɪfækt/
paths:
- ./.vitepress/dist
deploy-job:
stage: deploy
script:
- ls
- pwd
# 安装并配置 oss,参考 https://www.mmfei.com/2021/05/通过gitlab的ci自动部署前端项目到阿里云的oss/
- wget http://gosspublic.alicdn.com/ossutil/1.7.3/ossutil64 -O /usr/bin/ossutil64
- chmod 755 /usr/bin/ossutil64
- ossutil64 config -e $OSS_END_POINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET
# 部署制品文件到阿里云 oss test-zuo11-com 仓库
- ossutil64 cp -r -f ./.vitepress/dist oss://test-zuo11-com
其中阿里云 oss 命令行部署工具 ossutil64 需要配置 3 个敏感信息,怎么获取这些值?参考文档 配置ossutil - 阿里云
- -e endpoint, 设置Bucket所在地域的域名信息 OSS_END_POINT
- -i accessKeyID, 访问密钥的一部分,用于标识用户身份,以对命令请求进行身份验证。OSS_ACCESS_KEY_ID
- -k accessKeySecret, 访问OSS使用的访问凭证。OSS_ACCESS_KEY_SECRET
可以在 gitlab 对应仓库 Settings - CI/CD - Variables 位置设置这 3 个变量的值
设置完成后,提交 .gitlab-ci.yml 代码就会触发自动化部署,在仓库目录下的 Build - Pipelines 中可以看到,如下图
部署的目标 oss bucket 关联了 test.zuo11.com,在部署完成后,访问 test.zuo11.com 就能看到最新的内容,如下图
手动触发一键部署
上面的 .gitlab-ci.yml 配置在每次提交 push 到远程都会触发触发自动化部署。但有些提交比较频繁的场景,为了不浪费部署服务器性能,需要设置为手动触发,可以使用 when: manual 让某个 Job 只有手动点击才能触发,yaml 配置参数详情可以参考 .gitlab-ci.yml keyword reference - GitLab
yml
install-job:
stage: install
script:
- npm install
when: manual
我想的是把 npm install 安装依赖这个 Job 设置为手动触发,就可以阻止后续的执行。但提交后发现,居然只跳过这个 Job,下面的两个步骤依旧正常执行,如下图
为了手动部署时可以一键部署,我把安装依赖、build 两个stage 合并到 deploy stage,只保留一个 stage,配置如下
yml
image: node:16
stages:
- deploy
cache: # 缓存
paths:
- node_modules
deploy-job:
stage: deploy
script:
- ls
- pwd
- npm install
- npm run build
# 安装并配置 oss
- wget http://gosspublic.alicdn.com/ossutil/1.7.3/ossutil64 -O /usr/bin/ossutil64
- chmod 755 /usr/bin/ossutil64
- ossutil64 config -e $OSS_END_POINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET
# 部署制品文件到阿里云 oss test-zuo11-com 仓库
- ossutil64 cp -r -f ./.vitepress/dist oss://test-zuo11-com
when: manual
artifacts:
paths:
- ./.vitepress/dist
提交后,状态如下,点击 Stages 状态图标 - Paly,就可以一键部署了,如下图
修改标题后,点击手动部署,成功后再访问 test.zuo11.com 即可看到效果
多环境部署配置 only
在 gitlab 中,多环境可以使用 only 或者配置 environments 来实现。
先来看使用 only 指定分支,不同分支部署到不同 oss bucket
环境 | oss bucket | 分支 | 域名 |
---|---|---|---|
正式环境 | test-zuo11-com | main | test.zuo11.com |
测试环境 | test-zuo11-com-dev | v1.0.0 | test-dev.zuo11.com |
对应的 .gitlab-ci.yml 配置如下
yml
image: node:16
stages:
- deploy-prod
- deploy-dev
cache: # 缓存
paths:
- node_modules
deploy-job-prod:
stage: deploy-prod
script:
- npm install
- npm run build
# 安装并配置 oss
- wget http://gosspublic.alicdn.com/ossutil/1.7.3/ossutil64 -O /usr/bin/ossutil64
- chmod 755 /usr/bin/ossutil64
- ossutil64 config -e $OSS_END_POINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET
# 部署制品文件到阿里云 oss test-zuo11-com 仓库
- ossutil64 cp -r -f ./.vitepress/dist oss://test-zuo11-com
when: manual
only:
- main
artifacts:
paths:
- ./.vitepress/dist
deploy-job-dev:
stage: deploy-dev
script:
- npm install
- npm run build
# 安装并配置 oss
- wget http://gosspublic.alicdn.com/ossutil/1.7.3/ossutil64 -O /usr/bin/ossutil64
- chmod 755 /usr/bin/ossutil64
- ossutil64 config -e $OSS_END_POINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET
# 部署制品文件到阿里云 oss test-zuo11-com 仓库
- ossutil64 cp -r -f ./.vitepress/dist oss://test-zuo11-com-dev
when: manual
only:
- v1.0.0
artifacts:
paths:
- ./.vitepress/dist
这里有一个坑,就是 gitlab 非 main 分支读取不到 cicd 变量?需要看对应的变量是否勾选了 Protected,如果是,需要修改 - 取消勾选。
相关 Pipelines 流水线如下图,only 设置的分支,它的 stage 只会出现在对应的分支。修改代码提交后,点击 Statgs 图标 - Play 即可一键部署或重新部署。
部署完成后,看测试环境 test-dev.zuo11.com 是否可以正常访问,如下图
多环境部署配置 environments
上面用 only 来控制 Job 仅在指定分支运行,gitlab 还有一个专门的 environments 来管理多环境,如下图
创建环境需要一个 name、url,对应环境名称、部署后的链接,配置如下
yaml
deploy-job-prod:
stage: deploy-prod
# ...
environment:
name: prod
url: http://test.zuo11.com
deploy-job-dev:
stage: deploy-dev
# ...
environment:
name: test
url: http://test-dev.zuo11.com
设置好环境、.gitlab-ci.yml 后,页面如下,点击 open 可以跳转到对应环境的 url
完整配置如下
yml
image: node:16
stages:
- deploy-prod
- deploy-dev
cache: # 缓存
paths:
- node_modules
deploy-job-prod:
stage: deploy-prod
script:
- npm install
- npm run build
# 安装并配置 oss
- wget http://gosspublic.alicdn.com/ossutil/1.7.3/ossutil64 -O /usr/bin/ossutil64
- chmod 755 /usr/bin/ossutil64
- ossutil64 config -e $OSS_END_POINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET
# 部署制品文件到阿里云 oss test-zuo11-com 仓库
- ossutil64 cp -r -f ./.vitepress/dist oss://test-zuo11-com
when: manual
environment:
name: prod
url: http://test.zuo11.com
artifacts:
paths:
- ./.vitepress/dist
deploy-job-dev:
stage: deploy-dev
script:
- npm install
- npm run build
# 安装并配置 oss
- wget http://gosspublic.alicdn.com/ossutil/1.7.3/ossutil64 -O /usr/bin/ossutil64
- chmod 755 /usr/bin/ossutil64
- ossutil64 config -e $OSS_END_POINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET
# 部署制品文件到阿里云 oss test-zuo11-com 仓库
- ossutil64 cp -r -f ./.vitepress/dist oss://test-zuo11-com-dev
when: manual
environment:
name: test
url: http://test-dev.zuo11.com
artifacts:
paths:
- ./.vitepress/dist
提交后,Pipelines 如下图,上面的配置中没有用 only 限制版本,且为手动,点击不同的 stage 图标可以一键部署到不同的环境。如果你比较细心,你可能会发现不使用 environments 也可以达到这种效果,这里使用 evironments 环境配置只是做了一个分类。
使用 ssh 命令操作部署远程服务器
在将项目部署到服务器之前,有必要先来看看怎么使用 ssh 命令操作服务器,一般分为两种
- 使用 ssh 在远程服务器上执行命令
bash
# 在 ip 为 47.107.49.197 的服务器上执行 "pwd;git pull" 等命令
ssh root@47.107.49.197 "pwd;git pull;npm install;npm run build;"
- 使用 scp 将本地文件部署到服务器(scp 可以简单理解为 cp + ssh 的组合)
bash
# 将当前目录下的 dist 文件内容部署到服务器的 /root/demo.zuo11.com 目录
scp -r ./dist/* root@47.107.49.197:/root/demo.zuo11.com)
上面操作命令很简单,但相对麻烦的是连接远程服务器的鉴权问题,在上一篇介绍 Github Actions 部署时,我们有提到使用 ssh 私钥方式连接服务器并进行部署。这里再深入一点,通过纯 Linux 命令操作来理解 ssh 鉴权,一般鉴权分为两种
- ssh 密码登录
- ssh 私钥登录(相对更安全,但稍微麻烦一点)
ssh 密码登录
ssh 密码登录,只需要有服务器 ssh 登录的密码即可(一般可以在云服务器管理页面进行设置)
如图,由于 ssh 命令在执行时,需要人工操作输入密码,不适合自动化操作,因此一般会借助 sshpass 来自动填充密码,linux 系统不自带 sshpass,需要安装(另外 windows 不支持 sshpass)
bash
# CenterOS 安装 sshpass
yum install sshpass -y # 如果是 Ubuntu 使用 sudo apt-get install sshpass
新服务器第一次如果不进行下面这一步,后面的 sshpass 命令操作服务器可能不会有任何效果,加入参数 -o StrictHostKeyChecking=no 表示自动信任主机
bash
# 密码 123456 记得替换成自己的
sshpass -p 123456 ssh root@47.107.49.197 -o StrictHostKeyChecking=no
后面就可以愉快的操作服务器了,以下命令在阿里云 A 服务器上操作腾讯云 B 服务器,实测运行正常
bash
sshpass -p 123456 ssh root@47.107.49.197 "touch 3.txt"
sshpass -p 123456 scp -r ./dist/* root@47.107.49.197:/root/demo.zuo11.com
ssh 私钥登录
假设用电脑 A 通过 ssh 登录操作服务器 B,需要两步操作
-
查看电脑 A 是否已经生成过 ssh 公钥/私钥对(看电脑中是否有
~/.ssh/
目录是否有id_rsa
与id_rsa.pub
这两个文件),如果没有使用ssh-keygen
命令生成。 -
复制步骤 1 中生成的 ssh 公钥内容(~/.ssh/id_rsa.pub),登录到 B 服务器执行
echo "复制的公钥内容" >> ~/.ssh/authorized_keys
,将公钥内容追加到~/.ssh/authorized_keys
文件末尾
这样就可以直接使用 ssh/scp 操作服务器了
bash
ssh root@$CUSTOM_IP "rm -rf /root/demo.zuo11.com"
scp -r ./dist root@$CUSTOM_IP:/root/demo.zuo11.com
部署 vue3+vite 项目到腾讯云
以配置中心前端代码 zuo-config-fe 为例,将这个 vue3+vite 项目部署到腾讯云服务器,这里使用 sshpass 密码登录方式操作,需要在仓库的 Settings- CI/CD - Variables 中设置了三个变量
变量名 | 值 |
---|---|
PASSWORD | 目标服务器 ssh 登录密码 |
CUSTOM_USERNAME | 服务器用户名,我用的是 root |
CUSTOM_IP | 服务器 IP |
具体 .gitlab-ci.yml 配置如下
yml
image: node:16
stages:
- build
- deploy
cache: # 缓存
paths:
- node_modules
build-job:
stage: build
script:
- npm install
- npm run build
artifacts:
paths:
- dist
deploy-job:
stage: deploy
image: ringcentral/sshpass:latest
script:
- sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no -r ./dist/* $CUSTOM_USERNAME@$CUSTOM_IP:/root/demo.zuo11.com
由于 gitlab 自带的 shared runners 默认运行环境是 docker,上面会用到两个镜像,一个是 node 环境镜像 node:16
,一个是 sshpass 镜像 ringcentral/sshpass:latest
,因此把 build 和 deploy 拆成了两个 stage,不然就不支持 sshpass 命令。
提交后,会触发自动化部署,访问 demo.zuo11.com 即可看到最新内容
多环境配置
上面部署 vue3 项目到腾讯云服务器,具体操作是将 gitlab shared runners 中构建生成 dist,通过 scp 命令远程部署到腾讯云服务器的 /root/demo.zuo11.com 目录
要配置多环境,可以新开一个 demo-test.zuo11.com 域名,对应一个新的目录 /root/test/demo.zuo11.com,nginx 配置如下
conf
server {
listen 80;
server_name demo.zuo11.com;
charset utf-8;
location / {
root /root/demo.zuo11.com;
index index.html index.htm;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
break;
}
}
}
server {
listen 80;
server_name demo-test.zuo11.com;
charset utf-8;
location / {
root /root/test/demo.zuo11.com;
index index.html index.htm;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
break;
}
}
}
这里有一个坑,就是变量设置时不能勾选 Protected,不然 test 分支触发的 CI/CD 拿不到这个变量
修改 .gitlab-ci.yml 配置,支持多环境,使用 only 来限制部署的 job,如果是主分支部署到 /root/demo.zuo11.com,如果是 test 分支部署到 /root/test/demo.zuo11.com(注意:第一次操作时,如果服务器没有这个目录,需要在服务器创建)
yml
image: node:16
stages:
- build
- deploy
cache: # 缓存
paths:
- node_modules
build-job:
stage: build
script:
- npm install
- npm run build
artifacts:
paths:
- dist
deploy-job:
stage: deploy
image: ringcentral/sshpass:latest
script:
- sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no -r ./dist/* $CUSTOM_USERNAME@$CUSTOM_IP:/root/demo.zuo11.com
only:
- main
deploy-job-test:
stage: deploy
image: ringcentral/sshpass:latest
script:
- sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no -r ./dist/* $CUSTOM_USERNAME@$CUSTOM_IP:/root/test/demo.zuo11.com
only:
- test
test 分支提交后,部署效果如下,test 分支触发 deploy-job-test 任务,main 分支触发 deploy-job 任务
部署 koa 接口服务到腾讯云
上面是部署的前端项目,针对后端项目,部署思路如下
- 使用 scp 将最新代码 copy 到腾讯云服务器的特定目录
- (可选,如果是目标服务器是全新服务器)通过 ssh 执行 shell 命令,安装 node, nginx, pm2。
- 通过 ssh 执行 shell 命令:进入该目录,安装依赖,使用 pm2 重启接口服务
这里使用 zuo-config-server koa 接口服务项目来测试,.gitlab-ci.yml 配置如下(ssh 密码、服务器用户名、IP 变量设置这里就不赘述了,上面有介绍过)
yml
image: node:16
stages:
- deploy
cache: # 缓存
paths:
- node_modules
deploy-job:
stage: deploy
image: ringcentral/sshpass:latest
script:
- ls
- pwd
# 1、自动信任主机,执行远程服务器的 "pwd; ls",正好可以查看服务器目录、文件是否正常
- sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no $USER@$SERVER_IP "pwd;ls;"
# 2、将当前项目最新代码,复制到服务器指定目录
# 查看远程服务器是否有 zuo-config-server 目录,如果没有就创建
- sshpass -p $PASSWORD ssh $USER@$SERVER_IP "mkdir -p zuo-config-server;"
# copy 当前项目代码到服务器上的 /root/zuo-config-server 目录
- sshpass -p $PASSWORD scp -r ./* $USER@$SERVER_IP:/root/zuo-config-server
# 3、执行部署脚本
# 如果是目标服务器是全新服务器,在服务器上执行项目根目录的 deploy-first.sh 脚本
- sshpass -p $PASSWORD ssh $USER@$SERVER_IP 'bash -s' < ./deploy-first.sh
# 二次部署,在目标服务器执行 deploy.sh 部署脚本
- sshpass -p $PASSWORD ssh $USER@$SERVER_IP 'bash -s' < ./deploy.sh
部署脚本 deploy.sh 和 deploy-first.sh 和 .gitlab-ci.yml 都是在项目根目录,如下图
deploy-first.sh,新服务器,首次部署时安装 node、nginx、pm2,下一次部署时,就不用执行了
bash
yum install nodejs npm nginx -y;
npm install -g pm2;
deploy.sh 进入项目目录,安装依赖,使用 pm2 更新接口服务(这里目标服务器没有使用 git,而是在 gitlab shared runners 运行时,将项目最新代码通过 scp 拷贝到远程服务器的指定目录)
bash
# 安装依赖
cd /root/zuo-config-server;
npm install --production;
# 使用 pm2 重启服务
pm2 delete config.zuo11.com;
pm2 start src/index.js -n 'config.zuo11.com';
提交后,即可触发部署,通过服务器 ip、koa 接口服务开启端口 http://47.107.49.197:5000/share/test-deploy
,即可成功访问对应的接口,如下图
多环境配置
接口服务的多环境,可以使用一台新的服务器来做测试环境,不同的服务器 ip 对应不同的环境、域名
上图的 .gitalb-ci.yml 配置如下
- 新增了一个 TEST_SERVER_IP 变量表示测试环境的服务器 ip,密码和正式环境服务器一致。
- 这里并没有使用 only 来控制分支,而是使用两个 stage、手动触发一键部署。第一个 stage 用于部署到正式环境,第二个 stage 用于部署到测试环境。
yml
image: node:16
stages:
- deploy-prod
- deploy-test
deploy-job:
stage: deploy-prod
image: ringcentral/sshpass:latest
script:
- ls
- pwd
- sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no $USER@$SERVER_IP "pwd;ls;"
- sshpass -p $PASSWORD ssh $USER@$SERVER_IP "mkdir -p zuo-config-server;"
- sshpass -p $PASSWORD scp -r ./* $USER@$SERVER_IP:/root/zuo-config-server
- sshpass -p $PASSWORD ssh $USER@$SERVER_IP 'bash -s' < ./deploy-first.sh
- sshpass -p $PASSWORD ssh $USER@$SERVER_IP 'bash -s' < ./deploy.sh
when: manual
deploy-job:
stage: deploy-test
image: ringcentral/sshpass:latest
script:
- ls
- pwd
- sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no $USER@$TEST_SERVER_IP "pwd;ls;"
- sshpass -p $PASSWORD ssh $USER@$TEST_SERVER_IP "mkdir -p zuo-config-server;"
- sshpass -p $PASSWORD scp -r ./* $USER@$TEST_SERVER_IP:/root/zuo-config-server
- sshpass -p $PASSWORD ssh $USER@$TEST_SERVER_IP 'bash -s' < ./deploy-first.sh
- sshpass -p $PASSWORD ssh $USER@$TEST_SERVER_IP 'bash -s' < ./deploy.sh\
when: manual
test 分支,部署 log 如下图
更新代码,二次部署
服务器安装 gitlab runner 进行部署
上面介绍了使用 gitlab 共享 runner 执行 CI/CD 流程进行自动化部署,但共享 runner 的缺点在于有每月运行时长有限制,超过限制如果不付费就不能再使用,另外免费的共享 runner 性能也不高,部署时间相对会久一点。
因此,在自己的服务器上安装 gitlab runner 程序执行 CI/CD 流程,是有必要了解的。这里为了测试,我在阿里云创建了一个按量付费的 2核 CPU 4G 内存 5M 带宽
服务器,用于安装 gitlab runner 程序。使用几个小时成本不到 1 元。阿里云 ECS 创建
使用自定义 runner 部署
在 gitlab 仓库的设置 Settings - CI/CD - Runners 中,可以创建 Project runner,如下图
点击新建 runner
- 选择安装 gitlab runner 程序的服务器操作系统,我使用的是 CenterOs 服务器,选择 Linux
- 填写这个 runner 的 tag(我这里填的是
dev-zuo
),部署任务 Job 与 tag 关联,可以指定仅这个 runner 可以触发该 Job 执行 - 可选的 Details,可以给这个 runner 加一个描述
填写完上面的信息,点击创建 runner,会进入一个注册 runner 的引导页面,如下图
点击 How do I install GitLab Runner,会打开一个弹窗抽屉,教你怎么在服务器安装 gitlab runner 程序,命令如下
默认给的命令会有坑,如果完全按照官方给的执行,后面 CI/CD 会出现执行命令没权限的问题,建议直接使用 root),参考:gitlab-runner的无权限问题
bash
# 下载 gitlab-runner
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
# 给下载的 gitlab-runner 添加可执行权限
sudo chmod +x /usr/local/bin/gitlab-runner
# (有坑 - 不推荐)创建一个 GitLab Runner 用户
# useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
# (有坑 - 不推荐) 安装、运行 gitlab-runner
# gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
# 推荐直接使用 root 用户,方便命令执行,不然 CI/CD 时总是提示没权限
gitlab-runner install --working-directory /home/gitlab-runner --user root
gitlab-runner start
安装完成后,使用页面中给的命令注册 runner,这样可以将这个 runner 与当前的 gitlab 仓库关联
bash
gitlab-runner register
--url https://gitlab.com
--token glrt-i8xxxxxxxx # 这里直接 copy 页面中的指令,不同的用户,token 会不一样
运行效果如下图,会让你选择一个 runner executor,指定运行 CI/CD 使用的环境,这里我选的 shell
完成后,进入仓库 - 设置 - Runners 位置,即可看到 runner 状态,如下图
gitlab runner 服务器环境准备
由于我们上面选择的 excutor(执行器)为 shell,不像 docker 那样可以直接拉去 image 镜像,因此 gitlab runner 运行所依赖的命令都需要在服务器上安装,比如 git、node、npm 等
bash
# 我这里安装 gitlab runner 程序的服务器是 centos 7.6,如果是 ubuntu 需要用 apt-get
# 防止默认安装 git 1.x 版本
sudo yum install https://packages.endpointdev.com/rhel/7/os/x86_64/endpoint-repo.x86_64.rpm -y
# 安装 git、node 等
yum install nodejs npm git -y
git 版本需要注意,需要是 2.x 版本,不然可能会出现 fatal: git fetch-pack: expected shallow list
错误,参考:CentOS 7 升级 git 版本
部署 vitepress 到 oss(多环境)
这里使用 blog - gitlab 项目来测试,首先在 gitlab runner 所在的服务器安装阿里云 oss 命令行工具
bash
wget http://gosspublic.alicdn.com/ossutil/1.7.3/ossutil64 -O /usr/bin/ossutil64
chmod 755 /usr/bin/ossutil64
修改 .gitlab-ci.yml
- 增加 tags 标记,把原先 shared runner 中使用的 docker image 字段删除
- 由于 ossutil64 配置会指定 oss bucket 所在的地域 OSS_END_POINT,不同仓库所在的地域可能不一样,这里还是放到配置中,如果你的所有 oss bucket 都是固定在一个地区,可以把这个去掉,直接在服务器执行一次即可。
上图中的配置如下
yml
stages:
- deploy-prod
- deploy-dev
cache: # 缓存
paths:
- node_modules
deploy-job-prod:
stage: deploy-prod
tags:
- dev-zuo
script:
- npm install
- npm run build
# 配置 oss
- ossutil64 config -e $OSS_END_POINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET
# 部署制品文件到阿里云 oss test-zuo11-com 仓库
- ossutil64 cp -r -f ./.vitepress/dist oss://test-zuo11-com
when: manual
artifacts:
paths:
- ./.vitepress/dist
deploy-job-dev:
stage: deploy-dev
tags:
- dev-zuo
script:
- npm install
- npm run build
# 配置 oss
- ossutil64 config -e $OSS_END_POINT -i $OSS_ACCESS_KEY_ID -k $OSS_ACCESS_KEY_SECRET
# 部署制品文件到阿里云 oss test-zuo11-com-dev 仓库
- ossutil64 cp -r -f ./.vitepress/dist oss://test-zuo11-com-dev
when: manual
artifacts:
paths:
- ./.vitepress/dist
# ossutil64 用法
# -e endpoint, 设置Bucket所在地域的域名信息 OSS_END_POINT
# -i accessKeyID, 访问密钥的一部分,用于标识用户身份,以对命令请求进行身份验证。OSS_ACCESS_KEY_ID
# -k accessKeySecret, 访问OSS使用的访问凭证。OSS_ACCESS_KEY_SECRET
在 Job 中可以看到 runner 的 tag 标记
部署到,效果如下
部署 vue3 项目到其他服务器(多环境)
这里使用 zuo-config-fe - gitlab 前端项目进行部署测试。之前创建的 runner 是在 blog 这个仓库,在这个账号的 zuo-config-fe 这个仓库,设置中也能看到这个runner,点击 enable for this project 就可以使用这个 runner 了。
部署到其他服务器,这里用的 ssh 登录密码方式连接服务器,需要使用 sshpass 命令,要先在 gitlab runner 所在服务器进行安装
bash
yum install sshpass -y # CenterOS 安装命令, ubuntu 使用 apt-get
修改 .gitlab-ci.yml 配置,效果如下图
yml
stages:
- deploy-main
- deploy-test
cache: # 缓存
paths:
- node_modules
deploy-job:
stage: deploy-main
tags:
- dev-zuo
script:
- npm install
- npm run build
- sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no -r ./dist/* $CUSTOM_USERNAME@$CUSTOM_IP:/root/demo.zuo11.com
when: manual
artifacts:
paths:
- dist
deploy-job-test:
stage: deploy-test
tags:
- dev-zuo
script:
- npm install
- npm run build
- sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no -r ./dist/* $CUSTOM_USERNAME@$CUSTOM_IP:/root/test/demo.zuo11.com
when: manual
artifacts:
paths:
- dist
部署成功后,效果如下图
部署 vue3 项目到当前服务器
上面是使用 ssh 部署到其他服务器,如果是部署到 gitlab runner 程序所在的服务器,那就只需要把构建产物,复制到指定目录就可以了,如果执行 mkdir 等命令没权限,参考:gitlab-runner的无权限问题
yml
stages:
- deploy-main
- deploy-test
cache: # 缓存
paths:
- node_modules
deploy-job:
stage: deploy-main
tags:
- dev-zuo
script:
- npm install
- npm run build
- pwd;mkdir -p /root/prod/zuo-config-fe;
- rm -rf /root/prod/zuo-config-fe/*;cp -r ./dist/* /root/prod/zuo-config-fe/;
when: manual
artifacts:
paths:
- dist
deploy-job-test:
stage: deploy-test
tags:
- dev-zuo
script:
- npm install
- npm run build
- pwd;mkdir -p /root/test/zuo-config-fe;
- rm -rf /root/test/zuo-config-fe/*;cp -r ./dist/* /root/test/zuo-config-fe/;
when: manual
artifacts:
paths:
- dist
部署 koa 接口服务到腾讯云
这里还是使用 zuo-config-server koa 接口服务来测试部署,把上面使用 gitlab 共享 runner 部署的配置稍微修改下即可
yml
stages:
- deploy-prod
- deploy-test
deploy-job:
stage: deploy-prod
tags:
- dev-zuo
script:
- ls
- pwd
- sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no $USER@$SERVER_IP "pwd;ls;"
- sshpass -p $PASSWORD ssh $USER@$SERVER_IP "rm -rf zuo-config-server;mkdir -p zuo-config-server;"
- sshpass -p $PASSWORD scp -r ./* $USER@$SERVER_IP:/root/zuo-config-server
# - sshpass -p $PASSWORD ssh $USER@$SERVER_IP 'bash -s' < ./deploy-first.sh
- sshpass -p $PASSWORD ssh $USER@$SERVER_IP 'bash -s' < ./deploy.sh
when: manual
deploy-job-test:
stage: deploy-test
tags:
- dev-zuo
script:
- ls
- pwd
- sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no $USER@$TEST_SERVER_IP "pwd;ls;"
- sshpass -p $PASSWORD ssh $USER@$TEST_SERVER_IP "rm -rf zuo-config-server;mkdir -p zuo-config-server;"
- sshpass -p $PASSWORD scp -r ./* $USER@$TEST_SERVER_IP:/root/zuo-config-server
# - sshpass -p $PASSWORD ssh $USER@$TEST_SERVER_IP 'bash -s' < ./deploy-first.sh
- sshpass -p $PASSWORD ssh $USER@$TEST_SERVER_IP 'bash -s' < ./deploy.sh
when: manual
部署后,效果如下图
执行 log
两种 runner 部署耗时比对
从上面的截图可以看出自定义 runner 比共享 runner 部署耗时短很多,下面是一些数据对比
类别 | gitlab 共享 runner | 在自己服务器上安装 gitlab runner |
---|---|---|
oss 部署耗时 | 03:14 / 01:25(二次) | 00:45 |
vue3 前端项目部署耗时 | 04:20 / 02:28(二次) | 00:46 |
koa 接口部署耗时 | 02:57 / 01:10(二次) | 00:19 |
总结
上面我们使用 gitlab 共享 runner、自定义 runner 分别对三个项目进行了多环境 CI/CD 自动化部署实践,希望对大家有帮助,ღ( ´・ᴗ・` )比心