如何使用github进行自动化不停机CI/CD
前言
最近在跟同学一起做一个产品,我们也没有什么钱,在做产品部署的时候想着能用免费的就用免费的了,于是就使用 github 完成了自动化 CI/CD 的蓝绿部署
思路
蓝绿部署本质上就是两份文件,一份是新版本另一份是老版本,在切换版本时候不停机不影响另一份。而 github 又有 actions 可以免费做 CI/CD 的操作,那我们就可以通过 github 的 actions 来操作我们服务器了。
步骤
github actions 脚本
-
在 github 仓库跟根目录下准备
.github/workflows/test-deploy.yaml,其中test-deploy可以替换成你的部署的文件名,但是结尾必须是.yaml -
我的 yaml 文件如下
name: 部署测试环境
on: push: branches: - develop # 或者是你想触发自动构建的分支 - feat/** # 可以写也可以不写path模块,它的意思是当修改的代码命中下列规则时才会执行脚本 paths: - "apps/server/**" - "apps/web/**" - ".github/workflows/test-delopy.yaml" # paths-ignore: # - 'apps/mini-program/**'
# 公共的env 参考https://github.com/easingthemes/ssh-deploy下的tipsenv: # 本地.ssh文件下的私钥id_rsa,存在secrets的PRIVATE_KEY中 SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_PRIVATE_KEY_TEST }} # 服务器域名/IP REMOTE_HOST: ${{ secrets.SERVER_HOST_TEST }} # 服务器端口 REMOTE_PORT: ${{ secrets.SERVER_PORT_TEST }} # 服务器默认用户名为root REMOTE_USER: ${{ secrets.SERVER_USER_TEST }}
jobs: test-deploy-server: runs-on: ubuntu-latest steps: - name: 检测仓库 uses: actions/checkout@v3
- name: 部署到服务器 uses: appleboy/ssh-action@master with: host: ${{ env.REMOTE_HOST }} port: ${{ env.REMOTE_PORT }} username: ${{ env.REMOTE_USER }} key: ${{ env.SSH_PRIVATE_KEY }} script: | set -e # 任何命令失败立即退出 cd /home/apps/sports ./deploy-server.sh上述的 yaml 文件表示当我的分支名命中develop或者是以feat开头时,并且我推送的代码的更改命中了 path 中声明的文件就会执行该 action,path 模块可以不写,不写的话表示只要命中了分支名就会执行该 action
env 模块表示引用了 secret 中的变量到 env 中,方便后续再 steps 中使用,方便统一管理。我的 env 模块引用了四个变量,分别是服务器的ssh连接密钥、服务器地址、服务器ssh端口、服务器用户名,其中服务器指的是你的代码要部署的服务器。
下面的 jobs 模块声明了一个部署任务:test-deploy-server,该部署任务主要工作是使用了appleboy/ssh-action@master带服务器上执行 shell 脚本,我们上述声明的环境变量就是在此处使用的。比较重要的是部署到服务器步骤中的script中的内容,它表示:到服务器的 /home/apps/sports目录下执行deploy-server.sh脚本。
deploy-server.sh 脚本
set -e # 任何命令失败立即退出# 加载了nvm的命令source /root/.nvm/nvm.sh# nvm使用了node24nvm use 24# 安装了pnpmnpm i -g pnpm# 也可以设置执行当前脚本时的环境变量例如NODE_ENVexport NODE_ENV=production
# 目录定义BLUE_DIR=/home/apps/sports/blueGREEN_DIR=/home/apps/sports/greenCURRENT_SYMLINK=/home/apps/sports/current
# 自动创建目录(首次部署时不存在)mkdir -p $BLUE_DIRmkdir -p $GREEN_DIR
# 判断当前指向如果当前指向蓝则将当前指向为绿if [ "$(readlink -f $CURRENT_SYMLINK)" == "$BLUE_DIR" ]; then NEW_DIR=$GREEN_DIRelse NEW_DIR=$BLUE_DIRfi
echo "Deploying to $NEW_DIR ..."
# 清空新目录并拉取代码rm -rf $NEW_DIRmkdir -p $NEW_DIR# 克隆当前的develop分支代码到新的文件夹中,当然也可以判断一下如果是首次就克隆后续可以直接pullgit clone -b develop git@github.com:zhaoyuqiqi/xxxx.git $NEW_DIRcd $NEW_DIRgit checkout develop
# 安装依赖 & 构建pnpm install
pnpm run build:server
# 数据库迁移pnpm run migrate:server
# 更新 symlinkln -sfn $NEW_DIR $CURRENT_SYMLINK
# PM2 reload(cluster 模式保证零停机)cd /home/apps# 通过机子上的PM2重新启动新项目pm2 reload pm2.config.js --only sports
echo "Deployment completed successfully."通过上述的步骤即可自动化部署一个零停机的 nodejs 应用,当然部署其他的也是类似的步骤,主要是通过了ln -sfn 地址A /home/apps/sports/current,将/home/apps/sports/current指向了地址 A,这个操作是瞬时的,并且在 pm2 的部署脚本中,部署的代码地址也是指向了/home/apps/sports/current所以可以做到切换当前目录后,直接重启 pm2 部署脚本即可。