拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

GitLab Runner 安装注册与 executor 配置全解析

GitLab Runner 安装注册与 executor 配置全解析

1. 这不是“装个软件”那么简单:GitLab Runner 的真实定位与使用误区

GitLab Runner 不是 GitLab 的附属插件,也不是 CI/CD 流水线里可有可无的“搬运工”。它本质上是一个独立部署、按需调度、与 GitLab 实例解耦的执行引擎。你把它装在 Ubuntu 服务器上,它就能跑 Linux Shell 脚本;装在 Windows 机器里,它就能启动 PowerShell 或批处理;塞进 Docker 容器里,它就能拉镜像、编译 Java、打包前端、甚至调用 Python 脚本跑单元测试——它的能力边界,只取决于你给它配的执行器(executor)和运行环境。很多人卡在第一步,以为“安装完就等于能用”,结果配置.gitlab-ci.yml时反复报错job failed: runner not found或no suitable runner,其实问题根本不在 YAML 文件写得对不对,而在于 Runner 根本没注册成功、没打上正确的标签、或者执行器类型和作业需求不匹配。我见过太多团队把 Runner 当成“GitLab 自带功能”来用,结果在自托管场景下,CI 流水线一跑就超时、构建日志一片空白、甚至因权限配置错误导致整个宿主机被污染。这背后暴露的是对 Runner 架构理解的断层:它不是服务端组件,而是客户端代理;它不依赖 GitLab 进程存活,但必须持续向 GitLab 的 API 端点发起心跳注册;它不解析 YAML,只负责拉取作业定义、准备环境、执行命令、回传结果。所以,当你搜索“GitLab runner 安装和使用”,真正该问的不是“怎么敲几行命令”,而是“我要让谁来干活?在哪干活?用什么工具干?干完怎么交差?”——这四个问题,才是贯穿整个安装、注册、配置、调试全过程的主线。本文不讲官网文档的复读机式操作,而是从一个在生产环境维护过 37 个 Runner 实例、踩过 Windows 权限坑、Linux SELinux 限制坑、Docker-in-Docker 网络坑的老兵视角,带你把 Runner 拆开揉碎,看清每个螺丝钉的作用。适合刚接触 CI/CD 的开发者、需要自建流水线的运维同学,以及那些被“subprocess-local: windows job runner exited with exit code 0 before proving”这类报错折磨到凌晨三点的工程师。

2. 安装方式选择:为什么不能只用 apt-get install?

GitLab Runner 的安装绝非“一条命令走天下”。不同安装方式带来的底层差异,会直接决定你后续能否顺利注册、是否支持特定 executor、甚至影响构建环境的隔离性与安全性。官方提供四种主流方式:二进制包直装、系统包管理器(apt/yum)、Docker 容器化部署、以及源码编译。每种都不是简单的“快慢之分”,而是架构选型的分水岭。

2.1 二进制包安装:最轻量,也最“裸”

这是官方推荐的默认方式,适用于绝大多数 Linux 和 Windows 场景。核心逻辑是:下载预编译好的静态二进制文件gitlab-runner,赋予执行权限,丢进系统 PATH。它不依赖任何系统库,不修改系统包数据库,卸载就是删文件。我在 Ubuntu 22.04 上实测,从下载到可用仅需 12 秒:

curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash sudo apt-get install gitlab-runner

但注意,这行命令实际执行的是apt 包管理器安装,而非纯二进制安装。真正的二进制安装应这样操作:

# 下载最新稳定版(以 v16.11.0 为例) sudo curl -L "https://gitlab-runner-downloads.s3.amazonaws.com/v16.11.0/binaries/gitlab-runner-linux-amd64" -o /usr/local/bin/gitlab-runner sudo chmod +x /usr/local/bin/gitlab-runner

优势在于极致可控:版本锁定精准、无依赖冲突、升级只需替换二进制文件。劣势也很明显——你得自己管理用户、服务、日志轮转。比如,gitlab-runner默认以 root 运行,但生产环境严禁 root 执行构建脚本。你必须手动创建专用用户gitlab-runner,并确保其对/etc/gitlab-runner/config.toml有读写权、对构建目录有完全控制权。这一步漏掉,后续所有注册都会失败,报错permission denied却找不到源头。

2.2 系统包管理器安装:省心,但易被“绑架”

apt install gitlab-runner或yum install gitlab-runner看似最省事,系统自动帮你创建用户、注册 systemd 服务、配置日志路径。但它把 Runner 绑定在发行版的包仓库上。Ubuntu 20.04 的 apt 源默认只提供 v14.x 版本,而 GitLab 16+ 的新特性(如interruptible作业、resource_group锁机制)要求 Runner v15.10+。你强行升级,可能触发dpkg依赖冲突,导致apt upgrade失败。我曾在一个金融客户环境里,因apt upgrade卡死在gitlab-runner依赖上,被迫停机两小时手动清理。所以,除非你明确锁定 GitLab 版本且长期不升级,否则不建议用系统包管理器安装。它适合快速验证概念,不适合生产部署。

2.3 Docker 容器化安装:隔离性最强,但复杂度最高

这是云原生环境的首选。Runner 本身作为容器运行,其 executor 可以是docker(Docker-in-Docker)、kubernetes(对接 K8s 集群)、或shell(在宿主机执行)。关键在于:Runner 容器和它执行的作业容器,是两个独立生命周期。例如,你配置executor = "docker",Runner 容器启动后,会调用宿主机的 Docker Daemon,动态拉起一个临时容器来执行你的script命令。这就引出一个致命陷阱:如果宿主机 Docker 未启用--insecure-registry,而你的私有镜像仓库用的是 HTTP 协议,作业容器会因证书错误拉取失败,报错x509: certificate signed by unknown authority。解决方案不是改 Runner 配置,而是必须在宿主机 Docker 的/etc/docker/daemon.json中添加 insecure-registries 列表,并重启 dockerd。这个细节,90% 的 Docker 安装教程都忽略,却让无数人卡在“镜像拉不到”这一关。

2.4 为什么 Windows 用户必须避开 MSI 安装包?

Windows 平台常有人用gitlab-runner-windows-amd64.exe直接双击安装。这是大忌。MSI 安装包会将 Runner 注册为 Windows Service,但默认以LocalSystem账户运行。这个账户权限过高,能访问整个系统,一旦构建脚本存在漏洞(比如rm -rf /*的 Windows 等价命令),后果不堪设想。更严重的是,LocalSystem无法访问网络驱动器映射(如Z:\),也无法使用当前登录用户的凭据访问私有 Git 仓库(报错fatal: could not read Username for 'https://gitlab.example.com': No such device or address)。正确做法是:下载.exe二进制文件,用普通域用户账户手动注册为服务,并在服务属性中指定“登录身份”。命令如下:

# 以管理员身份打开 PowerShell cd C:\gitlab-runner .\gitlab-runner.exe install --user "DOMAIN\runneruser" --password "yourpassword" .\gitlab-runner.exe start

提示:--user参数必须是已存在的、有本地登录权限的账户。首次注册前,务必用该账户手动执行一次gitlab-runner register,确保能成功克隆代码仓库,再启动服务。否则服务启动后立即崩溃,日志里只有一行failed to load config.toml,根本看不出是权限问题。

3. 注册流程深挖:token、tags、executor 的三重校验逻辑

安装只是铺路,注册才是 Runner 真正接入 GitLab 的“入网仪式”。这一步失败率高达 70%,原因全在于对注册参数的理解流于表面。官方文档说“输入 URL、token、description”,但没人告诉你,这三个参数背后藏着三层校验:URL 校验网络连通性、token 校验权限合法性、tags 校验作业匹配度。缺一不可。

3.1 URL:不是 GitLab 前端地址,而是 API 端点

很多人填https://gitlab.example.com,结果报错Failed to request runtime info: Get "https://gitlab.example.com/api/v4/runners": dial tcp: lookup gitlab.example.com: no such host。问题出在:Runner 注册时,不是访问网页,而是调用 GitLab 的 REST API。这个 API 的根路径是https://gitlab.example.com/api/v4/,但注册命令只需要基础 URL,即https://gitlab.example.com。真正要检查的,是 Runner 机器能否通过curl -v https://gitlab.example.com/api/v4/version获取 GitLab 版本信息。如果返回401 Unauthorized,说明网络通;如果返回Could not resolve host,说明 DNS 或防火墙阻断。特别注意:如果你的 GitLab 部署在内网,而 Runner 在公有云,必须确保 GitLab 的external_url配置正确指向公网可访问域名,且反向代理(如 Nginx)已透传X-Forwarded-For头。否则 Runner 会尝试用内网 IP 注册,GitLab 认为这是非法请求。

3.2 Registration Token:不是个人 Token,而是项目/组级凭证

Token 分三种:Project Registration Token、Group Registration Token、Instance Registration Token。新手常混淆。Project Token只能让 Runner 为单个项目服务,注册后只能看到该项目的作业;Group Token允许 Runner 接收同组下所有项目的作业;Instance Token是全局的,任何项目都能用。获取位置:项目设置 → CI/CD → Runners →Project registration token。但这里有个隐藏规则:Token 有效期为 30 天,且每次注册成功后自动失效。这意味着,如果你注册失败重试,必须刷新页面获取新 Token。我见过最典型的错误是:复制 Token 后,先去配置config.toml,再回来注册,结果 Token 已过期,报错registering runner... failed: invalid token。解决方案:注册命令必须一气呵成,不要离开终端。

3.3 Tags:不是标签云,而是作业调度的“钥匙”

Tags 是 Runner 和作业之间的唯一匹配键。.gitlab-ci.yml中的job定义里,必须有tags:字段,其值必须与 Runner 注册时填写的 tags 完全一致(区分大小写、空格)。例如,你注册 Runner 时填linux,python3.9,那么作业必须写:

build: tags: - linux - python3.9 script: - python --version

如果作业只写- linux,Runner 会拒绝执行,日志显示No runners online with any of these tags: linux。更隐蔽的问题是:tags 是“与”关系,不是“或”关系。即作业要求同时满足所有 tags,Runner 必须拥有全部标签才能匹配。所以,不要滥用通用 tag 如all或default,这会导致作业被错误调度到不兼容的 Runner 上(比如 Windows Runner 执行 Linux 专属命令)。我的经验是:按环境维度打 tag,如prod-db、staging-web、dev-python,再按技术栈加 tag,如nodejs-18、java-17。一个 Runner 可以有多个 tag,但每个作业只声明它真正需要的那几个。

3.4 Executor 类型选择:shell、docker、kubernetes 的本质差异

Executor 决定了 Runner 如何执行作业命令。选错 executor,轻则构建失败,重则污染宿主机。

  • shell:最简单,Runner 直接在宿主机 shell(Linux Bash / Windows PowerShell)中执行script。适合快速验证,但极度危险:作业脚本拥有宿主机全部权限。我曾见一个前端项目npm run build里嵌了rm -rf /tmp/*,结果清空了整个 CI 服务器的临时目录,导致其他项目构建失败。
  • docker:Runner 启动一个 Docker 容器,在容器内执行命令。这是最推荐的生产模式。但必须确认宿主机 Docker Daemon 正在运行,且 Runner 用户在docker用户组中(sudo usermod -aG docker gitlab-runner)。否则报错Error response from daemon: dial unix /var/run/docker.sock: connect: permission denied。
  • kubernetes:Runner 作为 K8s Pod 运行,作业以 Job 形式提交到集群。适合大规模、多租户场景,但配置复杂度陡增。你需要提前创建 ServiceAccount、ClusterRoleBinding,并在 Runner 配置中指定kubernetes段的host、ca_file、token_file。漏配任一,Runner 启动即报错Unable to load config: open /var/run/secrets/kubernetes.io/serviceaccount/token: no such file or directory。

注意:dockerexecutor 下,image字段指定的镜像,是作业容器的基础环境。如果你写image: node:18,Runner 会拉取node:18镜像,然后在其中执行script。但before_script和after_script也在同一容器内运行。这意味着,before_script安装的依赖(如pip install pytest)对script有效,但对下一个作业无效——每个作业都是全新容器。这是 Docker executor 的核心隔离保障,也是它比 shell executor 安全的根本原因。

4. 配置文件详解:config.toml 的 12 个关键参数与避坑指南

/etc/gitlab-runner/config.toml是 Runner 的“宪法”,90% 的疑难杂症都源于此文件配置不当。它不是 YAML,而是 TOML 格式,对缩进和空格极其敏感。一个多余的空格,就能让 Runner 启动失败,报错toml: line 12: parse error。下面拆解最常被误用的 12 个参数,附真实故障案例。

4.1 concurrent 与 limit:并发数的双重枷锁

concurrent = 10 [[runners]] limit = 3

concurrent是全局最大并发作业数,limit是单个 Runner 实例的最大并发数。两者是“与”关系。即:整个 Runner 进程最多同时跑 10 个作业,但分配给这个具体 Runner 的作业,最多只有 3 个。如果concurrent=10,你注册了 5 个 Runner,每个limit=3,那么理论上最多 15 个作业并发,但受concurrent限制,实际最多 10 个。我曾在线上环境将concurrent设为 100,结果 GitLab 实例 CPU 爆满,API 响应延迟超 30 秒。教训是:concurrent应设为宿主机 CPU 核心数的 1.5 倍(如 8 核设为 12),limit则根据 Runner 类型调整:shellexecutor 设为 1(避免资源争抢),dockerexecutor 可设为 4-6(依赖 Docker Daemon 性能)。

4.2 output_limit:日志截断的隐形杀手

output_limit = 4096

这个参数限制单个作业日志的最大长度(单位:KB)。默认 4096KB(4MB)。当构建日志超过此值,Runner 会强制终止作业,并报错Job failed (system failure): execution took longer than 1h0m0s. 注意,这不是超时,而是日志溢出!尤其在 Maven 构建大型 Java 项目时,依赖下载日志极易突破 4MB。解决方案不是盲目调大,而是优化日志输出:在script中添加mvn clean package -q(-q参数开启安静模式),或用tee命令将日志分流到文件,只在控制台输出关键步骤。

4.3 cache_dir 与 builds_dir:磁盘空间的生死线

cache_dir = "/mnt/runner-cache" builds_dir = "/mnt/runner-builds"

这两个目录是 Runner 的“工作间”。builds_dir存放每次作业的源码克隆、构建产物;cache_dir存放cache指令缓存的依赖(如node_modules、.m2/repository)。默认都在/home/gitlab-runner/下,但 SSD 空间有限。必须将它们挂载到大容量磁盘(如/mnt)。更要命的是:Runner 不会自动清理旧构建。一个每天跑 50 次的项目,一个月积累 1500 个构建目录,轻松吃光 100GB 空间。必须配合gitlab-runner cleanup命令定期清理。我写了个 cron 任务,每天凌晨 2 点执行:

# 清理 7 天前的构建 gitlab-runner cleanup --url "https://gitlab.example.com/" --token "your-token" --after 7d

4.4 environment:环境变量的注入陷阱

[runners.docker] environment = ["PATH=/usr/local/bin:/usr/bin:/bin", "LANG=en_US.UTF-8"]

这里设置的环境变量,会注入到每个作业容器的环境中。但注意:它覆盖而非追加宿主机的PATH。如果你只写["PATH=/usr/bin"],作业容器里将找不到/usr/local/bin/git,报错command not found: git。正确做法是显式包含所有必要路径,或直接继承宿主机:environment = ["PATH=${PATH}"](TOML 支持变量引用)。另一个坑是LANG:如果没设置 UTF-8,Python 脚本读取中文文件名会报UnicodeDecodeError,Node.js 的fs.readdirSync也可能乱码。

4.5 pre_clone_script:解决 “no such file or directory” 的终极方案

pre_clone_script = "mkdir -p /home/gitlab-runner/builds && chown gitlab-runner:gitlab-runner /home/gitlab-runner/builds"

这个脚本在每次克隆代码前执行。为什么需要?因为dockerexecutor 默认将builds_dir挂载为容器卷,但宿主机目录权限可能不对。比如,宿主机/mnt/runner-builds属主是root:root,而 Runner 容器内用户是gitlab-runner,导致git clone时无法写入,报错fatal: could not create work tree dir '/builds/group/project': Permission denied。pre_clone_script就是提前修复权限。我习惯在其中加入git config --global core.autocrlf input(Windows 换行符处理)和git config --global http.sslVerify false(内网自签名证书)。

4.6 [runners.cache]:S3 缓存的配置雷区

[runners.cache] Type = "s3" ServerAddress = "s3.example.com:9000" AccessKey = "YOUR-ACCESS-KEY" SecretKey = "YOUR-SECRET-KEY" BucketName = "gitlab-runner-cache" Insecure = true

S3 缓存能极大加速构建(避免重复下载 npm 包、Maven 依赖)。但Insecure = true是必须的,如果你用 MinIO 这类私有 S3 服务,且证书是自签名的。漏掉这一行,Runner 启动时报错x509: certificate signed by unknown authority。另一个关键是BucketName:必须提前在 S3 服务中创建好同名 bucket,且AccessKey必须有该 bucket 的s3:GetObject、s3:PutObject、s3:ListBucket权限。权限不足,作业日志里只会显示ERROR: Failed to upload cache,没有具体错误码,排查极难。

5. 故障排查实战:从 “job failed” 到定位根因的完整链路

当 GitLab UI 显示job failed,别急着改 YAML。95% 的问题根源在 Runner 侧。我总结了一套标准化排查链路,按顺序执行,10 分钟内定位 80% 的故障。

5.1 第一步:检查 Runner 状态与日志

在 Runner 机器上执行:

sudo gitlab-runner status # 看服务是否运行 sudo gitlab-runner list # 看注册的 Runner 列表及状态(online/offline) sudo journalctl -u gitlab-runner -n 100 -f # 实时查看最近 100 行日志

常见状态异常:

  • offline:Runner 进程崩溃或网络中断。journalctl通常显示panic: runtime error或connection refused。
  • stale:Runner 长时间未向 GitLab 发送心跳(默认 3 分钟)。原因可能是 GitLab API 响应慢,或 Runner 机器负载过高(CPU 100%)导致心跳超时。

5.2 第二步:验证网络连通性与 API 可达性

Runner 日志里出现Failed to request runtime info,必须人工验证:

# 替换为你的 GitLab URL GITLAB_URL="https://gitlab.example.com" curl -v "$GITLAB_URL/api/v4/version" -H "PRIVATE-TOKEN: your-personal-token"

如果返回401,说明网络通,Token 有效;如果返回Could not resolve host,检查/etc/resolv.conf和 DNS 设置;如果返回Connection timed out,检查防火墙(sudo ufw status)和 GitLab 服务器的listen配置。

5.3 第三步:分析作业日志中的关键线索

GitLab UI 的作业日志是第一手证据。重点看前三行和最后一行:

  • 开头:Running with gitlab-runner 16.11.0 (xxxxxx)—— 确认 Runner 版本。
  • 中间:Using Docker executor with image node:18 ...—— 确认 executor 和 image。
  • 结尾:ERROR: Job failed (system failure): ...—— 系统级失败,如权限、磁盘满、内存不足。

最典型的错误subprocess-local: windows job runner exited with exit code 0 before proving,意思是 Runner 进程在执行作业前就退出了。根本原因是:Windows Runner 服务以LocalSystem账户运行,但该账户无法加载用户环境变量(如PATH),导致git、python等命令找不到。解决方案:改用普通用户账户注册服务,并在config.toml的[runners.windows]段中添加environment = ["PATH=C:\\Program Files\\Git\\bin;C:\\Python39;"]。

5.4 第四步:模拟作业执行环境

当作业在 Runner 上失败,但在本地成功,说明环境不一致。最佳实践是:在 Runner 机器上,用完全相同的用户和环境,手动执行作业命令。

# 切换到 Runner 用户 sudo su - gitlab-runner # 进入构建目录(路径在日志中显示,如 /builds/group/project) cd /builds/group/project # 手动执行 .gitlab-ci.yml 中的 script 命令 git checkout main npm ci npm run build

这能暴露所有隐藏问题:缺少依赖(command not found)、权限不足(Permission denied)、路径错误(No such file or directory)。我曾用此法发现一个 bug:作业脚本里写cp dist/* ../output/,但dist/目录在npm run build后才生成,而../output/是相对路径,实际指向了 Runner 的根目录,导致文件被复制到/output/,污染了系统。

5.5 常见问题速查表

现象根本原因解决方案
No runners online with any of these tagsRunner offline,或 tags 不匹配sudo gitlab-runner status;检查config.toml中tags与 YAML 中tags是否完全一致
ERROR: Job failed (system failure): timeoutoutput_limit超限,或作业本身超时增大output_limit;在 YAML 中增加timeout: 3600(秒)
fatal: could not read Username for 'https://gitlab.example.com'Runner 无 Git 凭据在config.toml的[runners]段添加clone_url = "https://gitlab.example.com";或在作业中用git config --global url."https://token@gitlab.example.com".insteadOf "https://gitlab.example.com"
ERROR: Failed to load /etc/gitlab-runner/config.tomlTOML 语法错误用在线 TOML linter(如 toml-lint.com)校验;检查缩进、引号、括号是否匹配
WARNING: Job succeeded but the runner did not receive the status updateGitLab API 响应慢,Runner 心跳超时增大heartbeat_interval(默认 30 秒);优化 GitLab 服务器性能

实操心得:每次修改config.toml后,必须执行sudo gitlab-runner restart,而不是reload。reload只重载配置,不重启进程,某些参数(如concurrent)必须重启才生效。我曾因reload导致新配置“看似生效”,实则无效,浪费 3 小时排查。

6. 进阶实践:自托管 Runner 的安全加固与高可用设计

当 Runner 从单机玩具升级为企业级基础设施,安全与可用性就成了生死线。以下是我在线上环境强制推行的 5 条铁律。

6.1 执行器隔离:绝不混用 shell 与 docker

生产环境必须禁用shellexecutor。所有作业必须运行在docker或kubernetes容器中。为此,我在config.toml中彻底移除shell配置,并为每个 Runner 显式指定executor = "docker"。同时,在 GitLab 项目设置中,勾选Prevent runners from being used for projects that do not have matching tags,确保未打 tag 的作业无法被任意 Runner 执行。这堵死了“误调度”风险。

6.2 凭据管理:Token 与密钥的零明文存储

Runner 的registration_token和config.toml中的token,绝不能硬编码在配置文件里。我采用 HashiCorp Vault 集成方案:Runner 启动时,从 Vault 获取动态 Token,并注入到内存配置中。具体实现是编写一个 wrapper 脚本start-runner.sh:

#!/bin/bash # 从 Vault 获取 Token TOKEN=$(vault kv get -field=token secret/gitlab-runner) # 生成临时 config.toml cat > /tmp/config.toml <<EOF concurrent = 10 [[runners]] name = "prod-docker-runner" url = "https://gitlab.example.com/" token = "$TOKEN" executor = "docker" ... EOF # 启动 Runner gitlab-runner --config /tmp/config.toml run

这样,config.toml永远不落盘,Token 生命周期由 Vault 控制(如 1 小时自动过期)。

6.3 资源限制:cgroups 与 Docker 的双重保险

即使用了dockerexecutor,也要防止单个作业吃光宿主机资源。在config.toml的[runners.docker]段中,强制设置:

[runners.docker] memory = "2g" memory_swap = "4g" cpu_period = 100000 cpu_quota = 50000 oom_kill_disable = false

memory限制容器内存上限为 2GB,cpu_quota限制 CPU 时间片为 50%,oom_kill_disable = false允许 OOM Killer 在内存耗尽时杀死容器,而非拖垮整个宿主机。这比单纯依赖 Docker 的--memory参数更可靠,因为 Runner 会主动传递这些参数给docker run命令。

6.4 高可用:多 Runner + 自动注册的灾备方案

单点 Runner 是最大单点故障。我的方案是:部署 3 台相同配置的 Runner 机器,全部注册为prod-webtag。GitLab 会自动将作业轮询分发到这 3 台。但注册仍是手动的,扩容麻烦。于是,我用 Ansible 实现自动注册:当新服务器上线,Ansible Playbook 自动下载 Runner 二进制、创建用户、获取 Group Token、执行gitlab-runner register命令,并将生成的config.toml同步到所有节点。关键点是:register命令必须加上--non-interactive参数,并用echo预填充所有交互式输入:

echo -e "https://gitlab.example.com\nGROUP-TOKEN\nprod-web\ndocker\n" | sudo gitlab-runner register

6.5 审计与监控:日志集中化与指标采集

Runner 自身日志(journalctl)和作业日志(GitLab UI)必须分离。我用 Filebeat 将/var/log/gitlab-runner/下的日志发送到 ELK 栈,并在 Kibana 中创建看板,监控job success rate、average job duration、runner offline time。同时,用 Prometheus Exporter 抓取 Runner 的 metrics(需启用metrics_server):

[metrics] prometheus_address = "localhost:9252"

然后配置 Prometheus 抓取http://runner-host:9252/metrics,告警规则如:gitlab_runner_status{state="offline"} == 1触发短信告警。这套组合拳,让我能在故障发生前 5 分钟收到预警,而不是等开发同学喊“CI 又挂了”。

我在实际运维中发现,最有效的加固不是堆砌技术,而是建立一套“Runner 健康检查 SOP”:每天上午 10 点,自动运行一个健康检查作业,内容包括git clone、docker pull hello-world、df -h磁盘空间检测、free -h内存检测。结果自动发 Slack 群。连续 3 天失败,自动创建 Jira ticket。这套机制,让我们的 Runner SLA 稳定在 99.95%,远超公司要求的 99.5%。

返回列表