部署CICD

CICD

每当我们将前端代码更新并 PUSH 到仓库后,CICD 将会拉取仓库代码并自动部署到服务器。

这就是 CICD 要做的事情。

  • CI,Continuous Integration,持续集成。
  • CD,Continuous Deployment,持续部署。(或者 Continuous Delivery,持续交付)

CICD 与 git 集成在一起,可理解为服务器端的 git hooks: 当代码 push 到远程仓库后,对当前代码在构建服务器(即 CI 服务器,也称作 Runner)中进行自动构建、测试及部署等。

为了方便理解,我们将上文章中用于部署的服务器称为部署服务器,而 CI 中所指的服务器,称为构建服务器。

  • 部署服务器: 对外提供服务的服务器,容器在该服务器中构建并启动。
  • 构建服务器: 进行CI构建的服务器,一般用以构建、测试和部署,构建镜像以及自动部署服务。一般也可以是 Docker 容器。

在以前的篇章中,相当于构建服务器和部署服务器为同一个服务器,而在工作中,二者往往为独立服务器。

但是为了更好的 CICD,构建服务器会赋予控制部署服务集群的权限,在构建服务器中通过一条命令,即可将某个服务在部署服务器集群中进行部署。

在 CICD 中,构建服务器往往会做以下工作:

  1. 功能分支提交后,通过 CICD 进行自动化测试、语法检查、npm 库风险审计等前端质量保障工程,如未通过 CICD,则无法 Code Review,更无法合并到生产环境分支进行上线
  2. 功能分支提交后,通过 CICD 对当前分支代码构建独立镜像,并生成独立的分支环境地址进行测试。如对每一个功能分支生成一个可供测试的地址,一般是 <branch>.xx.xx.com 此种地址
  3. 功能分支测试通过后,合并到主分支,自动构建镜像并部署到生成环境中 (一般生成环境需要手动触发、自动部署)

image-20230421172846125

Gitlab CICD Workflow
(opens new window)

  1. CI: 切出功能分支,进行新特性开发。此时为图中的 VerifyPackage 阶段
  2. CD: 合并功能分支,进行自动化部署。此时为图中的 Release 阶段。

    CICD 的基本术语

  • Runner: 用来执行 CI/CD 的构建服务器
  • workflow/pipeline: CI/CD 的工作流。(在大部分 CI,如 Gitlab 中为 Pipeline,而 Github 中为 Workflow,但二者实际上还是略有不同)
  • job: 任务,比如构建,测试和部署。每个 workflow/pipeline 由多个 job 组成

事件: on push

该 CI/CD 触发时的事件。如果需要上传代码自动部署的功能,应该选择 on: push

1
on: push

更多 Github Actions Event 可以参考官方文档 Events that trigger workflows(opens new window)

以下是 Github Actions 的一些时机的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 仅仅当 master 代码发生变更时,用以自动化部署
on:
push:
branches:
- master

# 仅当 feature/** 分支发生变更时,进行 Preview 功能分支部署
on:
push:
branches:
- 'feature/**'

# 仅当提交 PR 及提交后 feature/** 分支发生变更时,进行 Preview 功能分支部署
on:
pull_request:
types:
# 当新建了一个 PR 时
- opened
# 当提交 PR 的分支,未合并前并拥有新的 Commit 时
- synchronize
branches:
- 'feature/**'

# 在每天凌晨 0:30 处理一些事情,比如清理多余的 OSS 资源,清理多余的功能分支 Preview
on:
schedule:
- cron: '30 0 * * *'

在 Gitlab CI 中通过 rules (opens new window)进行配置,以下是 Gitlab CI 一些时机的示例:

1
2
3
4
5
6
7
8
9
10
# 仅仅当 master 代码发生变更时,用以自动化部署
rules:
- if: $CI_COMMIT_REF_NAME = "master"

# 仅当 feature/** 分支发生变更时,进行 Preview 功能分支部署 (见 Preview 篇)
rules:
- if: $CI_COMMIT_REF_NAME =~ /feature/

rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"

命令: Job 与脚本

如,在 push 到最新代码时,使用 docker-compose up 进行部署。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
name: push

on: [push]

jobs:
test:
# 将代码跑在 ubuntu 上
runs-on: ubuntu-latest
steps:
# 切出代码,使用该 Action 将可以拉取最新代码
- uses: actions/checkout@v2

# 运行部署的脚本命令
- run: docker-compose up -d

分支的合并策略 (主分支保护规则)

生产环境的代码必须通过 CI 检测才能上线,但这也需要我们进行手动设置。

一般而言,我们会设置以下策略加强代码的质量管理。

  1. 主分支禁止直接 PUSH 代码
  2. 代码都必须通过 PR 才能合并到主分支
  3. 分支必须 CI 成功才能合并到主分支
  4. 代码必须经过 Code Review (关于该 PR 下的所有 Review 必须解决)
  5. 代码必须两个人同意才能合并到主分支

在 Gitlab 与 Github 中均可进行设置:

如下示例,未通过 CI,不允许 Merge。可见示例 PR #22 (opens new window)

ssh案例

以下是对于简单部署在个人服务器的一个 Github Actions 的案例,由于构建服务器无部署服务器管理集群应用的能力与权限 (kubernetes 拥有这种能力)。如果部署到服务器,只能简单粗暴地通过 ssh 进入服务器并拉取代码执行命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
deploy:
runs-on: ubuntu-latest
steps:
- |
ssh root@xxx.xx.xx "
# 假设该仓库位于 ~/Documents 目录
cd ~/Documents/deploy

# 拉取最新代码
get fetch origin master
git reset --hard origin/master

# 部署
docker-compose up --build -d
"

自建 Runner

在本次实践中,将构建服务器与部署服务器置于一起,则可以解决这个问题。在 Github Actions,可以在自有服务器中自建 Runner,文档如下。

通过一些封装的命令来完成,分为三步:

  1. 构建镜像
  2. 推送镜像到自建的镜像仓库
  3. 将镜像仓库中的镜像拉取到部署服务器进行部署 (kubectl)
1
2
3
4
5
6
7
8
9
10
production:
# 该 JOB 在自建 Runner 中进行运行
runs-on: self-hosted
steps:
# 构建镜像
- docker build -t cra-deploy-app .
# 推送镜像
- docker push cra-deploy-app
# 拉取镜像并部署,deploy 为一个伪代码命令,在实际项目中可使用 helm、kubectl
- deploy cra-deploy-app .
感谢你的打赏哦!