持续集成工具(GitLab CI)
一、核心概念
GitLab CI 是 GitLab 提供的内置持续集成 / 持续部署(CI/CD)工具,可自动化软件开发流程中的构建、测试、部署等环节。以下是其核心概念的详细解释:
1. gitlab-ci.yml 文件
1.1作用:项目根目录下的 YAML 配置文件,定义了 CI/CD 流程的结构和规则。
1.2核心组件:
- stages:定义流程阶段(如 build、test、deploy),按顺序执行。
- jobs:每个阶段包含多个作业,同一阶段的作业并行执行。
- keywords:如 script(执行命令)、image(Docker 镜像)、artifacts(传递文件)等。
1.3示例:
yaml 运行stages:- build- testbuild\_job:stage: buildimage: node:14script:- npm install- npm run buildartifacts:paths:- dist/test\_job:stage: testimage: node:14script:- npm testdependencies:- build\_job
2. Pipeline(流水线)
2.1定义:一次完整的 CI/CD 流程,包含所有阶段和作业。
2.2触发方式:
- 代码提交:push 到仓库时自动触发。
- Schedule:定时任务(如每晚运行测试)。
- API 触发:通过 GitLab API 手动触发。
2.3状态:成功(green)、失败(red)、运行中(yellow)。
3. Job(作业)
3.1定义:Pipeline 中的最小执行单元,属于某个阶段。
3.2关键属性:
- script:执行的 shell 命令。
- image:指定 Docker 镜像(如 python:3.9)。
- only/except:控制触发条件(如仅主分支触发)。
- artifacts:保存文件供后续作业使用。
- cache:缓存依赖(如 node_modules)加速构建。
4. Runner(执行器)
4.1定义:执行 Pipeline 中作业的服务器或容器。
4.2类型:
- 共享 Runner:GitLab 托管的公共执行器。
- 特定 Runner:项目专属执行器(需自行部署)。
- 执行环境:支持 Docker、Kubernetes、Shell 等。
4.3注册命令示例:
bash 运行gitlab-runner register \--url https://gitlab.com/ \--registration-token YOUR\_TOKEN \--executor docker \--docker-image alpine:latest
5. Stage(阶段)
5.1定义:Pipeline 的逻辑分组,按顺序执行。
5.2特点:
- 同一阶段的作业并行执行。
- 前一阶段失败,后续阶段不会执行。
- 常见阶段:build → test → deploy → cleanup。
6. Artifacts(制品)
6.1定义:作业产生的文件或目录,可传递给后续作业。
6.2用途:
- 传递构建产物(如编译后的二进制文件)。
- 保存测试报告(如 JUnit XML)。
6.3配置示例:
yaml 运行build:artifacts:paths:- dist/app.jarexpire\_in: 1 week
7. Cache(缓存)
7.1定义:加速作业执行的依赖项缓存机制。
7.2与 Artifacts 的区别:
- Cache:用于同一作业的重复执行(如复用 node_modules)。
- Artifacts:用于不同作业间的文件传递。
7.3配置示例:
yaml 运行test:cache:paths:- node\_modules/key: ${CI\_COMMIT\_REF\_SLUG}
8. Rules(规则)
8.1作用:动态控制作业是否执行,替代 only/except。
8.2条件类型:
- if:基于变量或分支判断。
- changes:基于文件变更触发。
- exists:基于文件存在触发。
8.3示例:
yaml 运行deploy\_prod:script:- deploy-to-prod.shrules:- if: '$CI\_COMMIT\_BRANCH == "main" && $CI\_PIPELINE\_SOURCE == "push"'when: manual # 手动触发
9. Environment(环境)
9.1定义:部署目标(如 staging、production)。
9.2功能:
- 记录部署历史和状态。
- 支持环境回滚。
- 关联环境 URL。
9.3配置示例:
yaml 运行deploy\_staging:script:- deploy-to-staging.shenvironment:name: stagingurl: https://staging.example.com
10. Variables(变量)
10.1作用:存储敏感信息或配置参数。
10.2类型:
- 全局变量:在 .gitlab-ci.yml 中定义。
- 项目变量:在 GitLab 项目设置中配置(如 API 密钥)。
- 预定义变量:GitLab 内置变量(如 $CI_COMMIT_SHA)。
10.3使用示例:
yaml 运行deploy:script:- echo "Deploying ${ENVIRONMENT} with API key ${API\_KEY}"
二、关键功能
1. 多阶段 Pipeline
- 顺序执行:通过 stages 定义阶段(如 build → test → deploy),前一阶段失败则后续阶段不会执行。
- 并行作业:同一阶段的作业自动并行,提高效率。
示例配置:
yaml 运行stages:- build- test- deploybuild:stage: buildscript:- npm install- npm run buildtest:stage: testparallel: 3 # 并行3次执行相同作业script:- npm test --shard=$CI\_NODE\_INDEX/$CI\_NODE\_TOTAL
2. 条件执行与规则系统
- 基于分支 / 标签触发:使用 only/except 或更灵活的 rules。
- 动态决策:根据变量、文件变更或 Pipeline 来源控制作业执行。
示例:仅在合并请求时运行安全扫描
yaml 运行security\_scan:script:- run-security-check.shrules:- if: '$CI\_PIPELINE\_SOURCE == "merge\_request\_event"'when: always- when: never
3. 缓存与制品管理
- Cache:加速依赖安装(如 npm install),支持跨作业共享。
- Artifacts:保存构建产物(如二进制文件、测试报告),支持过期策略。
示例:缓存 npm 依赖并传递构建产物
yaml 运行build:cache:key: ${CI\_COMMIT\_REF\_SLUG}paths:- node\_modules/artifacts:paths:- dist/expire\_in: 1 hourtest:dependencies:- build # 依赖 build 作业的 artifacts
4. 矩阵构建
- 并行测试不同环境:使用 parallel 或 rules:when:matrix 针对多个环境执行相同作业。
示例:测试多个 Node.js 版本
yaml 运行test:script:- npm teststrategy:matrix:NODE\_VERSION: \[14, 16, 18\]image: node:${NODE\_VERSION}
5. 环境与部署管理
- 环境追踪:记录部署历史,支持回滚和环境可视化。
- 手动操作:通过 when: manual 设置审批卡点。
示例:生产环境部署需手动确认
yam 运行deploy\_prod:script:- deploy-to-prod.shenvironment:name: productionurl: https://example.comrules:- if: '$CI\_COMMIT\_BRANCH == "main"'when: manual
6. 变量与秘密管理
- 预定义变量:如 $CI_COMMIT_SHA、$CI_PIPELINE_ID 等系统变量。
- 自定义变量:在 .gitlab-ci.yml 或项目设置中定义,支持加密存储敏感信息。
示例:使用加密变量连接数据库
yaml 运行test:script:- psql "$DATABASE\_URL" -c "SELECT 1"
7. 定时 Pipeline
Schedule:通过 Cron 表达式定期触发 Pipeline(如每晚运行集成测试)。
配置步骤:
- 进入项目 Settings → CI/CD → Schedules
- 设置 Cron 表达式(如 0 0 * * *)和目标分支
8. 自动合并请求(Auto DevOps)
- 静态代码分析:自动检测代码质量并在 MR 中显示结果。
- 自动部署预览:为每个 MR 创建临时环境,支持可视化审查。
9. API 与触发器
- 外部触发:通过 API 触发 Pipeline 并传递参数。
- Webhook:基于外部事件(如代码推送、Issue 更新)触发操作。
API 触发示例:
bash 运行curl -X POST \\-F token=$TRIGGER\_TOKEN \-F "variables\[ENV\]=staging" \https://gitlab.com/api/v4/projects/12345/trigger/pipeline
10. 与第三方工具集成
- 测试报告:集成 JUnit、Codecov 等工具,可视化测试覆盖率。
- 容器注册表:与 GitLab Container Registry 无缝对接,实现镜像构建与推送。
示例:发布 Docker 镜像
yaml 运行docker\_build:image: docker:latestservices:- docker:dindscript:- docker login -u $CI\_REGISTRY\_USER -p $CI\_REGISTRY\_PASSWORD $CI\_REGISTRY- docker build -t $CI\_REGISTRY\_IMAGE:$CI\_COMMIT\_TAG .- docker push $CI\_REGISTRY\_IMAGE:$CI\_COMMIT\_TAG
11. 资源限制与并行控制
- 并发限制:通过 resource_group 控制共享资源的作业并发数。
- 资源分配:为不同作业分配 CPU/Memory 权重(Runner 支持)。
示例:限制数据库迁移作业的并发
yaml 运行db\_migrate:script:- run-migrations.shresource\_group: database
12. 模板与复用
- CI/CD 模板:使用 include 引用公共模板(如 .NET, Python 官方模板)。
- 作业继承:通过 extends 复用配置,减少重复代码。
示例:继承官方 Python 模板
yaml 运行include:- template: Python.gitlab-ci.ymlstages:- build- test- deploy\# 自定义测试命令testextends: .python-testscript:- pytest --cov=myapp
三、Runner 配置
GitLab Runner 是执行 CI/CD 作业的引擎,其配置直接影响 Pipeline 的性能和稳定性。以下是关键配置步骤和最佳实践:
1. Runner 安装与注册
1.1 安装 Runner
根据操作系统选择安装方式(以 Linux 为例):
bash 运行\# 下载二进制文件sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64\# 赋予执行权限sudo chmod +x /usr/local/bin/gitlab-runner\# 创建用户sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash\# 安装并启动服务sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runnersudo gitlab-runner start
1.2 注册 Runner
获取项目或组的注册令牌(Settings → CI/CD → Runners)后执行:
bash 运行sudo gitlab-runner register \--url https://gitlab.com/ \--registration-token YOUR\_REGISTRATION\_TOKEN \--executor docker \--docker-image alpine:latest \--description "my-docker-runner" \--tag-list "docker,linux" \--run-untagged \--locked="false"
2.核心配置文件
Runner 的全局配置位于 /etc/gitlab-runner/config.toml,常见参数:
toml 运行concurrent = 4 # 并发执行的 Pipeline 数量check\_interval = 30 # 检查新作业的间隔(秒)[session\_server]session_timeout = 1800 # 会话超时时间[[runners]]name = "my-docker-runner"url = "https://gitlab.com/"token = "YOUR\_RUNNER\_TOKEN"executor = "docker"[runners.docker]tls_verify = falseimage = "alpine:latest"privileged = falsedisable_entrypoint\_overwrite = falseoom_kill_disable = falsedisable_cache = falsevolumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"\] # 挂载 Docker 套接字支持 dindshm_size = 2147483648 # 共享内存大小(2GB)[runners.cache]Type = "s3"Path = "cache"Shared = true[runners.cache.s3]ServerAddress = "s3.amazonaws.com"AccessKey = "YOUR_ACCESS_KEY"SecretKey = "YOUR_SECRET_KEY"BucketName = "gitlab-runner-cache"Insecure = false
3. 执行器配置
3.1 Docker 执行器
适用于容器化环境,需安装 Docker:
toml 运作[[runners]]executor = "docker"[runners.docker]image = "python:3.9" \# 默认镜像pull_policy = "if-not-present" \# 镜像拉取策略network_mode = "host" \# 网络模式
3.2 Kubernetes 执行器
适用于大规模集群,动态创建 Pod 执行作业:
toml 运作[[runners]]executor = "kubernetes"[runners.kubernetes]host = "https://kubernetes-api:443"namespace = "gitlab-runner"image = "alpine:latest"cpu_limit = "1"memory_limit = "512Mi"service_cpu_limit = "500m"service_memory_limit = "128Mi"
3.3 Shell 执行器
直接在 Runner 主机上执行命令(需谨慎配置权限):
toml 运行[[runners]]executor = "shell"
4. 高级配置
4.1 缓存优化
使用 S3 或 MinIO 作为分布式缓存:
toml 运作[runners.cache]Type = "s3"Path = "my-project-cache"Shared = true[runners.cache.s3]ServerAddress = "minio.example.com:9000"AccessKey = "minio_access_key"SecretKey = "minio_secret_key"BucketName = "runner-cache"Insecure = true \# 使用 HTTP
4.2 镜像拉取加速
配置 Docker 镜像加速器:
toml 运行[runners.docker]image = "alpine:latest"registry_mirrors = ["https://registry.docker-cn.com"]
4.3 自定义 Hooks
在作业前后执行自定义脚本:
toml 运行[[runners]]pre_build_script = "echo 'Preparing environment...'"post_build_script = "echo 'Cleaning up...'"
5. Runner 管理命令
bash 运行\# 查看状态sudo gitlab-runner status\# 重启 Runnersudo gitlab-runner restart\# 查看已注册的 Runnersudo gitlab-runner list\# 验证 Runner 配置sudo gitlab-runner verify\# 升级 Runnersudo gitlab-runner upgrade
6. 安全与权限
- 最小权限原则:避免使用 privileged = true,确有需要时使用 cap_add 细化权限。
- 隔离 Runner:为敏感项目创建专用 Runner,避免共享环境。
- 定期更新:及时升级 Runner 以修复安全漏洞。
- 加密通信:确保 Runner 与 GitLab 服务器通过 HTTPS 通信。
7. 监控与故障排除
日志查看:
bash 运行sudo journalctl -u gitlab-runner -f # 查看系统日志
性能监控:
使用 Prometheus 收集 Runner 指标
配置 concurrent 参数避免资源过载
本地调试:
bash 运行gitlab-runner exec docker test\_job # 本地执行作业
8. 最佳实践
- 按需扩展:使用 Auto Scaling Runner(如 AWS EC2、GKE)应对峰值负载。
- 标签分类:为 Runner 添加标签(如 docker, gpu, heavy),通过 tags 字段在 .gitlab-ci.yml 中指定使用特定 Runner。
- 版本对齐:保持 Runner 与 GitLab 版本一致(至少相差不超过 1 个 major 版本)。
- 资源限制:为每个作业设置合理的 CPU/Memory 限制,避免相互影响。
四、故障排除
1. Pipeline 未触发
1.1可能原因
- .gitlab-ci.yml 文件存在语法错误
- 分支 / 标签不匹配触发规则(only/except 或 rules)
- Runner 未在线或无可用执行器
- 项目设置中禁用了 CI/CD
1.2排查步骤
- 验证 YAML 语法
- 在 GitLab 项目的 CI/CD 设置页面使用 CI Lint 工具检查语法
- 本地安装 yamllint 进行静态检查
检查触发规则
yaml 运行\# 示例:仅在 main 分支和合并请求触发rules:- if: '$CI_COMMIT_BRANCH == "main" || $CI_PIPELINE_SOURCE == "merge_request_event"'when: always
确认 Runner 状态
在项目的 CI/CD 设置中查看 Runner 是否在线
检查 Runner 日志:sudo journalctl -u gitlab-runner -f
2. 作业执行失败
2.1 命令执行错误
- 现象:作业日志显示命令不存在或权限不足
解决方案:
- 确认镜像中是否包含所需工具(如 npm, python)
使用 before_script 安装依赖:
yaml 运行before_script:- apt-get update && apt-get install -y curl
2.2 依赖缓存问题
- 现象:每次构建都重新下载依赖,耗时过长
解决方案:
yaml 运行cache:key: ${CI_COMMIT_REF_SLUG}paths:- node_modules/
2.3 网络连接超时
- 现象:无法访问外部资源(如 GitHub、npm 仓库)
解决方案:
配置镜像源(如 npm、pip):
yaml 运行before_script:- npm config set registry https://registry.npmmirror.com
检查 Runner 网络配置,确保能访问公网
3. Runner 相关问题
3.1 Runner 未注册或离线
解决方案:
bash 运行\# 注册新 Runnersudo gitlab-runner register\# 检查状态sudo gitlab-runner status\# 重启 Runnersudo gitlab-runner restart
3.2 权限不足
- 现象:作业无法访问文件或执行命令
- 解决方案:
- 确保 Runner 用户有足够权限
- 避免使用 root 用户,通过 chmod 调整文件权限
3.3 磁盘空间不足
解决方案:
bash 运行\# 清理 Docker 镜像docker system prune -a\# 调整缓存过期时间artifacts:expire_in: 1 hour
4. Artifacts/Cache 问题
4.1 Artifacts 未传递
- 现象:后续作业无法访问之前作业的 artifacts
解决方案:
确保 artifacts.paths 路径正确
使用 dependencies 明确指定依赖的作业:
yaml 运行test:dependencies:- build
4.2 Cache 失效
- 现象:缓存未命中,重新下载依赖
解决方案:
使用稳定的缓存键(如 key: ${CI_PROJECT_ID}-npm)
检查 cache.paths 是否与依赖路径匹配
5. Docker 执行器问题
5.1 镜像拉取失败
- 现象:Failed to pull image 错误
解决方案:
yaml 运行\# 使用国内镜像源[runners.docker]registry_mirrors = ["https://registry.docker-cn.com"]
5.2 Docker-in-Docker (DinD) 问题
- 现象:作业内无法运行 Docker 命令
解决方案:
yaml 运行\# 挂载 Docker 套接字services:- docker:dindvariables:DOCKER_HOST: tcp://docker:2375DOCKER_TLS_CERTDIR: ""
6. Kubernetes 执行器问题
6.1 Pod 创建失败
- 现象:Runner 无法创建 Pod 执行作业
解决方案:
bash 运行\# 检查集群连接kubectl get nodes\# 查看 Runner 权限配置kubectl get rolebindings -n gitlab-runner
6.2 资源不足
- 现象:Pod 因资源不足被驱逐
解决方案:
yaml 运行\# 调整资源请求[runners.kubernetes]cpu_request = "500m"memory_request = "512Mi"
7. 高级调试技巧
7.1 本地执行作业
bash 运行\# 使用 gitlab-runner 本地执行作业gitlab-runner exec docker test_job
7.2 使用 debug 模式
yaml 运行\# 在 .gitlab-ci.yml 中添加调试信息variables:CI_DEBUG_TRACE: "true"
7.3 分步调试
yaml 运行\# 使用 allow\_failure 允许作业失败但不影响 Pipeline 状态test:script:- run-tests.shallow_failure: true