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
# Ubuntu/Debian
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt-get install gitlab-runner

# CentOS/RHEL
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

# 按提示输入:
# GitLab URL: https://gitlab.example.com
# Registration token: <从 GitLab 项目设置获取>
# Runner description: my-docker-runner
# Tags: docker,build
# Executor: docker
# Docker image: docker:24.0

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
# 使用 rules(推荐)
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
# Prometheus 告警规则
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
# 检查 Runner 状态
sudo gitlab-runner verify

# 查看 Runner 日志
sudo journalctl -u gitlab-runner -f

# 检查 Runner 指标
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
# GitLab UI:进入流水线 → 点击作业 → 查看日志
# 或通过 API
curl --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.example.com/api/v4/projects/<id>/jobs/<job_id>/trace"

九、最佳实践总结

  1. 使用模板减少重复:通过 extendstemplate 复用配置
  2. 合理设置缓存:加速构建,但注意缓存大小
  3. 并行化作业:独立作业并行执行,缩短流水线时间
  4. 保护敏感信息:使用 CI/CD 变量,不在代码中硬编码
  5. 使用 rules 替代 only/except:更灵活的条件控制
  6. 设置作业超时:避免作业无限期运行
  7. 定期清理 artifacts:设置合理的过期时间
  8. 监控 Runner 资源:确保 Runner 有足够资源执行作业

十、参考资源