GitLab CI/CD 流水线配置与运维实战
一、概述
GitLab CI/CD 是 GitLab 内置的持续集成和持续部署工具,通过 .gitlab-ci.yml 配置文件定义流水线,实现代码构建、测试、部署的自动化。本文介绍 GitLab CI/CD 的核心概念、配置方法及运维实践。
二、核心概念
2.1 流水线(Pipeline)
流水线是 CI/CD 的核心执行单元,由多个阶段(Stage)组成,每个阶段包含若干作业(Job)。
1 2 3 4 5 6 7 8 9
| Pipeline ├── Stage: build │ ├── Job: compile │ └── Job: package ├── Stage: test │ ├── Job: unit-test │ └── Job: integration-test └── Stage: deploy └── Job: production
|
2.2 作业(Job)
作业是流水线的基本执行单元,每个作业定义了在特定条件下执行的脚本命令。
2.3 Runner
Runner 是执行作业的执行器,分为:
- Shared Runner:GitLab 实例共享,所有项目可用
- Group Runner:组内项目共享
- Project Runner:专属特定项目
- 按执行方式:Shell、Docker、Kubernetes、SSH 等
三、安装与配置
3.1 安装 GitLab Runner
1 2 3 4 5 6 7
| curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash sudo apt-get install gitlab-runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash sudo yum install gitlab-runner
|
3.2 注册 Runner
1 2 3 4 5 6 7 8 9
| sudo gitlab-runner register
|
3.3 配置 Runner
编辑 /etc/gitlab-runner/config.toml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| concurrent = 4 check_interval = 0
[[runners]] name = "docker-runner" url = "https://gitlab.example.com" token = "xxxxxxxxxxxx" executor = "docker" [runners.docker] tls_verify = false image = "docker:24.0" privileged = false disable_cache = false volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"] shm_size = 0 [runners.cache] [runners.cache.s3] [runners.cache.gcs]
|
重启 Runner:
1
| sudo systemctl restart gitlab-runner
|
四、.gitlab-ci.yml 配置详解
4.1 基础结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| stages: - build - test - deploy
variables: DOCKER_DRIVER: overlay2 BUILD_IMAGE: myapp:${CI_COMMIT_SHA}
build_job: stage: build script: - echo "Building application..." - docker build -t $BUILD_IMAGE . only: - main - develop
test_job: stage: test script: - echo "Running tests..." - npm test artifacts: reports: junit: test-results.xml expire_in: 1 week
deploy_job: stage: deploy script: - echo "Deploying to production..." - kubectl apply -f k8s/ only: - main environment: name: production url: https://app.example.com
|
4.2 常用关键字
| 关键字 |
说明 |
stages |
定义流水线阶段顺序 |
script |
作业执行的命令 |
only/except |
控制作业触发条件 |
rules |
更灵活的条件控制(推荐) |
variables |
定义变量 |
artifacts |
作业产物配置 |
cache |
缓存配置 |
dependencies |
作业依赖 |
needs |
显式定义作业依赖关系 |
environment |
部署环境配置 |
tags |
指定 Runner 标签 |
4.3 条件控制示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| deploy_prod: stage: deploy script: - ./deploy.sh production rules: - if: $CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push" - if: $CI_COMMIT_TAG when: manual
manual_approval: stage: deploy script: - echo "Manual approval passed" when: manual
|
4.4 缓存配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/ - .npm/
cache_deps: key: deps-${CI_COMMIT_REF_SLUG} paths: - node_modules/ policy: pull-push
cache_build: key: build-${CI_COMMIT_REF_SLUG} paths: - dist/ policy: push
|
4.5 多环境部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| stages: - build - test - deploy:staging - deploy:production
.deploy_template: stage: deploy script: - ./deploy.sh $ENVIRONMENT environment: name: $ENVIRONMENT url: $ENV_URL
deploy_staging: extends: .deploy_template variables: ENVIRONMENT: staging ENV_URL: https://staging.app.example.com rules: - if: $CI_COMMIT_BRANCH == "develop"
deploy_production: extends: .deploy_template variables: ENVIRONMENT: production ENV_URL: https://app.example.com rules: - if: $CI_COMMIT_BRANCH == "main" when: manual
|
五、Docker 构建优化
5.1 Docker-in-Docker (DinD)
1 2 3 4 5 6 7 8 9 10 11
| docker_build: stage: build image: docker:24.0-dind services: - docker:24.0-dind variables: DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_CERTDIR: "/certs" script: - docker build -t myapp:$CI_COMMIT_SHA . - docker push myapp:$CI_COMMIT_SHA
|
5.2 使用 Docker Socket 绑定
1 2 3 4 5 6 7 8 9
| docker_build_socket: stage: build image: docker:24.0 variables: DOCKER_HOST: unix:///var/run/docker.sock volumes: - /var/run/docker.sock:/var/run/docker.sock script: - docker build -t myapp:$CI_COMMIT_SHA .
|
5.3 多阶段构建
1 2 3 4 5 6 7 8 9 10 11 12
| build_optimized: stage: build script: - | docker build \ --build-arg BUILDKIT_INLINE_CACHE=1 \ --cache-from myapp:latest \ -t myapp:$CI_COMMIT_SHA \ -t myapp:latest \ . - docker push myapp:$CI_COMMIT_SHA - docker push myapp:latest
|
六、安全实践
6.1 敏感信息管理
使用 CI/CD 变量(推荐):
在 GitLab 项目设置 → CI/CD → Variables 中配置:
DOCKER_REGISTRY_USERNAME
DOCKER_REGISTRY_PASSWORD
KUBECONFIG_CONTENT
DEPLOY_SSH_KEY
1 2 3 4
| deploy: script: - echo "$DOCKER_REGISTRY_PASSWORD" | docker login -u "$DOCKER_REGISTRY_USERNAME" --password-stdin - docker push myapp:$CI_COMMIT_SHA
|
6.2 保护分支和标签
1 2 3 4 5
| deploy_prod: script: - ./deploy.sh rules: - if: $CI_COMMIT_REF_PROTECTED == "true"
|
6.3 作业权限控制
1 2 3 4 5 6 7
| manual_deploy: script: - ./deploy.sh when: manual rules: - if: $GITLAB_USER_LOGIN == "admin" || $GITLAB_USER_LOGIN == "devops"
|
七、运维监控
7.1 流水线监控指标
1 2 3 4 5 6
| # GitLab 暴露的指标(需启用 Prometheus) gitlab_ci_pipeline_duration_seconds gitlab_ci_pipeline_status gitlab_ci_job_duration_seconds gitlab_ci_job_status gitlab_runner_jobs
|
7.2 告警规则示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| groups: - name: gitlab_ci rules: - alert: GitLabPipelineFailed expr: gitlab_ci_pipeline_status{status="failed"} == 1 for: 5m labels: severity: warning annotations: summary: "GitLab 流水线失败" description: "项目 {{ $labels.project }} 的流水线失败"
- alert: GitLabJobQueuedTooLong expr: gitlab_ci_job_queued_seconds > 600 for: 10m labels: severity: warning annotations: summary: "GitLab 作业排队时间过长" description: "作业排队超过 10 分钟"
|
7.3 Runner 健康检查
1 2 3 4 5 6 7 8
| sudo gitlab-runner verify
sudo journalctl -u gitlab-runner -f
curl http://localhost:9252/metrics
|
八、故障排查
8.1 常见问题及解决方案
| 问题 |
可能原因 |
解决方案 |
| 作业一直 pending |
Runner 不可用/标签不匹配 |
检查 Runner 状态和标签配置 |
| Docker 构建失败 |
磁盘空间不足 |
清理 Docker 镜像和缓存 |
| 作业超时 |
网络问题/资源不足 |
增加 timeout 或优化脚本 |
| 变量未生效 |
变量作用域错误 |
检查变量配置在项目/组级别 |
| 缓存未命中 |
缓存 key 不匹配 |
统一缓存 key 格式 |
8.2 调试技巧
1 2 3 4 5 6 7
| debug_job: script: - set -x - echo "CI_COMMIT_SHA: $CI_COMMIT_SHA" - echo "CI_JOB_ID: $CI_JOB_ID" - env | sort
|
8.3 查看作业日志
1 2 3 4
|
curl --header "PRIVATE-TOKEN: <token>" \ "https://gitlab.example.com/api/v4/projects/<id>/jobs/<job_id>/trace"
|
九、最佳实践总结
- 使用模板减少重复:通过
extends 和 template 复用配置
- 合理设置缓存:加速构建,但注意缓存大小
- 并行化作业:独立作业并行执行,缩短流水线时间
- 保护敏感信息:使用 CI/CD 变量,不在代码中硬编码
- 使用 rules 替代 only/except:更灵活的条件控制
- 设置作业超时:避免作业无限期运行
- 定期清理 artifacts:设置合理的过期时间
- 监控 Runner 资源:确保 Runner 有足够资源执行作业
十、参考资源