实战分享:用CI/CD实现持续部署

cicd 的概念和优势

GitLab CI/CD 是一个使用持续方法进行软件开发的工具。

使用持续的软件开发方法,您可以不断地构建、测试和部署迭代代码更改。这个迭代过程有助于减少基于错误或失败的以前版本开发新代码的机会。使用这种方法,从开发新代码到部署新代码,您将努力减少人为干预,甚至根本不进行干预。

环境搭建

  • gitlab 安装服务器要求 2核4g

  • 需要安装的包

    • node 安装依赖、打包
    • nginx web 项目部署必须「正向代理、方向代理、负载均衡等等」、 GitLab 也会用到 Nginx(默认自动安装)
    • git 自动化部署,拉取代码
    • gitlab-runner 配合gitlab CI/CD使用的应用程序(runner 可以安装在别的服务器上)

安装node

下载和解压

bash 复制代码
# 下载安装包,需要哪个版本,在url中修改就可以了
wget https://nodejs.org/dist/v12.9.0/node-v12.9.0-linux-x64.tar.xz 

# 解压
tar xf node-v12.9.0-linux-x64.tar.xz

# 复制
cp -rf /root/node-v12.9.0-linux-x64 /usr/local/node

编辑配置

bash 复制代码
# 打开编辑配置文件
vim /etc/profile

# 在文件的最后,加上下面的内容
export PATH=$PATH:/usr/local/node

重载系统配置文件

bash 复制代码
source /etc/profile

安装git

Ubuntu 和 CentOs 下载有区别,目前以Ubuntu为例子

bash 复制代码
# 
sudo apt update
sudo apt install git
git --version

安装gitlab

gitlab包列表

bash 复制代码
下载
wget --content-disposition https://packages.gitlab.com/gitlab/gitlab-ce/packages/ubuntu/jammy/gitlab-ce_16.2.2-ce.0_amd64.deb/download.deb
# 解压
sudo dpkg -i gitlab-ce_16.2.2-ce.0_amd64.deb

修改配置文件

bash 复制代码
vim /etc/gitlab/gitlab.rb

修改一下信息

  • external_url 可以是域名,或者服务器IP,可以加端口,加端口时确保自己开放了对应的端口
bash 复制代码
external_url 'http://60.204.142.73:1874'
bash 复制代码
#重载配置文件,需要的时间比较长
sudo gitlab-ctl reconfigure

机器加上端口号

bash 复制代码
# 启动gitlab服务 
sudo gitlab-ctl start

gitlab常用命令

bash 复制代码
# 启动gitlab服务 
sudo gitlab-ctl start
# gitlab服务停止 
sudo gitlab-ctl stop
# 重启gitlab服务 
sudo gitlab-ctl restart

访问配置的地址 http://60.204.142.73:1874

  • 默认用户名是root
  • 密码在**/etc/gitlab/initial_root_password** 目录下 iV/KSiLgCl8YkRfl8AXbzKBJg05MyUHGOm1jQyz6EU0=
  • gitlab 代码在服务器存储路径 /var/opt/gitlab/git-data

至此,成功搭建gitlab

安装gitlab-runner

参考文章 juejin.cn/post/701774...

gitlab-runner 安装我放在了另一台服务器上,CentOs(也需要像上面步骤一样安装git node)

nginx

bash 复制代码
yum install -y nginx
systemctl start nginx.service

配置nginx

配置后执行 nginx -s reload

nginx 命令

nginx -s reload 重启

安装runner

gitlab-runner 下载目录 /usr/local/bin/gitlab-runner

gitlab-runner 安装目录 /home/gitlab-runner

bash 复制代码
# 下载
wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64

# 分配运行权限
chmod +x /usr/local/bin/gitlab-runner

# 创建用户
useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

# 安装
gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner

# 运行
gitlab-runner start 

注册 Shell Executor 类型 runner

bash 复制代码
# 注册 runner
gitlab-runner register

# 输入 gitlab 的访问地址
http://60.204.142.73:1874

# 输入 runner token,把开 http://60.204.142.73:1874/admin/runners 页面查看
49suDNTBzztDQ-kzvQY6

# runner 描述,随便填
测试webpack-vue项目部署

# runner tag
shellrunner

# 输入(选择) shell
shell

查看注册的runner

runner token 获取

gitlab-runner是如何工作的

新建项目,上传到搭建的gitlab

查看项目对应的runner

配置.gitlab-ci.yml文件

yml 复制代码
stages: # List of stages for jobs and their order of execution
  - build
  - deploy

build-job:
  stage: build
  script:
    - npm install
    - npm run build

查看pipeline

可以看到 runner先去拉取gitlab代码 放到/home/gitlab-runner/builds/ks_UxGnW/0/root/test-cice-myserver/ 目录下,然后执行yml对应的script

ks_UxGnW 是对应的runner名称

到服务器查看runner目录

我们看到了执行npm install生成的node_modulesbuild目录

完善yml

yml 复制代码
stages: # List of stages for jobs and their order of execution
  - build
  - deploy

build-job:
  stage: build
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

pages:
  stage: deploy # Set this new job to run in the `deploy` stage
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"

上面看到,即使执行了npm install 但是并没有存储下来,第二次jop 删除了生成的文件 Removing build/ Removing node_modules/

由此我们了解了gitlab-runner是如何工作的

学习gitlab-ci.yml配置

到此,CICD 环境已经搭建完成了

基本概念

pipelines是持续集成、交付和部署的顶级组件。

pipelines包含两部分:

  • Jobs:定义具体要做什么,例如编译,测试
  • Stages,定义jobs的执行顺序。

配置.gitlab-ci.yml后,会触发CI,执行pipeline

jobs

Pipeline配置始于job。job是. gitlab-ci. yml 文件中最基本的元素。

yml 语法

只有了解了yml的语法我们才能进行进一步的配置。

gitlab中文文档

关键字:

  • 全局关键字(配置pipeline使用)
关键字 说明
default job的自定义默认值
include 从其他 YAML 文件导入配置
stages pipeline 的阶段名称和顺序
variables 为pipeline中所有job定义CI/CD变量,
workflow 控制pipeline执行的类型
yml 复制代码
# default 示例
default: 
    image: ruby:3.0
  • job关键字
关键字 说明
after_script 覆盖作业后执行的一组命令
allow_failure 允许作业失败。失败的作业不会导致流水线失败。
artifacts 成功时附加到作业的文件和目录列表
cache 应在后续运行之间缓存的文件列表
coverage 给定作业的代码覆盖率设置
dast_configuration 在作业级别使用来自DAST配置文件的配置
dependencies 通过提供要从中获取产物的作业列表,来限制将哪些产物传递给特定作业。
environment 作业部署到环境的名称
except 控制何时不创建作业
extends 此作业继承自的配置条目
image 使用docker镜像
inherit 选择所有作业继承的全局默认值
interruptible 定义当新运行使作业变得多余时,是否可以取消作业。
needs 在 stage 顺序之前执行的作业
only 控制何时创建作业
pages 上传作业的结果,与 GitLab Pages 一起使用。
parallel 应该并行运行多少个作业实例。
release 指示运行器生成 release 对象。
resource_group 限制作业并发
retry 在失败的情况下可以自动重试作业的时间和次数
rules 用于评估和确定作业的选定属性以及它是否已创建的条件列表
script 由 runner 执行的 Shell 脚本。
secrets 作业所需的 CI/CD secret 信息。
services 使用 Docker 服务镜像。
stage 定义作业阶段。
tags 用于选择 runner 的标签列表。
timeout 定义优先于项目范围设置的自定义作业级别超时。
tags 用于选择 runner 的标签列表。
trigger 定义下游流水线触发器。
variables 在作业级别定义作业变量。
when 何时运行作业

gitlab-ci.yml 实战配置

artifacts

用于存储构建生成的结果,例如编译后的二进制文件、测试报告、构建产物等。Artifacts 是在作业级别生成并存储的,它们在作业完成后,可以供其他作业或管道阶段使用。Artifacts 可以被下载、浏览和保存在 GitLab 服务器上。

  • 定义每个作业的产物
  • 同一流水线后期的后续作业可以使用产物
  • 不同的项目不能共享产物
  • 默认情况下,产物会在30天后过期。您可以自定义到期时间
  • 如果启用了保留最新产物,则最新的产物不会过期。
  • 使用依赖来控制哪些作业获取工件。

下面的配置是把打包之后的产物 build提供给后面的作业使用

yml 复制代码
stages: # List of stages for jobs and their order of execution
  - build
  - deploy

build-job: # job的名称,自定义
  stage: build # job所处的阶段
  script: # 执行的脚本
    - npm install
    - npm run build
  artifacts: # 作业的产物
    paths:
      - "build/"

pages:
  stage: deploy # Set this new job to run in the `deploy` stage
  script:
    - cp -rf build/* /usr/web/test-cicd-myserver/ # 将打包后的文件放到对应的目录下

这是一个完整的部署配置

访问 http://150.158.75.248:3000/ 会看到部署的页面

cache

cache 是用于缓存构建过程中的依赖项,例如依赖库、依赖的软件包等。缓存是在不同的 CI/CD 作业之间共享的,以便加快构建过程的速度。当一个作业完成时,可以将特定的文件或目录缓存下来,以便在后续的作业中重复使用。当下一个作业执行时,它可以从缓存中检索所需的依赖项,而不是重新从头构建这些依赖项。Cache 是存储在 GitLab 服务器上的,并在作业级别进行管理。

yml 复制代码
stages: # List of stages for jobs and their order of execution
  - install_dependencies
  - build
  - deploy

install_dependencies:
  stage: install_dependencies
  cache:
    key: node_modules_cache
    paths:
      - node_modules/
  script:
    - npm install

build-job:
  stage: build
  cache:
    key: node_modules_cache
    paths:
      - node_modules/
  script:
    - npm run build
  artifacts: # 产物
    paths:
      - "build/"

pages:
  stage: deploy # Set this new job to run in the `deploy` stage
  script:
    - cp -rf build/* /usr/web/test-cicd-myserver/

缓存存在/home/gitlab-runner/cache/root/test-cice-myserver/目录下

第一次提交代码,runner执行的时候没有发现缓存,会继续执行npm isntall 下载依赖。当下次提交代码后,runner检测到有cache,不会再执行npm install脚本,节省发布时间

对比下没缓存和有缓存花费的总时间

下载依赖,build,都在同一个阶段只想

无缓存

yml 复制代码
stages: # List of stages for jobs and their order of execution
  - install_build

install_build:
  stage: install_build
  script:
    - npm install
    - npm run build
    - cp -rf build/* /usr/web/test-cicd-myserver/

执行时间

有缓存

yml 复制代码
stages: # List of stages for jobs and their order of execution
  - install_build

install_build:
  stage: install_build
  cache:
    key: node_modules_cache_v2
    paths:
      - node_modules/
  script:
    - npm install
    - npm run build
    - cp -rf build/* /usr/web/test-cicd-myserver/

由于项目是一个刚创建的项目,里面依赖的node包很少,所以看起来有缓存和无缓存差距不大,但是当项目越来越大,依赖的插件越来越多,缓存还是很有必要的

清除缓存

artifacts 和 cache 的区别

artifacts

paths 关键字确定将哪些文件添加到作业产物中。 文件和目录的所有路径都相对于创建作业的仓库。

yml 复制代码
build-job: 
  stage: build 
  script: 
    - npm run build 
  artifacts: # 产物 
    paths:
      - "build/"

cache

  • cache:paths选择要缓存的文件或目录

es: 缓存binaries下.apk后缀的文件和。config文件

yml 复制代码
rspec:
  script:
    - echo "This job uses a cache."
  cache:
    key: binaries-cache
    paths:
      - binaries/*.apk
      - .config
  • cache:key 给缓存一个唯一的标识(没有设置默认值为default) es:
yml 复制代码
cache-job:
  script:
    - echo "This job uses a cache."
  cache:
    key: binaries-cache-$CI_COMMIT_REF_SLUG
    paths:
      - binaries/

key值不能包含:

  • /符号或者 二进制

  • The / character, or the equivalent URI-encoded %2F.

  • Only the . character (any number), or the equivalent URI-encoded %2E.

  • cache:key:files 定义在一个或两个文件改变时重新生成

缓存存放的位置

docs.gitlab.com/ee/ci/cachi...

注册docker runner

yml

yml 复制代码
stages: # List of stages for jobs and their order of execution
  - install_build

install_build:
  stage: install_build
  # cache:
  #   key: node_modules_cache_v2
  #   paths:
  #     - node_modules/
  script:
    - npm install
    - npm run build
    - cp -rf build/* /usr/web/test-cicd-myserver/
  tags:
    - docker

因为服务器上没有安装docker,所有报错了。

centos 安装docker

安装docker

job

因为脚本是在docker中执行的,找不到/usr/web/test-cicd-myserver/

所以要换一种办法将dist包上传到服务器

配置 服务器gitlab-runner runner配置

bash 复制代码
vim /etc/gitlab-runner/config.toml

这样操作 docker容器里的 /builds/root/test-cicd-myserver 目录,服务器/usr/web/test-cicd-myserver也会同步

yml

bash 复制代码
stages: # List of stages for jobs and their order of execution
  - install_build

install_build:
  image: node:14
  stage: install_build
  script:
    - npm install
    - npm run build
    - echo $DEV_DEPLOY_HOST
    - rm -rf /builds/root/test-cicd-myserver/*
    - cp -r build/* /builds/root/test-cicd-myserver/
  tags:
    - docker

可以看到部署成功

上面使用了shell 和 docker 两种不同的runner,但是可以看到,runner 和部署后的dist包都是在同一台服务器上,但我们很多情况下是需要部署多台服务器,所以我们可以用先登录要部署的服务器,然后上传文件到目标服务器即可。

配置免密登录

本地生成一对秘钥

拿到秘钥,将它添加到gitlab 变量里面,分别命名为私钥 SSH_PRIVATE_KEY 和 公钥SSH_PUBLIC_KEY

配置 DEV_DEPLOY_HOST 自己要部署项目的服务器ip或域名 配置 ETC_HOSTS 值 StrictHostKeyChecking no 设置known_hosts新增公钥时不提示

另外配置SSH_CONFIG

配置yml

ba'sh 复制代码
stages: # List of stages for jobs and their order of execution
  - install_build

before_script:
  # 配置ssh,添加私钥,设置known_hosts新增公钥时不提示
  - mkdir -p ~/.ssh && chmod 700 ~/.ssh
  - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
  - echo "$SSH_PUBLIC_KEY" > ~/.ssh/id_rsa.pub && chmod 644 ~/.ssh/id_rsa.pub
  - echo "$SSH_CONFIG" >> ~/.ssh/config
  - echo "$ETC_HOSTS" >> /etc/hosts
  - cat ~/.ssh/known_hosts


install_build:
  image: node:14
  stage: install_build
  # cache:
  #   key: node_modules_cache_v2
  #   paths:
  #     - node_modules/
  script:
    - npm install
    - npm run build
    # 执行脚本 DEV_DEPLOY_HOST 为cicd预设变量
    - bash scripts/deploy.sh $DEV_DEPLOY_HOST 
  tags:
    - docker

scripts/deploy.sh

basg 复制代码
#!/bin/bash
set -e
cd `dirname $0` && cd ..

echo $0

pwd


# D_HOST='[email protected]'
# [email protected]
D_HOST=$1 

NOW=`date "+%Y%m%d_%H%M%S"`
PACKAGE_NAME="$NOW.tar.gz"
PACKAGE_DIR_SOURCE="build"

PACKAGE_DIR="test-cicd-myserver"
MY_PATH="/usr/web/"
D_PATH="/usr/web/"


# 修改文件名build(打包生成的)为test-cicd-myserver(服务器部署的文件目录名字),然后压缩,压缩后的文件名是当前时间命名的
mv $PACKAGE_DIR_SOURCE $PACKAGE_DIR && tar -zcf $PACKAGE_NAME $PACKAGE_DIR

# 上传压缩包到服务器/usr/web/目录下
scp $PACKAGE_NAME "$D_HOST:$D_PATH"
# 登录服务器,进入/usr/web/目录,删除旧的test-cicd-myserver ,解压缩上传的文件,至此新的打包内容就上传到了服务器
ssh "$D_HOST" "cd $D_PATH && rm -rf $PACKAGE_DIR && tar -zxf $PACKAGE_NAME && echo $PACKAGE_NAME successfully deployed!"

运行遇到问题,这是 让我们请教下chart-gpt

于是做出一下修改

bash 复制代码
stages: # List of stages for jobs and their order of execution
  - install_build

before_script:
  # 配置ssh,添加私钥,设置known_hosts新增公钥时不提示
  - mkdir -p ~/.ssh && chmod 700 ~/.ssh
  - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
  - echo "$SSH_PUBLIC_KEY" > ~/.ssh/id_rsa.pub && chmod 644 ~/.ssh/id_rsa.pub
  - echo "$SSH_CONFIG" >> ~/.ssh/config
  - echo "$ETC_HOSTS" >> /etc/hosts
  # 解决Host key verification failed.问题
  - ssh-keyscan 150.158.75.248 >> ~/.ssh/known_hosts
  - cat ~/.ssh/known_hosts


install_build:
  image: node:14
  stage: install_build
  # cache:
  #   key: node_modules_cache_v2
  #   paths:
  #     - node_modules/
  script:
    - npm install
    - npm run build
    # 执行脚本 DEV_DEPLOY_HOST 为cicd预设变量
    - bash scripts/deploy.sh $DEV_DEPLOY_HOST 
  tags:
    - docker

从新运行,可以看到成功啦

小总结

初次写这么长的文章,感觉写的逻辑有些混乱,自己对cicd 也不是非常熟悉,但这都是自己实际操作一遍写出的文章。

如果有同学看不懂或者写的不对地方,可随意指出,我一定改正。

参考文章

GitLab CI/CD 自动化部署入门 ,手把手教你搭建 ------ 从安装 Linux 到 GitLab 自动化部署

ubantu 安装gitlab www.jianshu.com/p/6cd5eecd8... cloud.tencent.com/developer/a...

相关推荐
JYeontu3 分钟前
浏览器书签还能一键下载B站视频封面?
前端·javascript
陈随易3 分钟前
Bun v1.2.16发布,内存优化,兼容提升,体验增强
前端·后端·程序员
聪明的水跃鱼4 分钟前
Nextjs15 基础配置使用
前端·next.js
happyCoder5 分钟前
如何判断用户设备-window.screen.width方式
前端
wearegogog1235 分钟前
Docker Buildx 简介与安装指南
运维·docker·容器
Sun_light11 分钟前
深入理解JavaScript中的「this」:从概念到实战
前端·javascript
小桥风满袖12 分钟前
Three.js-硬要自学系列33之专项学习基础材质
前端·css·three.js
聪明的水跃鱼17 分钟前
Nextjs15 构建API端点
前端·next.js
小明爱吃瓜34 分钟前
AI IDE(Copilot/Cursor/Trae)图生代码能力测评
前端·ai编程·trae
水冗水孚36 分钟前
🚀四种方案解决浏览器地址栏预览txt文本乱码问题🚀Content-Type: text/plain;没有charset=utf-8
javascript·nginx·node.js