3. GitLab CI基础:.gitlab-ci.yml文件结构、Runner注册与配置、Pipeline与Job概念

好,咱们进入正题。GitLab CI 说白了就是一套自动化流水线的引擎。你写好配置文件,它负责跑。我刚开始接触的时候,觉得这东西挺玄乎,后来拆开一看,核心就三个东西:配置文件执行器(Runner)流水线(Pipeline)。今天咱们一个一个说清楚。

3.1 .gitlab-ci.yml 文件结构

这个文件是 GitLab CI 的灵魂。你把它放在项目根目录,GitLab 就会自动识别。我习惯叫它「流水线剧本」——你写什么,它就演什么。

核心结构:

  • stages:定义流水线的阶段顺序
  • Job:每个任务块,属于某个 stage
  • script:Job 要执行的命令
  • 全局配置:如 before_script、after_script、variables

来看一个最简单的例子:

stages:
  - build
  - test
  - deploy

build_job:
  stage: build
  script:
    - echo "编译代码..."
    - make build

test_job:
  stage: test
  script:
    - echo "运行测试..."
    - make test

deploy_job:
  stage: deploy
  script:
    - echo "部署到服务器..."
    - ./deploy.sh

嗯,这里要注意:Job 的名字可以随便起,但 stage 必须和 stages 里定义的一致。我见过有人把 stage 拼错了,结果 Job 一直不跑,排查了半天。

我的习惯:Job 命名用下划线分隔,比如 build_frontend、test_backend。这样一眼就能看出是干什么的。

3.2 Runner 注册与配置

Runner 是真正干活的机器。GitLab 本身不执行你的脚本,它把任务派发给 Runner。你可以用 GitLab 官方的共享 Runner,也可以自己搭。

我个人建议:生产环境一定要用自建 Runner。为什么?共享 Runner 的资源是有限的,排队能排到你怀疑人生。我曾经在项目高峰期,一个 Job 等了 40 分钟才轮到——从那以后,我再也没用过共享 Runner。

注册 Runner 的步骤

  1. 在 GitLab 项目里找到 Settings → CI/CD → Runners
  2. 拿到注册 token
  3. 在服务器上执行注册命令
# 安装 GitLab Runner(以 Ubuntu 为例)
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt-get install gitlab-runner

# 注册 Runner
sudo gitlab-runner register
# 输入 GitLab 实例 URL
# 输入注册 token
# 输入 Runner 描述(比如 "生产环境构建机")
# 选择执行器(我一般用 docker)
# 输入默认镜像(比如 alpine:latest)

避坑指南:我曾经注册完 Runner 后发现 Job 一直处于 pending 状态。后来发现是 Runner 的 tag 没设置对。如果你在 .gitlab-ci.yml 里指定了 tags,Runner 必须包含对应的 tag 才能接活。

Runner 的三种类型

类型 说明 适用场景
Shared Runner 所有项目共享 小团队、测试项目
Group Runner 组内项目共享 部门级项目
Specific Runner 仅限指定项目 生产环境、敏感项目

你想想看,如果公司有多个项目,用 Group Runner 最划算。既不用每个项目都配一台机器,又能保证资源隔离。

3.3 Pipeline 与 Job 概念

Pipeline 就是一次完整的流水线执行。它由多个 Job 组成,Job 按 stage 顺序执行。说白了,Pipeline 是「面」,Job 是「点」。

关键概念:

  • Pipeline:一次完整的 CI/CD 流程
  • Job:Pipeline 里的一个任务单元
  • Stage:Job 的逻辑分组,同 stage 的 Job 可以并行执行
  • Artifact:Job 产生的文件,可以传递给后续 Job

我画了一张图,帮你理清它们的关系:

Pipeline(一次完整流水线) Stage: build Job: compile Job: lint (并行执行) Stage: test Job: unit_test Job: integration Stage: deploy Job: deploy_prod Stage Job

这张图你看懂了吗?Pipeline 从左到右执行,每个 Stage 里的 Job 可以并行跑。比如 build 阶段,compile 和 lint 可以同时进行。等 build 全部完成后,才进入 test 阶段。

我的经验:合理利用并行能大幅缩短流水线时间。比如前端构建和后端构建没有依赖关系,就放在同一个 stage 里并行跑。我曾经把一个 15 分钟的流水线优化到 6 分钟,就是靠这个思路。

3.4 实战:一个完整的 .gitlab-ci.yml

光说不练假把式。咱们写一个真实项目会用到的配置:

stages:
  - install
  - test
  - build
  - deploy

variables:
  NODE_VERSION: "18"
  APP_NAME: "my-app"

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/

before_script:
  - node -v
  - npm -v

install_deps:
  stage: install
  script:
    - npm ci
  artifacts:
    paths:
      - node_modules/
    expire_in: 1 hour

run_lint:
  stage: test
  script:
    - npm run lint
  needs: [install_deps]

run_unit_test:
  stage: test
  script:
    - npm run test:unit
  needs: [install_deps]

build_app:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 day
  needs: [install_deps]

deploy_staging:
  stage: deploy
  script:
    - scp -r dist/* user@staging-server:/var/www/${APP_NAME}/
  only:
    - develop
  needs: [build_app]

deploy_production:
  stage: deploy
  script:
    - scp -r dist/* user@prod-server:/var/www/${APP_NAME}/
  only:
    - main
  when: manual
  needs: [build_app]

注意:deploy_production 我加了 when: manual,意思是需要手动点击才能执行。生产环境部署一定要加这个,防止手滑。我曾经有一次不小心 push 到 main 分支,结果自动部署到生产了……嗯,那天晚上我加班到凌晨两点。

3.5 常见问题与避坑

  • Job 一直 pending?检查 Runner 是否在线,tag 是否匹配。
  • Pipeline 卡住不动?看看是不是某个 stage 的 Job 失败了,默认情况下后续 stage 不会执行。
  • Artifact 太大?设置 expire_in 自动清理,不然磁盘会爆。
  • Runner 跑着跑着断了?检查服务器内存和磁盘,我遇到过好几次 OOM 导致 Runner 挂掉。

好了,GitLab CI 的基础就这些。你先把 .gitlab-ci.yml 写出来,注册一个 Runner,跑通第一个 Pipeline。后面咱们再聊更高级的玩法。


专注资料整理