GitLab CI 基础:Pipeline、Job、Stage 概念解析

刚开始接触 GitLab CI 的时候,我其实挺懵的。什么 Pipeline、Job、Stage,一堆术语砸过来。后来我在一个实际项目里亲手搭了一套 Kotlin 回归测试流水线,才真正搞明白这些概念到底在说什么。

说白了,GitLab CI 的核心就是一套自动化任务编排系统。你写一个 .gitlab-ci.yml 文件,告诉 GitLab:「当代码 push 上来以后,先做什么,再做什么,最后做什么」。就这么简单。

一句话总结:Pipeline 是整个流程,Stage 是流程里的阶段,Job 是每个阶段里具体干活的单元。

Pipeline:整条流水线

Pipeline 翻译过来就是「管道」或「流水线」。我习惯把它想象成一条汽车生产线——从原材料进来,到零件组装,再到质量检测,最后成品下线。整个过程就是一个 Pipeline。

在 GitLab CI 里,每次你往仓库 push 代码,或者手动触发一次 CI,就会自动创建一个 Pipeline。这个 Pipeline 里可以包含多个 Stage,Stage 里又包含多个 Job。Pipeline 的状态取决于它里面所有 Job 的执行结果——只要有一个 Job 失败,整个 Pipeline 就是失败的。

我踩过的坑:有一回我写的 Pipeline 里有个 Job 跑了一个小时还没结束,结果整个 Pipeline 被 GitLab Runner 超时杀掉了。后来我学会了给关键 Job 加 timeout 参数,提前暴露问题。

Stage:流水线的阶段

Stage 就是 Pipeline 里的一个个阶段。比如一个典型的回归测试流水线,我会分成这几步:

  • build —— 编译 Kotlin 代码,生成 jar 包
  • unit-test —— 跑单元测试
  • integration-test —— 跑集成测试(这部分往往是回归测试重点)
  • deploy-staging —— 部署到测试环境

默认情况下,Stage 是顺序执行的。前一个 Stage 里所有 Job 都成功,才会执行下一个 Stage。但你可以通过 needs 关键字打破这个规则,让某些 Job 提前跑。

注意:Stage 的名字可以随便取,但不要用空格或特殊字符。而且多个 Stage 之间是有依赖关系的——如果你把部署放在编译前面,那部署 Job 肯定拿不到编译产物。

Job:具体干活的工人

Job 是最小执行单元。每个 Job 跑在一个独立的 Runner 容器里,互不干扰。一个 Stage 里可以定义多个 Job,它们默认是并行执行的。这很实用——比如「跑集成测试」这个 Stage,你可以同时跑数据库测试、API 测试、UI 测试,三个 Job 一起上,大大缩短流水线总时间。

来看一个最简示例:

stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - ./gradlew assemble

unit-test-job:
  stage: test
  script:
    - ./gradlew test

integration-test-job:
  stage: test
  script:
    - ./gradlew integrationTest

deploy-job:
  stage: deploy
  script:
    - ./gradlew deployToStaging

你看,test 这个 Stage 里有两个 Job,它们会同时启动。我实际项目中遇到过一个问题:两个 Job 同时访问同一个数据库,导致测试数据互相污染。嗯,那之后我学会了用 parallel 和资源隔离。

三者关系:一张图说清

GitLab CI 核心概念关系 Pipeline(流水线) Stage: build Job: compile Job: package (顺序执行) Stage: test Job: unit-test Job: integration-test (并行执行) Stage: deploy (只有前面所有 Job 都成功才会执行) 说明:Stage 之间默认顺序执行,同一 Stage 内的 Job 默认并行执行。通过 needs 等关键字可改变执行顺序。

一个小技巧:看清楚依赖关系

概念 类比 关键属性
Pipeline 整条生产流水线 由一次 push 或 API 触发,包含所有 Stage
Stage 流水线的某个工位 默认顺序执行,可配置并行
Job 工位上的工人 最小执行单元,每个 Job 独立容器运行

避坑指南:我曾经在一个大项目里把 20 个 Job 全放在同一个 Stage 里,结果 GitLab Runner 负载过高,好几个 Job 因为等待资源超时失败了。后来我把它们分散到多个 Stage,或使用 parallel: 5 分组执行,问题就解决了。

怎么查看 Pipeline 运行状态?

你 push 代码后,去项目的 CI/CD -> Pipelines 页面就能看到。每个 Pipeline 都有一个状态图标:绿色对号表示通过,红色叉号表示失败,橙色圆圈表示运行中。点进去可以看到每个 Stage 的详情,以及每个 Job 的控制台日志——这是调试问题的利器。

我个人的一个小习惯:在 Job 脚本里加 echo "::group::初始化环境" 之类的日志分组命令,让日志更好读。你想想看,如果某个 Job 失败了,日志打印了上千行,没有分组简直要命。

好,关于 Pipeline、Job、Stage 的基础概念就先讲这么多。记住那个关系图,后面的章节我们会动手写一个真实的 .gitlab-ci.yml,把 Kotlin 回归测试流水线跑起来。