一、先理解架构:Runner 到底是怎么工作的?
在上一篇中,我们把 Runner 比作"工人",但它到底是如何和 GitLab 协作的?先看一张架构图:
┌─────────────────────────────────────────────────────┐
│ GitLab 服务器 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Pipeline │ │ Job 队列 │ │ 结果存储 │ │
│ └──────────┘ └─────┬────┘ └──────────┘ │
└───────────────────────┼─────────────────────────────┘
│ ① 轮询新任务
│ ② 分配 Job
│ ③ 回传结果
┌───────────────────────┼─────────────────────────────┐
│ Runner 机器(你的服务器 / K8s 集群) │
│ ┌────────────────────▼───────────────────────────┐ │
│ │ GitLab Runner 进程 │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Executor(执行器) │ │ │
│ │ │ Shell │ Docker │ Kubernetes │ ... │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘关键理解:
Runner 和 GitLab 是分离的:Runner 是独立安装的进程,通过 HTTPS 或 HTTP 与 GitLab 服务器通信
Runner 主动拉取(Pull)而非被动接收:Runner 持续轮询 GitLab 看有没有新任务,而不是 GitLab 推送过来
Executor 决定"在什么环境里执行":同一个 Runner 进程,可以通过不同的 Executor 在宿主机 Shell、Docker 容器或 K8s Pod 中执行任务
Runner 的三种范围
二、三种执行器(Executor)对比
选型建议:
个人项目或小团队 → Docker Executor(平衡了隔离性和简单性)
物理机 / 虚拟机已有环境 → Shell Executor(最简单)
已有 K8s 集群、需要弹性伸缩 → Kubernetes Executor
三、通用前置:获取注册令牌(Registration Token)
不管你用哪种执行器,注册 Runner 时都需要一个 Token。获取方式因 Runner 范围而异:
方式一:GitLab Web UI(推荐)
Shared Runner:Admin Area → CI/CD → Runners → New instance runner
Group Runner:Group → Settings → CI/CD → Runners → New group runner
Project Runner:Project → Settings → CI/CD → Runners → New project runner
GitLab 16+ 版本后推荐创建 Runner 时勾选 "Run untagged jobs",这样即使你的 Job 没有指定 tags,该 Runner 也会接收任务。
方式二:注册完成后运行交互式注册命令
新版本 GitLab 会在创建 Runner 时直接展示注册命令,复制粘贴即可。旧版本则需要手动记下 Token 后执行 gitlab-runner register。
四、Shell Executor:最直白的开始
4.1 安装 GitLab Runner
Linux(Debian/Ubuntu):
# 添加官方仓库
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
# 安装
sudo apt-get install gitlab-runnerLinux(RHEL/CentOS):
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash
sudo yum install gitlab-runnermacOS:
brew install gitlab-runner4.2 注册 Runner(交互式)
sudo gitlab-runner register交互式问答环节:
Enter the GitLab instance URL:
https://gitlab.example.com # ← 你的 GitLab 地址
Enter the registration token:
glrt-xxxxxxxxxxxxxxxx # ← 前面获取的 Token
Enter a description for the runner:
my-shell-runner # ← 起个描述名称
Enter tags for the runner (comma-separated):
shell,linux # ← 打标签,后续 Job 用 tags 选择
Enter optional maintenance note:
用于构建和部署的后端任务
Enter an executor:
shell # ← 选择 shell4.3 非交互式注册(一行命令)
sudo gitlab-runner register --non-interactive \
--url "https://gitlab.example.com" \
--registration-token "glrt-xxxxxxxxxxxxxxxx" \
--name "my-shell-runner" \
--tag-list "shell,linux" \
--executor "shell"4.4 验证 Runner 状态
# 查看已注册的 Runner
sudo gitlab-runner list
# 输出示例
Runtime platform arch=amd64 os=linux pid=1234 revision=abc123
Listing configured runners
my-shell-runner Executor=shell Token=xxxx URL=https://gitlab.example.com回到 GitLab Web UI → Settings → CI/CD → Runners,你应该能看到刚注册的 Runner 显示为绿色圆点(在线状态)。
4.5 测试你的 Runner
在项目中创建如下 .gitlab-ci.yml:
shell-test:
tags:
- shell # ← 匹配前面设置的 tag
script:
- whoami
- pwd
- echo "宿主机内核版本:$(uname -r)"提交后,如果 Pipeline 成功运行并输出了宿主机信息,说明 Shell Executor 配置成功。
4.6 Shell Executor 的坑与注意事项
环境依赖:Shell Executor 直接用宿主机的 Shell,所以你的依赖(Node.js、Java、Python 等)必须提前在宿主机上装好
安全性:Job 脚本拥有 gitlab-runner 用户的权限,小心权限泄露
残留文件:Job 执行完后,工作目录会保留,需要定期清理。可以在 /etc/gitlab-runner/config.toml 中设置清理策略
并发控制:默认 concurrent = 1,即同时只能跑一个 Job
五、Docker Executor:生产环境的首选
5.1 安装 GitLab Runner(Docker 方式)
最推荐的方式是用 Docker 运行 Runner 本身:
docker pull gitlab/gitlab-runner:latest
docker run -d \
--name gitlab-runner \
--restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest💡 关键:-v /var/run/docker.sock:/var/run/docker.sock 将宿主机的 Docker 套接字挂进容器,这样 Runner 才能"操控"宿主机 Docker 来启动 Job 容器。这就是所谓的 Docker-out-of-Docker (DooD) 模式。
5.2 注册 Runner
docker exec -it gitlab-runner gitlab-runner register \
--non-interactive \
--url "https://gitlab.example.com" \
--registration-token "glrt-xxxxxxxxxxxxxxxx" \
--name "my-docker-runner" \
--tag-list "docker,linux" \
--executor "docker" \
--docker-image "alpine:latest" \
--docker-volumes "/var/run/docker.sock:/var/run/docker.sock"关键参数说明:
--executor "docker":指定使用 Docker 执行器
--docker-image "alpine:latest":默认镜像——当 Job 中没有显式指定 image 时使用
--docker-volumes:挂载 Docker Socket,使 Job 容器内也能操作 Docker(Docker in Docker 的基础)
5.3 Docker Executor 的工作流程
当你提交代码后,Docker Executor 的执行过程是这样的:
① Runner 收到任务
② 拉取 job 中 image 指定的镜像(如 node:20)
③ 启动一个全新的容器
④ 在容器内克隆你的代码
⑤ 执行 before_script → script → after_script
⑥ 上传 artifacts 和日志
⑦ 销毁容器(默认行为)每次 Job 都是在全新的容器中运行,这保证了环境的一致性和隔离性。
5.4 Docker in Docker (DinD):在容器里构建 Docker 镜像
如果你的 CI 需要构建 Docker 镜像(常见于部署阶段),需要配置 DinD:
build-docker-image:
image: docker:latest
stage: build
services:
- docker:dind # ← 启动一个 Docker daemon 作为服务
variables:
DOCKER_TLS_CERTDIR: "" # ← 关闭 TLS(简化配置)
script:
- docker build -t myapp:$CI_COMMIT_SHORT_SHA .
- docker push registry.example.com/myapp:$CI_COMMIT_SHORT_SHA⚠️ 使用 DinD 时,Runner 注册时必须挂载了 /var/run/docker.sock 或在配置中启用了 privileged = true。
5.5 config.toml 关键配置
Runner 注册后,配置存储在 /etc/gitlab-runner/config.toml(或你挂载的卷中)。几个值得关注的参数:
concurrent = 4 # 全局最大并发 Job 数
[[runners]]
name = "my-docker-runner"
url = "https://gitlab.example.com"
token = "glrt-xxxxxxxx"
executor = "docker"
limit = 2 # 此 Runner 最大并发数
[runners.docker]
image = "alpine:latest"
privileged = false # 谨慎开启!
volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
shm_size = 256000000 # /dev/shm 大小(256MB),Node.js 项目可能需要
pull_policy = "if-not-present" # 镜像拉取策略六、Kubernetes Executor:面向云原生的弹性方案
6.1 为什么需要 K8s Executor?
当你的团队扩张到几十甚至上百个开发者,每天触发数百次 Pipeline 时,Docker Executor 的固定资源模型就不够了。K8s Executor 的核心优势:
弹性伸缩:每个 Job 启动一个独立 Pod,执行完自动销毁,资源回收
原生资源管理:通过 Pod 的 requests/limits 精确控制 CPU 和内存
集群调度:利用 K8s 调度器自动选择最优节点
6.2 使用 Helm 安装(推荐)
# 添加 GitLab Helm 仓库
helm repo add gitlab https://charts.gitlab.io
helm repo update
# 安装 Runner
helm install gitlab-runner gitlab/gitlab-runner \
--namespace gitlab-runner \
--create-namespace \
--set gitlabUrl=https://gitlab.example.com \
--set runnerRegistrationToken="glrt-xxxxxxxxxxxxxxxx" \
--set rbac.create=true \
--set runners.tags="k8s,linux"6.3 自定义 values.yaml
更推荐的方式是创建一个 values.yaml 文件来控制所有参数:
# values.yaml
gitlabUrl: "https://gitlab.example.com"
runnerRegistrationToken: "glrt-xxxxxxxxxxxxxxxx"
# 并发控制
concurrent: 10
# Runner 配置
runners:
tags: "k8s,linux"
privileged: false
config: |
[[runners]]
[runners.kubernetes]
namespace = "gitlab-runner"
image = "alpine:latest"
# 资源限制
[runners.kubernetes.pod_spec]
[[runners.kubernetes.pod_spec.containers]]
name = "build"
resources.requests.cpu = "500m"
resources.requests.memory = "512Mi"
resources.limits.cpu = "2"
resources.limits.memory = "2Gi"
# 持久化缓存(可选,使用 PVC)
[[runners.kubernetes.volumes.pvc]]
name = "runner-cache"
mount_path = "/cache"安装:
helm install gitlab-runner gitlab/gitlab-runner \
--namespace gitlab-runner \
--create-namespace \
-f values.yaml6.4 K8s Executor 的工作流程
① GitLab 分配 Job 给 K8s Runner
② Runner 创建以下资源:
- 一个 ConfigMap(注入构建脚本)
- 一个 Pod(包含 build + helper + service 容器)
- build 容器运行你的 script
- helper 容器负责克隆代码、上传 artifacts
- service 容器运行你声明的附加服务(如数据库)
③ Job 完成后自动清理 Pod6.5 使用 K8s Executor 的 Job 配置
k8s-job:
tags:
- k8s # ← 匹配 K8s Runner
image: node:20
script:
- npm install
- npm test
# K8s Executor 特有:自定义 Pod 资源
variables:
KUBERNETES_CPU_REQUEST: "500m"
KUBERNETES_CPU_LIMIT: "2"
KUBERNETES_MEMORY_REQUEST: "512Mi"
KUBERNETES_MEMORY_LIMIT: "2Gi"七、Runner 管理与运维
7.1 常用运维命令
# 查看所有 Runner
sudo gitlab-runner list
# 验证 Runner 配置
sudo gitlab-runner verify
# 取消注册某个 Runner
sudo gitlab-runner unregister --name "my-runner"
# 重启 Runner 服务
sudo gitlab-runner restart
# 查看 Runner 日志
sudo journalctl -u gitlab-runner -f7.2 Runner Tags:精确调度
Tags 是 Runner 选择机制的核心。一套成熟的 Tag 策略建议分层级:
Job 中指定 Tags:
heavy-build:
tags:
- docker
- large-memory
- linux
script:
- make build⚠️ Job 指定的 tags 必须全部匹配,Runner 才会接收。上面这个 Job 只会被同时拥有 docker、large-memory 和 linux 三个 Tag 的 Runner 执行。
7.3 并发控制
# /etc/gitlab-runner/config.toml
concurrent = 8 # 全局最大并发
[[runners]]
limit = 4 # 此 Runner 最大并发7.4 监控 Runner 健康
GitLab Web UI → Admin Area → Runners 可以看到:
每个 Runner 的在线状态(上次心跳时间)
当前正在执行的任务数
Runner 版本信息
也可以用 API 查询:
curl --header "PRIVATE-TOKEN: <your-token>" \
"https://gitlab.example.com/api/v4/runners"八、小结与下篇预告
三种方案对比速查
下篇预告
有了 Runner 这双"手脚",接下来就要学习如何写出一份高质量的"施工图纸"。第三篇《核心关键字详解:stages / jobs / variables / cache / artifacts》将深入讲解流水线配置中最常用、最重要的五个关键字类别,让你从"能跑"升级到"跑得好"。
参考资料: