本文介绍GitLab持续集成(CI)和持续交付(CD)。
持续集成内置于GitLab
持续集成
持续集成(Continuous Integration)指的是,频繁地(一天多次)将代码集成到主干。它的好处主要有两个:
- 尽快发现错误:每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。
- 防止分支大幅偏离主干:如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。
持续集成强调开发人员提交了新代码之后,立刻进行构建、(单元)测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。
持续交付
持续交付(Continuous Delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。
持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付的。
持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。比如,我们完成单元测试后,可以把代码部署到连接数据库的 Staging 环境中更多的测试。如果代码没有问题,可以继续手动部署到生产环境中
持续部署
持续部署(Continuous Deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。
持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。
持续部署的前提是能自动化完成测试、构建、部署等步骤。
GitLab CI / CD的优点
- 集成:GitLab CI / CD是GitLab的一部分,支持从计划到部署(甚至更多)的单个对话
- 开源:CI / CD是开源GitLab社区版和专有GitLab企业版的一部分
- 易于学习:请参阅官方快速入门指南
- 无缝:是单个GitLab应用程序的一部分,具有出色的用户体验
- 可扩展:测试可以在单独的计算机上分布式运行,可以根据需要添加任意数量的计算机
- 更快的结果:每个构建可以拆分为多个作业,这些作业可以在多台计算机上并行运行
- 针对交付进行了优化:多个阶段,手动部署入口,环境和变量
GitLab CI / CD的特征
- 多平台:可以在Unix,Windows,macOS和任何其他支持Go的平台上执行构建。
- 多国语言:构建脚本是命令行驱动的,并且可以与Java,PHP,Ruby,C和任何其他语言一起使用。
- 稳定:构建在与GitLab不同的机器上运行。
- 并行构建:GitLab CI / CD在多台机器上拆分构建,以实现快速执行。
- 实时日志记录:合并请求中的链接将您带到动态更新的当前构建日志。
- 灵活的管道:可以在每个阶段定义多个并行作业,并且可以触发其他构建。
- 版本管道:一个
.gitlab-ci.yml
文件包含测试,整个过程的步骤,使每个人都能贡献更改,并确保每个分支获得所需的管道。 - 自动缩放:可以自动旋转虚拟机,以确保立即处理您的构建并将成本降至最低。
- 构建工件:您可以将二进制文件和其他构建工件上传到GitLab并浏览和下载它们。
- 本地测试:有多个执行程序,可以在本地复制测试。
- Docker支持:可以使用自定义Docker镜像,作为测试的一部分启动服务,构建新的Docker镜像,甚至可以在Kubernetes上运行。
- 容器注册表:内置的容器注册表,用于存储,共享和使用容器镜像。
- 受保护的变量:在部署期间使用受每个环境保护的变量安全地存储和使用机密信息。
- 环境:定义多个环境,包括临时Review Apps请参阅每个环境的部署历史记录。
GitLab是整个DevOps生命周期的一个应用程序
- 使用GitLab Runners构建应用程序
- 运行单元和集成测试以检查代码是否有效
- 在合并到稳定版之前,使用Review Apps查看开发分支的实时预览
- 部署到暂存和生产等多个环境,并支持高级功能(例如canary deployments)
- 监视应用程序的性能和状态
与GitLab完全集成
- 快速的项目设置 单击添加项目,所有挂钩都通过GitLab API自动设置。
- 合并请求集成 在GitLab的合并请求中查看每个构建的状态。
架构
GitLab CI / CD 是GitLab的一部分,GitLab是具有API的Web应用程序,该API将其状态存储在数据库中。除了GitLab的所有功能之外,它还管理项目/构建并提供一个不错的用户界面。
GitLab Runner 是一个处理构建的应用程序。它可以单独部署,并通过API与GitLab CI / CD一起使用。
为了运行测试,至少需要一个 GitLab 实例和一个 GitLab Runner。
GitLab Runner
要执行实际的构建,需要安装用Go编写的GitLab Runner。
它可以在可以构建Go二进制文件的任何平台上运行,包括Linux,OSX,Windows,FreeBSD和Docker。
它可以测试任何编程语言,包括.Net,Java,Python,C,PHP等。
GitLab Runner具有许多功能,包括自动缩放,强大的Docker支持以及同时运行多个作业的能力。
持续集成的操作流程
提交
流程的第一步,是开发者向代码仓库提交代码。所有后面的步骤都始于本地代码的一次提交(commit)。
测试(第一轮)
代码仓库对 commit 操作配置了钩子(hook),只要提交代码或者合并进主干,就会跑自动化测试。
测试的种类:
- 单元测试:针对函数或模块的测试
- 集成测试:针对整体产品的某个功能的测试,又称功能测试
- 端对端测试:从用户界面直达数据库的全链路测试
第一轮至少要跑单元测试。
构建
通过第一轮测试,代码就可以合并进主干,就算可以交付了。
交付后,就先进行构建(build),再进入第二轮测试。所谓构建,指的是将源码转换为可以运行的实际代码,比如安装依赖,配置各种资源(样式表、JS脚本、图片)等等。
测试(第二轮)
构建完成,就要进行第二轮测试。如果第一轮已经涵盖了所有测试内容,第二轮可以省略,当然,这时构建步骤也要移到第一轮测试前面。
第二轮是全面测试,单元测试和集成测试都会跑,有条件的话,也要做端对端测试。所有测试以自动化为主,少数无法自动化的测试用例,就要人工跑。
需要强调的是,新版本的每一个更新点都必须测试到。如果测试的覆盖率不高,进入后面的部署阶段后,很可能会出现严重的问题。
部署
通过了第二轮测试,当前代码就是一个可以直接部署的版本(artifact)。
回滚
一旦当前版本发生问题,就要回滚到上一个版本的构建结果。最简单的做法就是修改一下符号链接,指向上一个版本的目录。
使用 GitLab 持续集成
从 GitLab 8.0 开始,GitLab CI 就已经集成在 GitLab 中,我们只要在项目中添加一个 .gitlab-ci.yml 文件,然后添加一个 Runner,即可进行持续集成。 而且随着 GitLab 的升级,GitLab CI 变得越来越强大。
Pipeline
一次 Pipeline 其实相当于一次构建任务,里面可以包含多个流程,如安装依赖、运行测试、编译、部署测试服务器、部署生产服务器等流程。
任何提交或者 Merge Request 的合并都可以触发 Pipeline,如下图所示:
+------------------+ +----------------+
| | trigger | |
| Commit / MR +---------->+ Pipeline |
| | | |
+------------------+ +----------------+
Stages
Stages 表示构建阶段,说白了就是上面提到的流程。我们可以在一次 Pipeline 中定义多个 Stages,这些 Stages 会有以下特点:
- 所有 Stages 会按照顺序运行,即当一个 Stage 完成后,下一个 Stage 才会开始
- 只有当所有 Stages 完成后,该构建任务 (Pipeline) 才会成功
- 如果任何一个 Stage 失败,那么后面的 Stages 不会执行,该构建任务 (Pipeline) 失败
因此,Stages 和 Pipeline 的关系就是:
+--------------------------------------------------------+
| |
| Pipeline |
| |
| +-----------+ +------------+ +------------+ |
| | Stage 1 |---->| Stage 2 |----->| Stage 3 | |
| +-----------+ +------------+ +------------+ |
| |
+--------------------------------------------------------+
Jobs
Jobs 表示构建工作,表示某个 Stage 里面执行的工作。我们可以在 Stages 里面定义多个 Jobs,这些 Jobs 会有以下特点:
- 相同 Stage 中的 Jobs 会并行执行
- 相同 Stage 中的 Jobs 都执行成功时,该 Stage 才会成功
- 如果任何一个 Job 失败,那么该 Stage 失败,即该构建任务 (Pipeline) 失败
所以,Jobs 和 Stage 的关系图就是:
+------------------------------------------+
| |
| Stage 1 |
| |
| +---------+ +---------+ +---------+ |
| | Job 1 | | Job 2 | | Job 3 | |
| +---------+ +---------+ +---------+ |
| |
+------------------------------------------+