# GitOps 下的 CI/CD 流程
CI/CD 是架构中非常重要的一个组件,在云原生时代,依托于容器化持续集成,改变了以往应用通过 Jar、war 包形式的部署方式,转而制作成镜像,通过集成 GitLab CI、镜像仓库、Kubernetes 、Argo CD 等各类效率、流程系统,对纳管集群进行镜像发布、应用验证、升级,进而实现了自动化和监控贯穿于应用迭代的整个生命周期。
## 什么是 CI/CD
CI(Continuous Intergration,持续集成),强调开发人员不断进行代码提交、单元测试、性能测试、代码扫描等操作,根据测试结果,发现问题及时回滚,并进行反馈。
持续部署 (Continuous Deployment,CD)或者说持续交付(Continuous Delivery,CD),是指在构建和测试完成通过后,通过一系列系统化手段让最新的功能能够尽快地更新到生产环境,并通过运营反馈需求,促进产品进一步迭代。持续部署需要保障整个过程的平滑和安全,通常借助蓝绿发布、金丝雀发布确保过程中的平滑、安全以及降低部署过程出错的概率。
总结来说,持续集成、持续部署与持续交付,是一种通过在应用开发阶段引入自动化,实现频繁交付应用的方法。
## GitOps 下的 CI/CD 流程
鉴于 GitOps 的设计哲学,我们看一下 GitOps 下的 CI/CD 流程,如下图所示:
<div align="center">
<img src="https://wiki.waringid.me/download/attachments/5636503/gitops-workflow.webp" width = "550" align=center />
</div>
- 首先,团队成员都可以 fork 仓库对配置进行更改,然后提交 Pull Request。
- 接下来运行 CI 流水线,进行校验配置文件、执行自动化测试、构建 OCI 镜像、推送到镜像仓库等。
- CI 流水线执行完成后,拥有合并代码权限的人会将 Pull Request 合并到主分支。
- 最后运行 CD 流水线,结合 CD 工具(例如 Argo CD)将变更自动应用到目标集群中。
整个过程中完全自动化且操作透明,通过多人协作和自动化测试来保证了基础设施声明的健壮性。另外由于基础设置配置都存储在 Git 仓库中,当应用出现故障时,也可快速地进行版本回退。
## CI/CD 中的工具链
在 CI/CD 工程实施中,Jenkins 和 Gitlab 已成为流程中的核心工具,其中 Jenkins 。现如今的 CI/CD 中,集合容器技术、镜像仓库、容器编排系统等各类工具链,已成为企业、各类组织效率提升必不可少的基础支撑。
<div align="center">
<img src="https://wiki.waringid.me/download/attachments/5636503/cicd-tools.png" width = "600" align=center />
<p>图:CI/CD 典型工具链</p>
</div>
目前,CI/CD 典型的工具链包括持续集成、持续交付、持续部署与基础工具类。
### 基础工具
Jenkins 是一个被广泛使用的可扩展的持续集引擎,提供了数以百计的插件来支持自动化构建、测试、部署相关的各类任务,Jenkins 在 2.0 版本中提供的流水线即代码(Pipeline as Code) 能力。贯穿于 CI/CD 整个过程,将原本独立运行与单个或多个节点的任务串联起来,从而实现单个任务难以完成的复杂发布流程。
Prometheus 是新一代的云原生监控系统,它是一个开源的完整监控解决方案,对传统的监控系统测试、告警模型进行了彻底颠覆的重新设计,形成了基于中央化的规则计算、统一分析和告警的新一模型。
为了实现统一的用户管理和权限管理,我们需要引入一套统一的用户管理系统,OpenLDAP 则是目前较为广泛应用的系统。
### 持续集成
典型的源码管理工具是 Gitlab,同时也可以完成代码评审等工作。
代码构建根据编程语言不同而不同,譬如 Java 构建工具包括 Maven、Gradle。单元测试框架 如 JUnit、TestNG 等。
制品仓库代表性产品为 Nexus,Nexus 可以支持多种私有仓库,包括 maven、nuget、docker、npm、bower、pypi、rubygems、go 等。
镜像仓库目前使用最广泛的 是 VMware 开源的 Harbor。Harbor 是一个用于存储和镜像分发的企业级镜像服务端软件,它添加了很多企业必须的功能特性,例如安全、标识和管理等。
代码质量管理使用最广泛的开源工具是 SonarQube, 它可以用代码风格、缺陷、漏洞、以及安全热点等几个维度对源代码进行扫码和分析。
# 持续集成
持续集成是系统持续提供可交付版本软件并且保证软件质量的一种开发方法。
它主张开发人员尽可能早、快地将各自开发的代码集成起来,每次集成都通过自动化的构建(包括静态代码扫描、编译、自动化测试、发布等)来进行质量验证,从而尽可能早地发现集成错误,避免项目延期以及不可预测的质量风险等。
持续集成系统的价值在于完全自动化构建和自动化测试,在微服务持续集成中,包含的关键要素为源代码库、持续集成机系统、自动化测试系统。
一个典型的持续集成过程为:开发团队基于源代码库(如 Git)建立持续集成系统,当团队成员对源代码就行更新并提交到源码库之后,持续集成系统先从版本控制服务器下载更新后的代码,调用自动化编译脚本进行编译,并运行开发人员预先编写的自动化测试脚本,最后将测试结果生成报告反馈给开发团队,开发团队根据反馈结果进行下一轮的代码迭代更新,并触发新一轮的持续集成过程。
GitLab CI 是为 Gitlab 提供持续集成的一整套系统,
<div align="center">
<img src="https://wiki.waringid.me/download/attachments/5636503/CI.png" width = "550" align=center />
</div>
## 流水线(Pipeline)
流水线是一个分成不同阶段(Stage)的作业(Job)的集合。一次 Pipeline 其实相当于一次构建任务,里面可以包含多个流程,如安装依赖、运行测试、编译、部署测试服务器、部署生产服务器等流程。任何提交或者 Merge Request 的合并都可以触发 Pipeline。
## Stages
Stages 表示构建阶段,说白了就是上面提到的流程。 我们可以在一次 Pipeline 中定义多个 Stages,这些 Stages 会有以下特点:
- 所有 Stages 会按照顺序运行,即当一个 Stage 完成后,下一个 Stage 才会开始
- 只有当所有 Stages 完成后,该构建任务 (Pipeline) 才会成功
- 如果任何一个 Stage 失败,那么后面的 Stages 不会执行,该构建任务 (Pipeline) 失败
## Jobs
Jobs 表示构建工作,表示某个 Stage 里面执行的工作。 我们可以在 Stages 里面定义多个 Jobs,这些 Jobs 会有以下特点:
- 相同 Stage 中的 Jobs 会并行执行
- 相同 Stage 中的 Jobs 都执行成功时,该 Stage 才会成功
- 如果任何一个 Job 失败,那么该 Stage 失败,即该构建任务 (Pipeline) 失败
## GitLab Runner
理解了上面的基本概念之后,还有一个问题,由谁来执行这些构建任务呢? 答案就是 GitLab Runner !
GitLab CI 最大的作用是管理各个项目的构建状态,因此,运行构建任务这种浪费资源的事情就交给 GitLab Runner 来做拉! 因为 GitLab Runner 可以安装到不同的机器上,所以在构建任务运行期间并不会影响到 GitLab 的性能
## .gitlab-ci.yml
配置好 Runner 之后,我们要做的事情就是在项目根目录中添加 .gitlab-ci.yml 文件。 当我们添加了 .gitlab-ci.yml 文件后,每次提交代码或者合并 MR 都会自动运行构建任务。
```plain
# 定义 stages
stages:
- build
- test
# 定义 job
job1:
stage: test
script:
- echo "I am job1"
- echo "I am in test stage"
# 定义 job
job2:
stage: build
script:
- echo "I am job2"
- echo "I am in build stage"
```
用 stages 关键字来定义 Pipeline 中的各个构建阶段,然后用一些非关键字来定义 jobs。 每个 job 中可以可以再用 stage 关键字来指定该 job 对应哪个 stage。 job 里面的 script 关键字是最关键的地方了,也是每个 job 中必须要包含的,它表示每个 job 要执行的命令。
```plain
I am job2
I am in build stage
I am job1
I am in test stage
```
### 持续交付
接口测试可以使用 Python 编写的功能自动化测试框架 RobotFramework,它具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端和接口,也可以进行分布式测试。
性能测试类工具可以使用 Java 开发的 JMeter,它可以对服务器、网络、或者对象模拟请求负载来测试他们的强度或者分析不同压力下整体性能。
### 持续部署
使用 Kebernetes 的配置功能(configmap、Secret)做配置管理。
可以使用 Helm 打包应用,管理应用的依赖关系,管理应用版本并发布应用到软件仓库。
Operator 是基于 Kebernetes 编写的也定应用程序控制器,它用来创建、配置和管理复杂的有状态应用,如数据库、缓存和监控系统。Operator 是将运维人员对软件操作代码化,同时利用 Kebernetes 强大的抽象来实现应用的生命周期管理。
|