系列文章: DevOps
  1. 1 API网关是什么?微服务的统一入口点
  2. 2 NAT是什么?计算机网络中的网络地址转换详解
  3. 3 GitLab CI/CD是什么?自动化构建、测试与部署流水线
  4. 4 Apache Kafka是什么?分布式事件流处理平台详解
  5. 5 Serverless是什么?FaaS、冷启动与何时选择无服务器架构
  6. 6 Subnet和CIDR是什么?IP网络分段与现代路由
  7. 7 什么是Kubernetes?当今最流行的容器编排平台
  8. 8 Proxy是什么?正向代理、反向代理与SOCKS5详解
  9. 9 什么是Nginx?集Web服务器、反向代理与负载均衡于一体
✦ 快速摘要
GitLab CI/CD 是 GitLab 内置的自动化平台,通过 .gitlab-ci.yml 配置文件在每次提交时触发构建、测试和部署流水线。了解 GitLab Runner、流水线结构及最佳实践。
这篇文章怎么样?

GitLab CI/CD 是内置于 GitLab 平台的流水线自动化系统——无需安装任何外部工具,只需在仓库根目录添加一个 .gitlab-ci.yml 文件,每次提交代码时就会自动触发构建、测试和部署的完整流程。

GitLab CI/CD 是什么?

GitLab CI/CD 是原生内置于 GitLab 的持续集成/持续交付平台,完全由仓库根目录下的 .gitlab-ci.yml 配置文件驱动。每当开发者推送代码或创建 Merge Request,GitLab 自动读取该文件,创建一条由多个 Stage(阶段)顺序执行的 Pipeline(流水线),每个 Stage 内可包含一个或多个并行运行的 Job(作业)。

流水线遵循 test → build → deploy 的经典模式。一旦某个 Job 失败,流水线立即停止并通知开发者——"快速失败"原则确保错误在尽可能早的阶段被捕获,防止问题代码进入生产环境。

GitLab 相较于 Jenkins 等独立 CI/CD 工具的核心优势在于:GitLab 将容器镜像仓库包仓库安全扫描(SAST、DAST)、环境管理部署追踪集成于同一平台,大幅减少了团队需要管理的工具数量。

CI/CD 是什么?持续集成与持续交付概述

.gitlab-ci.yml 的结构

整个流水线在一个 YAML 文件中定义。以下是一个将 Python 应用部署到 Kubernetes 的实际示例:

YAML
 1stages:
 2  - test
 3  - build
 4  - deploy
 5
 6variables:
 7  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
 8
 9# ── 阶段一:运行测试 ───────────────────────────────────────────
10test:
11  stage: test
12  image: python:3.11
13  script:
14    - pip install -r requirements.txt  # 安装依赖
15    - pytest tests/ -v                 # 运行测试
16  cache:
17    key: ${CI_COMMIT_REF_SLUG}
18    paths:
19      - .cache/pip                     # 缓存 pip 包,加速后续运行
20
21# ── 阶段二:构建 Docker 镜像并推送到 GitLab 镜像仓库 ──────────
22build:
23  stage: build
24  image: docker:24
25  services:
26    - docker:dind                      # 启用 Docker-in-Docker
27  script:
28    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
29    - docker build -t $DOCKER_IMAGE .  # 构建镜像
30    - docker push $DOCKER_IMAGE        # 推送到仓库
31  only:
32    - main                             # 仅在 main 分支触发
33
34# ── 阶段三:部署到 Kubernetes(手动确认) ─────────────────────
35deploy:
36  stage: deploy
37  script:
38    - kubectl set image deployment/myapp app=$DOCKER_IMAGE
39  environment:
40    name: production
41  when: manual                         # 需要人工点击确认
42  only:
43    - main

核心概念说明:

  • stages — 声明执行顺序。同一 Stage 内的 Job 并行运行;下一个 Stage 只有在上一个 Stage 全部成功后才会启动。
  • variables — 作用于整个流水线的环境变量。GitLab 还提供内置预定义变量,如 $CI_COMMIT_SHA$CI_REGISTRY_IMAGE$CI_COMMIT_REF_SLUG
  • image — 用作 Job 执行环境的 Docker 镜像,每个 Job 可使用不同的镜像。
  • services — 与 Job 并行运行的辅助容器(例如:docker:dind 允许在容器内构建 Docker 镜像)。
  • cache — 在多次流水线运行之间持久保存的目录,用于加速构建(.cache/pipnode_modules/)。
  • artifacts — Job 产生的输出文件,可传递给下游 Job 或在流水线完成后供下载。
  • only / rules — 控制 Job 触发条件(仅在 main 分支运行、仅在打 tag 时运行等)。
  • when: manual — Job 不会自动运行,需要有权限的人员在界面点击执行按钮——适合生产环境部署的审批门控。
  • environment — 将 Job 关联到 GitLab Environments 中的命名环境,支持部署历史追踪和一键回滚。

GitLab Runner

GitLab Runner 是安装在服务器(或容器/Kubernetes Pod)上的代理软件,负责从 GitLab 服务器接收 Job 并执行。Runner 持续轮询 GitLab,接收分配的 Job,克隆源代码,在已配置的执行器中运行脚本,最后将日志和退出码返回给 GitLab。

共享 Runner 与专用 Runner

共享 Runner 专用 Runner
管理方 GitLab(或组管理员) 您的团队
使用范围 实例内所有项目 特定项目或群组
资源 共享,高峰期可能排队 独享,无需排队
费用 按 CI 分钟计费 自有服务器成本
适合场景 小型项目、公共仓库 重度生产工作负载

Docker 执行器——最常用的选择

Docker 执行器在全新的 Docker 容器中运行每个 Job,确保每次运行的环境完全隔离且干净。这是大多数场景下推荐的执行器。

使用 Docker 执行器注册专用 Runner:

Bash
 1# 在 Ubuntu/Debian 上安装 GitLab Runner
 2curl -L --output /usr/local/bin/gitlab-runner \
 3  "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64"
 4chmod +x /usr/local/bin/gitlab-runner
 5
 6# 注册 Runner(在 Settings → CI/CD → Runners 获取 Token)
 7gitlab-runner register \
 8  --url "https://gitlab.com/" \
 9  --registration-token "YOUR_REGISTRATION_TOKEN" \
10  --executor "docker" \
11  --docker-image "alpine:latest" \
12  --description "my-docker-runner" \
13  --tag-list "docker,production"

注册完成后,Runner 出现在 Settings → CI/CD → Runners 中并开始接收 Job。使用**标签(tag)**将特定 Job 路由到特定 Runner——例如,生产部署 Job 只允许在打了 production 标签、部署在内网的 Runner 上执行。

Kubernetes 是什么?大规模容器编排

GitLab vs GitHub Actions vs Jenkins

对比维度 GitLab CI/CD GitHub Actions Jenkins
配置复杂度 低(内置) 低(内置) 高(需安装配置)
免费自托管 是(GitLab CE) 否(需 GitHub Enterprise) 是(开源)
免费云端额度 400 分钟/月 2,000 分钟/月
内置容器镜像仓库 是(GHCR)
内置安全扫描 是(SAST/DAST) 部分(CodeQL) 插件
配置语法 YAML (.gitlab-ci.yml) YAML (.github/workflows/) Groovy (Jenkinsfile)
市场/插件生态 GitLab 模板 20,000+ Actions 1,800+ 插件
最适合 自托管、一体化平台 GitHub 生态 企业本地部署

何时选择 GitLab CI/CD:

  • 项目需要将整个技术栈(代码 + CI/CD + 镜像仓库)自托管于本地环境。
  • 团队需要在同一平台内整合安全扫描、合规管理和审计追踪。
  • 金融科技、银行、医疗健康等行业需要 100% 的数据主权,所有数据必须保留在内部服务器。

何时选择 GitHub Actions:

  • 仓库已在 GitHub 上,希望零配置接入流水线。
  • 开源项目需要充裕的免费 CI 分钟数。
  • 需要与 GitHub 生态深度集成(Dependabot、CodeQL、GitHub Packages)。

何时选择 Jenkins:

  • 已在 Jenkins 插件和 Groovy 流水线上积累大量投资的传统企业环境。
  • 需要与多种代码管理系统集成(Bitbucket Server、Perforce、SVN)。

最佳实践

1. 缓存依赖以加速构建

YAML
 1# Python——缓存 pip 包
 2cache:
 3  key: ${CI_COMMIT_REF_SLUG}-pip
 4  paths:
 5    - .cache/pip
 6  policy: pull-push
 7
 8# Node.js——缓存 node_modules
 9cache:
10  key:
11    files:
12      - package-lock.json
13  paths:
14    - node_modules/

对于只读缓存的 Job,使用 policy: pull,避免每次 Job 结束后不必要的缓存上传。

2. 使用 needs: 实现并行化(DAG 流水线)

YAML
 1test-unit:
 2  stage: test
 3  script: pytest tests/unit/       # 运行单元测试
 4
 5test-integration:
 6  stage: test
 7  script: pytest tests/integration/ # 运行集成测试
 8
 9build:
10  stage: build
11  needs: [test-unit]               # test-unit 完成即可开始,无需等待 test-integration
12  script: docker build .

needs: 打破了传统的顺序 Stage 模型,让 build Job 在 test-unit 完成后立即启动,无需等待 test-integration,从而显著缩短流水线总耗时。

3. 保护生产环境

Settings → CI/CD → Environments → production 中配置:

  • 必要审批人数:生产部署需至少 1-2 名指定审批人确认。
  • 受保护分支:仅 mainrelease/* 分支可触发生产部署。
  • 部署冻结期:在流量高峰或重要假日期间禁止部署。

4. 启用内置 SAST 扫描

YAML
1include:
2  - template: Security/SAST.gitlab-ci.yml  # 引入官方 SAST 模板
3
4sast:
5  stage: test
6  variables:
7    SAST_EXCLUDED_PATHS: "tests/, docs/"   # 排除测试和文档目录

GitLab SAST 会自动为项目使用的语言选择合适的分析器(Python 使用 Bandit、JS/TS 使用 Semgrep、Java 使用 SpotBugs),无需额外配置。

5. 为生产部署设置手动审批门控

始终将 when: manualenvironment: production 结合使用。这在 GitLab 界面中创建了一个清晰的确认按钮,并记录完整的审计日志——谁触发了部署以及触发时间。

微服务是什么?分布式架构与实际应用

实际应用场景

初创企业——快速启动,无需专职运维

初创企业可以免费使用 GitLab.com(每月 400 分钟),配置一条基础的三阶段流水线:测试 → 构建 Docker 镜像 → 通过 SSH 部署到 VPS。所有配置集中在一个 .gitlab-ci.yml 文件中,从第一天起就无需专职 DevOps 工程师。随着规模扩大,只需对现有流水线结构做最小改动即可升级为 Kubernetes 部署。

银行与金融科技——自托管满足合规要求

金融机构需要将源代码、制品和日志完全保留在自有基础设施中。自托管 GitLab CE 实例提供:

  • 无流水线分钟限制 — 在内部服务器上自由运行流水线。
  • 数据不离开数据中心 — 源代码、Docker 镜像和流水线日志均保存在内部服务器。
  • 完整审计日志 — GitLab 记录每一个操作:谁提交了代码、谁批准了 Merge Request、谁触发了部署以及触发时间。
  • 集成 SAST 和密钥检测 — 意外提交到仓库的凭证信息在流水线内即刻被标记。

核心银行系统的典型流水线:sast → 单元测试 → 集成测试 → 构建镜像 → 推送到内部镜像仓库 → 部署预生产环境(自动)→ 部署生产环境(手动,需2人审批)

总结: 当您需要一个一体化平台——从代码管理到 CI/CD、容器镜像仓库和安全扫描——尤其是对数据主权要求严格的自托管项目,GitLab CI/CD 是极具竞争力的选择。从一个简单的 .gitlab-ci.yml 开始,随着团队成熟度的提升,逐步引入缓存、并行 Job 和手动审批门控。

常见问题

常见问题Q&A
GitLab CI/CD 和 GitHub Actions 有什么区别?
GitLab CI/CD 内置于 GitLab 平台,通过 .gitlab-ci.yml 配置,可运行在 GitLab.com(云端)或自托管实例上。GitHub Actions 与 GitHub 深度集成,使用类似的 YAML 语法,但以 workflow/job 替代 stages/jobs 的概念。主要区别在于:GitLab 在同一平台内集成了容器镜像仓库(Container Registry)、包仓库(Package Registry)和安全扫描(SAST/DAST);GitHub Actions 拥有更丰富的 Marketplace,且公共仓库的免费分钟数更多。需要将数据保留在本地的金融机构和银行通常选择 GitLab CE/EE,因为其私有化部署更为便捷。
GitLab Runner 是什么?
GitLab Runner 是安装在独立服务器(或容器/Kubernetes Pod)上的代理程序,负责轮询 GitLab 获取待执行的 Job 并运行它们。Runner 接收到 Job 后,拉取源代码,在已配置的执行器环境(Shell、Docker、Kubernetes、VirtualBox 等)中运行脚本,最后将日志和退出码返回给 GitLab。GitLab.com 提供共享 Runner,免费使用但有每月分钟限制;您也可以在自己的服务器上注册专用 Runner,获得完全的资源控制权且无分钟限制。
.gitlab-ci.yml 应该放在哪里?
.gitlab-ci.yml 文件必须放在仓库根目录下,与 README.md 和其他配置文件并列。GitLab 会在每次 push 或 Merge Request 事件时自动检测该文件。您可以在提交前通过浏览器内置的 CI Lint 工具(Settings → CI/CD → CI Lint)验证 YAML 语法。GitLab 还支持通过 include: 关键字将配置拆分为多个文件,从其他项目或内置的 GitLab CI/CD 模板库中引入模板。
流水线的 Job 可以并行运行吗?
可以。GitLab CI/CD 支持两种并行化方式:(1) 同一 Stage 内的 Job 在有足够 Runner 时默认并行运行。(2) needs: 关键字允许声明 Job 间的依赖关系——Job B 可以在 Job A 完成后立即启动,无需等待整个 Stage 结束,这称为 DAG(有向无环图)流水线。此外,parallel: matrix: 允许同一个 Job 以不同变量组合并行运行,非常适合跨浏览器测试或多版本兼容性测试。
GitLab CI 免费吗?
GitLab.com 的 Free 套餐每月提供 400 分钟共享 Runner CI/CD 时长。Premium 和 Ultimate 套餐提供更多分钟数及高级功能(完整 DAST、SAST、合规框架等)。如果您在自己的服务器上自托管 GitLab 社区版(CE),则没有分钟限制——使用量仅受服务器资源约束。这也是许多企业选择自托管 GitLab CE 的原因:无许可证费用,且流水线运行不受分钟限制。
GitLab CI 中 Artifact 和 Cache 有什么区别?
Artifact(制品)是 Job 产生的输出文件,由 GitLab 服务器保存并传递给下游 Job,或在流水线完成后供下载(例如已编译的二进制文件、测试报告)。Cache(缓存)是在多次流水线运行之间持久保存的目录(通常是 node_modules/ 或 .cache/pip),通过跳过重复的依赖下载来加速构建。Artifact 由 GitLab 服务器管理并支持过期策略;Cache 直接存储在 Runner 上,随时可能失效,因此您的流水线不应依赖 Cache 的存在来保证正确运行。