GitLab CI 面试题
40 道题- 分类
- DevOps
- 题目数
- 40 道
1 Pipeline / Stage / Job 的定义与关系
答案:
GitLab CI/CD 以 Pipeline 为核心执行单元,由 Stage 和 Job 组成三层结构。
| 层级 | 定义 | 职责 |
|---|---|---|
| Pipeline | 一次完整的 CI/CD 执行实例 | 关联一个 commit 或事件,包含全量自动化流程 |
| Stage | Pipeline 内的阶段分组 | 定义执行顺序,同一 Stage 的 Job 并行执行 |
| Job | 最小的执行单元 | 运行具体命令或脚本,绑定 Runner 执行 |
执行流程:
Commit Push --> Pipeline Created --> Stage[build] (并行 jobs) --> Stage[test] (并行 jobs) --> Stage[deploy] (并行 jobs)
- 所有 Job 在同一 Stage 中并行执行。
- 前一 Stage 所有 Job 成功后,下一 Stage 开始执行。
- 任一 Job 失败,Pipeline 中止(除非配置 allow_failure)。
适用场景: 多阶段流水线标准化交付流程,构建、测试、部署各阶段隔离执行。
2 .gitlab-ci.yml 文件结构
答案:
.gitlab-ci.yml 是 GitLab CI/CD 的声明式配置文件,采用 YAML 格式,定义 Pipeline 的全部行为。
stages: # 定义所有 Stage 及执行顺序
- build
- test
- deploy
variables: # 全局变量定义
IMAGE_TAG: $CI_COMMIT_SHORT_SHA
before_script: # 每个 Job 执行前运行的全局脚本
- echo "Starting job"
after_script: # 每个 Job 执行后运行的全局脚本
- echo "Job finished"
cache: # 全局缓存配置
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
job_name: # Job 定义
stage: build
script:
- docker build -t app:$IMAGE_TAG .
only:
- main
核心顶层关键字:
| 关键字 | 说明 |
|---|---|
| stages | 定义 Stage 列表与执行顺序 |
| variables | 声明 CI/CD 变量 |
| cache | 文件和目录缓存配置 |
| before_script / after_script | 全局前置 / 后置脚本 |
| include | 引入外部 YAML 模板 |
| workflow | Pipeline 级别的执行规则控制 |
| default | 所有 Job 的默认配置 |
3 Stage 执行顺序与失败策略
答案:
Stage 按 .gitlab-ci.yml 中 stages 列表顺序串行执行,同 Stage 内 Job 并行执行。
执行策略:
stages:
- build
- test
- deploy
| 场景 | 行为 |
|---|---|
| build 全部成功 | 进入 test stage |
| build 任一失败 | Pipeline 中止,跳过 test 和 deploy |
| 配置 allow_failure: true | Job 失败不影响 Pipeline 继续执行 |
| 手动触发 stage(when: manual) | 需人工确认后执行 |
配置示例:
build_job:
stage: build
script: make build
test_job:
stage: test
script: make test
allow_failure: true
deploy_job:
stage: deploy
script: make deploy
when: manual
4 Runner 类型对比
答案:
GitLab Runner 按注册范围分为三种类型。
| 类型 | 可见范围 | 适用场景 |
|---|---|---|
| Shared Runner | 整个 GitLab 实例 | 通用构建任务,多项目共享 |
| Group Runner | 一个 Group 内所有项目 | 部门级统一构建环境 |
| Project Runner | 单一项目独享 | 定制化构建需求,独立环境隔离 |
选择依据:
- Shared Runner 资源利用率高,适合标准构建环境。
- Group Runner 适合组织级统一构建镜像和策略。
- Project Runner 适合特殊硬件依赖或安全隔离要求。
注册命令示例:
gitlab-runner register \
--url https://gitlab.example.com \
--registration-token $TOKEN \
--executor docker \
--description "project-runner-1"
5 Runner Executor 类型对比
答案:
Executor 决定 Job 在何种环境中执行。
| Executor | 隔离机制 | 适用场景 |
|---|---|---|
| Docker | 容器隔离 | 通用 CI/CD,环境一致性强 |
| Kubernetes | Pod 隔离 | 云原生环境,弹性伸缩 |
| Shell | 进程隔离 | 简单任务,低 overhead |
| SSH | 远程主机 | 已有基础设施,免 Agent 部署 |
| Parallels | 虚拟机 | macOS 构建,iOS 编译 |
| VirtualBox | 虚拟机 | 完整系统测试 |
选型原则:
- Docker Executor 是默认首选,通过 image 指定运行环境,s 配置卷挂载和服务链接。
- K8s Executor 适合大规模 CI 集群,自动扩缩容,无需管理 Runner 主机。
- Shell Executor 不适合非信任 Job,存在环境污染风险。
- 同一 Runner 可注册多个 Executor 类型,通过 tags 分配。
6 Cache 与 Artifact 的区别
答案:
Cache 和 Artifact 均为文件传递机制,用途和生命周期不同。
| 特性 | Cache | Artifact |
|---|---|---|
| 目的 | 加速依赖安装,避免重复下载 | 传递 Job 产出物,供后续 Job 或下载 |
| 跨 Pipeline | 支持,key 相同可复用 | 不跨 Pipeline |
| 过期策略 | 自动清理,LRU 淘汰 | 设置 expire_in |
| 手动下载 | 不支持 | 支持 Web UI 和 API 下载 |
| 典型场景 | node_modules, vendor/bundle | 编译产物 JAR/WAR, 镜像, 报告 |
配置示例:
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository/
build_job:
stage: build
script: mvn package
artifacts:
paths:
- target/*.jar
expire_in: 30 days
7 rules 条件控制
答案:
rules 关键字控制 Job 在何种条件下加入 Pipeline,替代已废弃的 only/except。
job:
script: echo "Hello"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: always
- if: $CI_COMMIT_BRANCH == "main"
when: manual
- when: never
规则类型:
| 条件 | 说明 |
|---|---|
| if | 基于 CI/CD 变量表达式的条件判断 |
| changes | 检测特定文件路径是否变更 |
| exists | 检测仓库中是否存在指定文件 |
| allow_failure | 规则匹配时是否允许 Job 失败 |
| variables | 规则匹配时注入自定义变量 |
评估顺序:
- 按 rules 列表顺序从上到下逐条匹配。
- 匹配成功后使用该规则的 when 策略,不再继续评估。
- 末尾未匹配时,若未设置 when:never,默认 Job 加入 Pipeline。
8 only/except 与 rules 对比
答案:
only/except 是 GitLab 12.3 之前的条件控制语法,rules 为其替代方案。
| 特性 | only/except | rules |
|---|---|---|
| 变量表达式 | 有限支持 | 完整支持 $VAR == "value" |
| 多条件组合 | 不支持 AND/OR | 支持复杂逻辑 |
| changes 检测 | 基本支持 | 增强支持 |
| when 策略 | 仅全局 | 逐规则独立配置 |
| 维护状态 | 废弃 | 推荐 |
迁移示例:
# 旧语法
job:
only:
- main
except:
- tags
# 等价新语法
job:
rules:
- if: $CI_COMMIT_TAG
when: never
- if: $CI_COMMIT_BRANCH == "main"
when: always
9 CI/CD Variable 优先级
答案:
GitLab CI/CD 变量存在多层覆盖关系,高优先级覆盖低优先级同名变量。
优先级(从低到高):
| 优先级 | 变量来源 | 说明 |
|---|---|---|
| 1 | .gitlab-ci.yml 中定义的 variables | 配置文件默认值 |
| 2 | 项目级别 CI/CD Variables | 项目 Settings > CI/CD > Variables |
| 3 | Group 级别 CI/CD Variables | 整个 Group 共享 |
| 4 | Instance 级别 CI/CD Variables | 全实例共享 |
| 5 | 受保护变量(Protected) | 仅在受保护分支或标签运行 |
| 6 | 手动触发的 Pipeline Variables | API 触发时传入 |
| 7 | 预定义变量($CI_*) | 系统自动注入,不可覆盖 |
关键规则:
- 同一层级中,Masked 变量不额外提升优先级。
- 手动触发 Pipeline 时传入的变量优先级最高(除预定义变量外)。
- 受保护变量仅在 protected branch 或 protected tag 的 Pipeline 中注入。
10 Job 间数据传递方式
答案:
GitLab CI/CD 提供三种 Job 间数据传递机制。
| 方式 | 说明 | 跨 Stage | 跨 Pipeline |
|---|---|---|---|
| Artifact | 文件级传递 | 支持 | 不支持 |
| Cache | 加速依赖复用 | 支持 | 支持(按 key) |
| Multi-job Pipeline | needs 关键字 | 支持 | 不支持 |
配置示例:
build_job:
stage: build
artifacts:
paths:
- dist/
deploy_job:
stage: deploy
needs:
- build_job
script:
- ls dist/
dependencies 关键字控制 Artifact 下载范围:
deploy_job:
stage: deploy
dependencies:
- build_job
script:
- deploy.sh
11 Docker 镜像构建与推送
答案:
GitLab CI/CD 支持通过 Docker-in-Docker 或 Kaniko 构建镜像并推送到 Container Registry。
Docker-in-Docker 方案:
image: docker:20.10.16
services:
- docker:20.10.16-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
build_image:
stage: build
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
Kaniko 方案(无需特权模式):
build_image:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- /kaniko/executor
--context $CI_PROJECT_DIR
--dockerfile $CI_PROJECT_DIR/Dockerfile
--destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
| 方案 | 优点 | 缺点 |
|---|---|---|
| Docker-in-Docker | 原生 Docker 体验,功能完整 | 需特权模式,安全风险 |
| Kaniko | 无需特权,安全性高 | 构建速度略慢,部分功能受限 |
12 Kubernetes 部署集成
答案:
GitLab CI/CD 通过 kubectl 或 Helm 向 K8s 集群部署应用。
kubectl 直接部署:
deploy_k8s:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/app app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- kubectl rollout status deployment/app
environment:
name: production
Helm 部署:
deploy_helm:
stage: deploy
image: alpine/helm:latest
script:
- helm upgrade --install app ./chart
--set image.tag=$CI_COMMIT_SHORT_SHA
--namespace production
environment:
name: staging
K8s 认证方式:
| 方式 | 配置方法 |
|---|---|
| Kubeconfig 变量 | 将 kubeconfig 内容存入 CI/CD Variable |
| Service Account Token | 预创建 SA,使用 token 通过 kubectl 认证 |
| GitLab Agent | 通过 CI/CD Tunnel 建立安全连接 |
13 多分支 Pipeline 策略
答案:
GitLab CI/CD 支持基于分支的差异化 Pipeline 策略。
分支策略配置:
workflow:
rules:
- if: $CI_COMMIT_BRANCH == "main"
variables:
DEPLOY_ENV: "production"
- if: $CI_COMMIT_BRANCH =~ /^feature/
variables:
DEPLOY_ENV: "review"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH =~ /^release/
variables:
DEPLOY_ENV: "staging"
典型分支策略:
| 分支类型 | 执行阶段 | 部署目标 |
|---|---|---|
| feature/* | build + test | 无部署 |
| develop | build + test | review app |
| release/* | build + test + staging | staging 环境 |
| main | build + test + production | 生产环境 |
| tag | build + test + production | 生产环境并发布 |
14 CI/CD 安全控制
答案:
GitLab CI/CD 提供多层安全机制保护敏感信息。
变量保护措施:
| 机制 | 说明 |
|---|---|
| Masked | 变量值在 Job 日志中被 **** 替换 |
| Protected | 仅在受保护分支或标签的 Pipeline 中注入 |
| File 类型 | 变量内容以临时文件形式挂载 |
| Environment Scope | 限定变量仅在特定环境的 Job 中生效 |
最佳实践:
# 受保护变量注入
deploy_prod:
stage: deploy
script:
- echo $PROD_API_KEY # 仅在 main 分支 Pipeline 中可见,日志 masked
environment: production
only:
- main
Secret Detection 集成:
include:
- template: Security/Secret-Detection.gitlab-ci.yml
secret_detection:
stage: test
variables:
SECRET_DETECTION_HISTORIC_SCAN: "true"
15 Pipeline 效率优化
答案:
通过多维度策略提升 Pipeline 执行效率。
优化策略矩阵:
| 优化手段 | 效果 | 配置方式 |
|---|---|---|
| Cache 依赖目录 | 减少依赖安装时间 | cache:paths |
| needs 提前执行 | 缩短 Pipeline 总时长 | needs 关键字 |
| parallel 并行化 | 拆分大规模测试 | parallel 关键字 |
| DAG 依赖优化 | 非阻塞依赖执行 | needs + DAG |
| 轻量镜像 | 减少镜像拉取时间 | 精简 image 大小 |
配置示例:
test_job:
stage: test
script: npm test
parallel: 5
needs: ["build_job"]
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
触发策略优化:
- 使用 rules:changes 仅特定路径变更时触发,避免无关文件触发全量 Pipeline。
- Merge Request Pipeline 使用合并结果 Pipeline 提前验证但节省构建资源。
16 触发方式
答案:
GitLab Pipeline 支持多种触发方式。
| 触发方式 | 说明 | 典型场景 |
|---|---|---|
| Push | 代码推送自动触发 | 常规开发流程 |
| Merge Request | MR 创建或更新触发 | MR 验证 |
| Tag Push | 标签推送触发 | 版本发布 |
| Schedule | 定时触发 | nightly build / 定期清理 |
| Webhook | 外部 HTTP 调用 | 上游系统集成触发 |
| Pipeline Trigger Token | API 带 token 触发 | 跨项目触发 |
| Multi-project Pipeline | 下游项目被动触发 | 微服务链式发布 |
API 触发示例:
curl -X POST \
-F token=$CI_JOB_TOKEN \
-F ref=main \
-F variables[DEPLOY_ENV]=production \
https://gitlab.example.com/api/v4/projects/$PROJECT_ID/trigger/pipeline
Multi-project Pipeline 配置:
trigger_downstream:
stage: deploy
trigger:
project: mygroup/downstream-project
branch: main
strategy: depend
17 并发与队列管理
答案:
GitLab Runner 通过 concurrent 和 Runner 级别配置管理 Job 并发。
并发层级:
| 层级 | 配置项 | 作用范围 |
|---|---|---|
| Runner 实例 | concurrent | 单个 Runner 进程同时执行的最大 Job 数 |
| Executor 限制 | limit | 每个 Executor 的最大并发数 |
| Project 限额 | CI/CD Settings | 项目级别的 Pipeline 配额 |
| Instance 限额 | 管理员设置 | GitLab 实例全局限制 |
config.toml 配置示例:
concurrent = 10
[[runners]]
name = "docker-runner"
url = "https://gitlab.example.com"
token = "xxxx"
executor = "docker"
limit = 5
[runners.docker]
image = "alpine:latest"
resource_group 顺序化:
deploy_job:
stage: deploy
script: deploy.sh
resource_group: production
resource_group 确保同一组的 Job 串行执行,避免并发部署冲突。
18 GitLab Pages 集成
答案:
GitLab CI/CD 原生支持构建静态站点并发布到 GitLab Pages。
配置模板:
pages:
stage: deploy
script:
- npm install
- npm run build
artifacts:
paths:
- public/
rules:
- if: $CI_COMMIT_BRANCH == "main"
Pages 核心规则:
| 规则 | 说明 |
|---|---|
| Job 名称 | 必须命名为 pages |
| 产物路径 | 必须是 public/ 目录 |
| 发布 URL | https://<namespace>.gitlab.io/<project> |
| 自定义域名 | 支持通过项目 Settings > Pages 配置 |
| Access Control | 支持项目级别访问权限控制 |
框架集成示例:
# Jekyll
image: ruby:2.7
pages:
script:
- gem install jekyll
- jekyll build -d public/
Pages 部署触发条件: 仅 default branch 的 pages Job 可发布,其他分支的 pages Job 仅验证构建。
19 Auto DevOps
答案:
Auto DevOps 是 GitLab 内置的自动化 CI/CD 模板,根据代码内容自动检测语言并生成 Pipeline。
启用方式:
# 项目 Settings > CI/CD > Auto DevOps 开启
# 或显式 include 模板
include:
- template: Auto-DevOps.gitlab-ci.yml
自动检测阶段:
| Stage | 功能 |
|---|---|
| Build | 自动检测语言并构建 Docker 镜像 |
| Test | 运行语言特定的测试框架 |
| Code Quality | 代码质量分析 |
| SAST | 静态安全扫描 |
| DAST | 动态安全扫描 |
| Review | 创建 Review App 预览环境 |
| Deploy | 部署到 staging 和 production |
| Performance | 性能测试 |
| Cleanup | 清理 Review App 环境 |
适用限制:
- 仅支持 GitLab 预定义的语言栈。
- 需要 Kubernetes 集群用于部署阶段。
- 自定义程度低于手动编写 .gitlab-ci.yml。
20 parallel:matrix 矩阵构建
答案:
parallel:matrix 支持多维度组合的并行 Job,适用于跨语言、跨平台的矩阵测试。
test_job:
stage: test
parallel:
matrix:
- OS: ["ubuntu", "centos", "alpine"]
VERSION: ["18", "20"]
script:
- docker build -t app:${OS}-${VERSION} -f Dockerfile.${OS} .
- docker run app:${OS}-${VERSION} test
矩阵展开结果:
| Job 实例 | OS | VERSION |
|---|---|---|
| test_job: 1/6 | ubuntu | 18 |
| test_job: 2/6 | ubuntu | 20 |
| test_job: 3/6 | centos | 18 |
| test_job: 4/6 | centos | 20 |
| test_job: 5/6 | alpine | 18 |
| test_job: 6/6 | alpine | 20 |
变量引用:
script:
- echo "Testing on $OS version $VERSION"
限制: 矩阵维度组合数受 GitLab 实例并行配额限制,单 Job 最多展开 50 个并行实例。
21 Container Registry 管理
答案:
GitLab Container Registry 是内置的 Docker 镜像仓库,与 GitLab 项目集成。
build_image:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
Registry 路径规则:
| 变量 | 值示例 | 说明 |
|---|---|---|
| CI_REGISTRY | registry.gitlab.example.com | Registry 根地址 |
| CI_REGISTRY_IMAGE | registry.gitlab.example.com/group/project | 镜像仓库地址 |
| CI_REGISTRY_USER | gitlab-ci-token | 自动认证用户名 |
| CI_REGISTRY_PASSWORD | 自动生成的 token | 自动认证密码 |
清理策略:
- 过期清理策略在项目 Settings > CI/CD > Container Registry 中配置。
- 支持按时间或数量限制自动删除旧镜像。
- API 删除:
DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name
集成认证: Pipeline 内部自动使用 CI_REGISTRY_USER / CI_REGISTRY_PASSWORD 认证,无需额外配置。
22 单机多 Runner 注册
答案:
一台物理机或 VM 上可注册多个 GitLab Runner 实例以隔离不同项目的构建环境。
配置方法:
# 注册第一个 Runner
gitlab-runner register \
--non-interactive \
--url https://gitlab.example.com \
--registration-token TOKEN_A \
--executor docker \
--description "runner-project-a" \
--tag-list "project-a,node14" \
--run-untagged="false"
# 注册第二个 Runner
gitlab-runner register \
--non-interactive \
--url https://gitlab.example.com \
--registration-token TOKEN_B \
--executor docker \
--description "runner-project-b" \
--tag-list "project-b,node16" \
--run-untagged="false"
config.toml 结构:
concurrent = 8
[[runners]]
name = "runner-project-a"
url = "https://gitlab.example.com"
token = "token-a"
executor = "docker"
tag_list = ["project-a"]
[[runners]]
name = "runner-project-b"
url = "https://gitlab.example.com"
token = "token-b"
executor = "docker"
tag_list = ["project-b"]
隔离维度:
| 维度 | 策略 |
|---|---|
| 资源隔离 | 每个 Runner 配置独立的 CPU/Memory 限制 |
| 网络隔离 | 每个 Runner 使用独立的 Docker 网络 |
| 存储隔离 | 每个 Runner 配置独立的构建目录 |
| Token 隔离 | 每个 Runner 使用独立的注册 Token |
23 environment 与 Review Apps
答案:
environment 关键字管理部署目标环境,Review Apps 为每个 MR 创建临时预览环境。
environment 配置:
deploy_job:
stage: deploy
script: deploy.sh
environment:
name: production
url: https://app.example.com
Review Apps 配置:
review_deploy:
stage: deploy
script:
- helm upgrade --install review-$CI_MERGE_REQUEST_IID ./chart
--namespace review
environment:
name: review/$CI_MERGE_REQUEST_IID
url: https://review-$CI_MERGE_REQUEST_IID.example.com
on_stop: review_cleanup
rules:
- if: $CI_MERGE_REQUEST_ID
review_cleanup:
stage: deploy
script:
- helm uninstall review-$CI_MERGE_REQUEST_IID
environment:
name: review/$CI_MERGE_REQUEST_IID
action: stop
needs:
- review_deploy
rules:
- if: $CI_MERGE_REQUEST_ID
when: manual
环境生命周期:
| 操作 | 行为 |
|---|---|
| environment:name | 创建或重用一个命名环境 |
| environment:action:start | 手动启动环境 |
| environment:action:stop | 手动停止并清理环境 |
| on_stop | CI 自动触发清理 Job |
| MR 关闭 | MR 关闭时触发 on_stop |
24 needs 关键字与 DAG
答案:
needs 关键字突破 Stage 顺序限制,允许 Job 在非依赖 Stage 完成后立即执行,形成 DAG 执行图。
build_job:
stage: build
script: make build
test_unit:
stage: test
script: make test-unit
test_integration:
stage: test
script: make test-integration
needs:
- build_job
deploy_staging:
stage: deploy
script: deploy-staging.sh
needs:
- test_unit
- test_integration
DAG 执行图解析:
graph LR
build_job --> test_unit --> deploy_staging
build_job --> test_integration
test_integration --> deploy_staging
needs 限制:
| 限制项 | 说明 |
|---|---|
| 最大依赖数 | 单个 Job 最多依赖 10 个 Job |
| 跨 Stage 引用 | 支持引用之前所有 Stage 的 Job |
| parallel 冲突 | 不可与全局 needs 混用 |
25 resource_group 串行执行
答案:
resource_group 确保同一资源组的 Job 串行执行,适用于部署类 Job 避免并发冲突。
deploy_blue:
stage: deploy
script: deploy-blue.sh
resource_group: production
environment:
name: production
deploy_green:
stage: deploy
script: deploy-green.sh
resource_group: production
environment:
name: production
resource_group 行为:
| 场景 | 行为 |
|---|---|
| 同一资源组同时触发 | 排队等候,前一 Job 完成后执行 |
| 跨 Pipeline 同资源组 | 等待上一 Pipeline 的同组 Job 完成 |
| 同 Pipeline 同资源组 | 按 .gitlab-ci.yml 中出现顺序执行 |
| 无 resource_group | 默认不限流,并发执行 |
适用场景:
- 数据库迁移 Job 串行化。
- 蓝绿部署过程不交叉。
- 基础设施变更 Job 锁定执行。
26 include 关键字与模板复用
答案:
include 关键字引入外部 YAML 文件,支持模板化复用和多文件组合。
include:
- local: '/templates/.build-template.yml'
- project: 'shared/templates'
file: '/ci-templates/.docker-template.yml'
ref: v1.0
- remote: 'https://gitlab.com/example/template.yml'
- template: 'Security/SAST.gitlab-ci.yml'
include 类型对比:
| 类型 | 来源 | 适用场景 |
|---|---|---|
| local | 同仓库路径 | 项目内模块化 |
| project | 其他仓库 | 组织级模板共享 |
| remote | HTTP URL | 第三方公共模板 |
| template | GitLab 内置 | 安全扫描等官方模板 |
合并规则:
- include 文件在 Pipeline 解析期合并,与主文件共享命名空间。
- 同名 Job 定义合并时,主文件内容覆盖 include 定义。
- include 支持嵌套,最多 100 层。
27 workflow 控制 Pipeline 级别规则
答案:
workflow 关键字定义整个 Pipeline 的执行条件,比 rules 作用范围更大。
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+/
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH =~ /^feature/
variables:
SKIP_DEPLOY: "true"
- if: $CI_PIPELINE_SOURCE == "schedule"
variables:
NIGHTLY_BUILD: "true"
- when: never
workflow 功能:
| 能力 | 说明 |
|---|---|
| 全局拦截 | 不满足任何规则时整体 Pipeline 不创建 |
| 全局变量 | 匹配规则时注入全局变量 |
| 与 rules 协同 | workflow 做全局过滤,rules 做 Job 级别过滤 |
典型场景:
- Tag 推送时触发全量 Pipeline,普通分支仅触发部分。
- Schedule Pipeline 注入 NIGHTLY_BUILD=true 变量。
- MR Pipeline 跳过部署阶段。
- 非受保护分支不创建 Pipeline 节省资源。
28 Job Timeout 与 Retry
答案:
通过 timeout 和 retry 关键字控制 Job 执行时长和失败重试。
long_test:
stage: test
script: make long-test
timeout: 30 minutes
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
- unknown_failure
timeout 规则:
| 范围 | 默认值 | 最大值 |
|---|---|---|
| 项目级别 | 60 min | 管理员配置 |
| Job 级别 timeout | 项目值 | 不可超过项目级 |
| Runner 级别 | 无限制 | config.toml 配置 |
retry 配置:
| 参数 | 说明 |
|---|---|
| max | 最大重试次数(0-2,最多 3 次执行) |
| when | 触发重试的失败类型列表 |
| when:always | 所有失败均重试 |
| when:script_failure | 仅脚本执行失败时重试 |
失败类型:
| 类型 | 说明 |
|---|---|
| runner_system_failure | Runner 系统故障 |
| stuck_or_timeout_failure | Job 超时 |
| unknown_failure | 未知类型失败 |
| script_failure | 脚本返回非零退出码 |
| job_execution_timeout | Job 执行超时 |
29 GitLab CI 与 GitOps
答案:
GitLab CI/CD 通过 GitOps 模式实现声明式基础设施管理。
GitOps 工作流:
Git Push (manifests update) --> Pipeline --> kubectl apply / Helm upgrade --> Cluster state reconciliation
GitLab Agent for Kubernetes:
# .gitlab/agents/my-agent/config.yaml
gitops:
manifest_projects:
- id: mygroup/myproject
default_namespace: production
paths:
- glob: "manifests/**/*.yaml"
CI 驱动 GitOps 示例:
sync_cluster:
stage: deploy
image: bitnami/kubectl
script:
- kubectl apply -f manifests/
- kubectl wait --for=condition=Ready pods --all --timeout=300s
environment:
name: production
only:
- main
GitOps 优势:
| 特性 | 效果 |
|---|---|
| 声明式配置 | 集群状态以 Git 仓库为单一事实来源 |
| 可审计 | 每次变更对应一次 commit |
| 自动回滚 | 错误配置可通过 revert commit 恢复 |
| 差异检测 | Pipeline 通过 diff 检查配置漂移 |
30 Docker-in-Docker 原理与配置
答案:
Docker-in-Docker(DinD)是在 Docker 容器内运行 Docker 守护进程的方案,用于 CI 中构建和推送 Docker 镜像。
image: docker:20.10.16
variables:
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
DOCKER_DRIVER: overlay2
services:
- name: docker:20.10.16-dind
command: ["--tls=false"]
build:
stage: build
script:
- docker build -t app:$CI_COMMIT_SHORT_SHA .
- docker push app:$CI_COMMIT_SHORT_SHA
DinD 架构:
Runner Host
└── Docker Container (Job)
├── docker CLI
└── Service Container (docker:dind)
└── Docker Daemon (绑定 /var/run/docker.sock)
DinD 限制:
| 问题 | 说明 | 解决方案 |
|---|---|---|
| 特权模式 | 需要 privileged: true | 使用 Kaniko 替代 |
| 缓存失效 | 每次构建从零开始 | 使用 docker layer caching |
| 磁盘空间 | 镜像累积 | 定期清理 / 配置卷挂载 |
31 Artifact 过期策略
答案:
Artifact 通过 expire_in 字段控制保留时长,过期后自动清理。
build_job:
stage: build
script: mvn package
artifacts:
paths:
- target/*.jar
expire_in: 30 days
expire_in 格式:
| 格式 | 示例 | 说明 |
|---|---|---|
| 数字+单位 | 30 days | 单位支持 days / weeks / months |
| never | never | 永不过期(管理员可限制) |
| 组合 | 2 weeks 3 days | 组合时间单位 |
Artifact 生命周期:
- Pipeline 完成后开始计时。
- 过期后被 GitLab 后台清理线程删除。
- 过期前可通过 Web UI 或 API 手动延长保留。
- 最新 Job 的 Artifact 默认最终保留。
Keep 操作: 在 Pipeline 详情页将 Artifact 标记为 keep,覆盖 expire_in 设置。
32 tags 与 Runner 选择
答案:
tags 关键字将 Job 分配给具备特定标签的 Runner,实现 Runner 精确匹配。
build_linux:
stage: build
tags:
- linux
- docker
script: make build
build_macos:
stage: build
tags:
- macos
- shell
script: xcodebuild
Runner 标签匹配规则:
| Job tags 配置 | Runner tag 配置 | 是否匹配 |
|---|---|---|
| linux | linux | 是 |
| linux, docker | linux, docker | 是 |
| linux | linux, docker | 是(Runner 标签包含 Job 所需全部标签) |
| linux, docker | linux | 否(Runner 缺少 docker 标签) |
| 无 tags | run_untagged: true | 是 |
注意事项:
- Job 设置 tags 后,Runner 必须包含所有 tags 才能执行。
- Runner 设置 run_untagged = true 可接受无 tags 的 Job。
- runner 可通过 tags 实现环境隔离(GPU / 架构 / 网络区域)。
33 CI/CD 变量传递与受保护变量
答案:
CI/CD 变量通过 environments 和 protected 属性精确控制变量注入范围。
变量作用域配置:
# 项目 Settings > CI/CD > Variables
# Name: DB_PASSWORD
# Value: xxxxxx
# Protected: true
# Masked: true
# Environment: production
暴露规则矩阵:
| 变量属性 | 非受保护分支 | 受保护分支 |
|---|---|---|
| 非受保护 + 非环境限定 | 可见 | 可见 |
| 受保护 + 非环境限定 | 不可见 | 可见 |
| 非受保护 + 环境限定 | 环境匹配时可见 | 环境匹配时可见 |
| 受保护 + 环境限定 | 不可见 | 环境匹配时可见 |
File 类型变量:
# 存储 SSH_PRIVATE_KEY 为 File 类型变量
before_script:
- chmod 400 $SSH_PRIVATE_KEY
- ssh -i $SSH_PRIVATE_KEY user@host
File 类型变量在 Runner 上写入临时文件,文件路径保存在对应变量名中,避免值在日志中泄露。
34 Pipeline 缓存优化策略
答案:
通过多级缓存策略降低 Pipeline 执行时间。
缓存配置层次:
# 全局 Cache
cache:
key:
files:
- package-lock.json
prefix: npm-cache
paths:
- node_modules/
policy: pull-push
# Job 级别覆盖
test_job:
stage: test
cache:
key: test-${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
policy: pull
缓存 Key 策略:
| 策略 | 适用场景 | 缓存命中率 |
|---|---|---|
| 固定 key(npm-cache) | 共享依赖,不受分支影响 | 高 |
| 文件 hash(package-lock.json) | 按依赖文件版本隔离 | 中 |
| 分支名($CI_COMMIT_REF_SLUG) | 分支级隔离 | 低 |
| 组合策略(prefix + files) | 兼顾共享与隔离 | 高 |
pull-push 策略:
| 策略 | 行为 | 适用场景 |
|---|---|---|
| pull-push | 执行前拉取,完成后写入 | 首次或可能更新的 Job |
| pull | 仅拉取不写入 | 后续不需要更新的阶段 |
| push | 仅写入不拉取 | 构建阶段生成缓存 |
35 Job 依赖图与 DAG Pipeline
答案:
DAG Pipeline 通过 needs 关键字定义 Job 间的依赖关系,实现非线性的高效执行。
stages: [build, test, lint, package, deploy]
compile:
stage: build
script: make compile
unit_test:
stage: test
script: make test
lint:
stage: lint
script: make lint
package:
stage: package
script: make package
needs: [compile]
integration_test:
stage: test
script: make integration
needs: [compile]
deploy:
stage: deploy
script: deploy.sh
needs: [package, unit_test, lint, integration_test]
DAG 执行路径:
graph LR
compile --> lint
compile --> unit_test
compile --> integration_test
compile --> package
lint --> deploy
unit_test --> deploy
integration_test --> deploy
package --> deploy
DAG 优势:
| 对比项 | 传统 Pipeline | DAG Pipeline |
|---|---|---|
| 执行模型 | 严格 Stage 顺序 | 按依赖关系并行 |
| 总时长 | Stage 累加 | 关键路径长度 |
| 资源利用率 | 同 Stage 结束后闲置 | 按需释放无等待 |
注意事项: 使用 DAG 时,needs 引用的 Job 必须存在于当前 Pipeline 中,不能跨 Pipeline 引用。
36 Merge Request Pipeline 类型
答案:
GitLab 支持多种 MR Pipeline 类型,适用于不同验证场景。
| Pipeline 类型 | 触发条件 | 适用场景 |
|---|---|---|
| MR Pipeline | MR 创建或推送新 commit | 常规合并前验证 |
| Merged Results Pipeline | 模拟合并后的结果 | 检测目标分支合并冲突 |
| Merge Train Pipeline | 排队合并 | 批量合并质量控制 |
配置示例:
# MR Pipeline
test_in_mr:
stage: test
script: make test
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Merged Results Pipeline
# 需要项目 Settings > Merge Requests > Merge checks 开启
三种 Pipeline 对比:
| 特性 | MR Pipeline | Merged Results | Merge Train |
|---|---|---|---|
| 执行环境 | MR 源分支 | 源 + 目标合并结果 | 排队序列 |
| 冲突检测 | 不检测 | 检测 | 检测 |
| 资源消耗 | 低 | 中(需合并后 CI) | 高(多 MR 排队) |
| 推荐场景 | 标准 MR 流程 | 主线稳定性要求高 | 高并发 MR 团队 |
37 GitLab CI 中的 Secret Detection
答案:
GitLab 内置 Secret Detection 功能,在 CI Pipeline 中自动扫描代码中的敏感信息泄露。
include:
- template: Security/Secret-Detection.gitlab-ci.yml
secret_detection:
stage: test
variables:
SECRET_DETECTION_HISTORIC_SCAN: "true"
GIT_DEPTH: 0
扫描范围:
| 类型 | 检测内容 |
|---|---|
| API Key | AWS / GCP / Azure / GitLab / GitHub 等平台密钥 |
| Token | JWT / OAuth / Private Token |
| Credential | 数据库连接串 / SSH 密钥 |
| Certificate | PEM / P12 证书内容 |
结果处理:
- 检测结果在 Security & Compliance > Vulnerability Report 中集中展示。
- Pipeline 失败或警告可通过 SECRET_DETECTION_DISABLED 变量控制。
- 误报通过 .gitlab/secret_detection_rules.yml 自定义规则排除。
38 GitLab CI 与 GitLab Agent for Kubernetes
答案:
GitLab Agent for Kubernetes(KAS)建立 GitLab 实例与 K8s 集群之间的安全隧道,用于 CI/CD 部署和 GitOps。
# .gitlab/agents/my-agent/config.yaml
ci_access:
projects:
- id: mygroup/myproject
gitops:
manifest_projects:
- id: mygroup/myproject
default_namespace: production
CI 集成配置:
deploy_with_agent:
stage: deploy
variables:
KUBE_CONTEXT: mygroup/myproject:my-agent
script:
- kubectl apply -f manifests/
- kubectl rollout status deployment/app
Agent 工作模式:
| 组件 | 部署位置 | 职责 |
|---|---|---|
| GitLab Agent | GitLab 实例 | Agent 注册和管理 |
| Agent Pod | K8s 集群 | 维护与 GitLab 的长连接 |
| CI Job | Runner | 通过 KUBE_CONTEXT 选择目标集群 |
安全特性:
- Agent 使用 mTLS 加密通信,无需暴露 K8s API Server。
- 访问权限在 GitLab 项目级别精细化控制。
- Agent 支持 Impersonation,使用特定 ServiceAccount 执行操作。
39 CI/CD 中的环境变量注入风险与控制
答案:
CI/CD 变量在 Job 日志中可能被意外输出,需通过多重机制控制泄露风险。
泄露途径:
| 途径 | 说明 | 风险等级 |
|---|---|---|
| echo / print | Job 脚本中直接打印变量值 | 高 |
| 命令参数暴露 | 命令行参数被进程列表捕获 | 中 |
| 日志 debug 模式 | 工具输出包含变量内容 | 中 |
| 构建产物残留 | 变量写入文件被打包入 Artifact | 高 |
防护措施:
# 变量设为 Masked(日志自动替换)
# 变量设为 File 类型(写入临时文件,避免命令行传递)
before_script:
- export MASKED_VAR=$MY_SECRET
test_job:
stage: test
variables:
MY_SECRET: "" # 覆盖为全局变量,Job 内不可见
script:
- echo $MY_SECRET # 输出为空
审计策略:
- 启用 Pipeline 日志审计日志,记录所有变量赋值操作。
- 定期扫描 Artifact 产物中的敏感信息。
- 使用 Secret Detection 扫描历史 commit 中的变量硬编码。
40 GitLab CI 的整体架构与组件
答案:
GitLab CI/CD 架构由多个组件协同工作。
组件关系:
graph TD
A[User Push Code] --> B[GitLab Rails - Web UI + API]
B --> C[Workhorse - 请求代理]
B --> D[Sidekiq - 异步任务队列]
B --> E[Runner - Job 执行]
D --> F[Pipeline 创建和调度]
E --> G[Executor - Docker / K8s / Shell / SSH]
各组件职责:
| 组件 | 部署方式 | 职责 |
|---|---|---|
| GitLab Rails | 核心应用 | Web UI, API, 用户认证, 项目管理 |
| Workhorse | 反向代理 | 静态文件服务, 大文件上传, Git 操作代理 |
| Sidekiq | 异步 Worker | Pipeline 创建, Job 调度, Webhook 触发 |
| Runner | 独立进程 | 拉取 Job, 创建 Executor 环境, 执行脚本 |
| Executor | Runner 插件 | 容器化 / 虚拟化 / 本地执行环境 |
通信链路:
- Runner 通过轮询或长连接向 GitLab API 获取待执行 Job。
- GitLab 返回 Job 定义、变量、Artifact 引用和脚本内容。
- Runner 下载代码、挂载缓存、执行脚本并将日志实时推送到 GitLab。
- Sidekiq 处理 Pipeline 状态转换、通知发送和 Webhook 回调。