1. 问题背景:当Runner突然"罢工"时
作为持续集成流水线的核心中的超级核心,GitLab Runner在代码构建、测试、部署等场景中承担着核心任务。但在实际使用中(尤其是在资源受限的服务器上),我们经常会遇到这样的场景:
- 自动化构建突然中断
- 高并发任务执行时多个Runner集体宕机
- 长时间运行的测试任务神秘消失
本文将以Shell执行器的Linux环境为例(技术栈:GitLab Community Edition 15.6 + Runner 15.6.0),演示如何像侦探一样排查Runner异常停止的"犯罪现场"。
2. 现场勘查:三招定位停止原因
2.1 查看Runner服务日志
# 查看实时日志(systemd系统)
$ journalctl -u gitlab-runner.service -f
# 典型错误日志示例:
# Jul 15 10:23:45 CI-Server gitlab-runner[14257]: ERROR: Failed to process runner...
# Jul 15 10:23:45 CI-Server gitlab-runner[14257]: FATAL: OOM error: cannot create new OS thread
关键点:关注ERROR
和FATAL
级别的日志,内存不足(OOM)、端口冲突、权限错误是常见元凶
2.2 检查作业日志残留
# 进入Runner工作目录
$ cd /home/gitlab-runner/builds/
# 查找未完成的作业目录
$ find . -name ".job.log" -mtime -1 | xargs grep "ERROR: Job failed"
示例输出:
./abc1234/.job.log:ERROR: Job failed: exit status 137
解密:exit code 137通常表示进程被强制终止(128+9=SIGKILL)
2.3 系统资源监控取证
# 查看历史内存使用(需安装sysstat)
$ sar -r -f /var/log/sysstat/sa15
# 检查进程被杀记录
$ grep -i 'killed process' /var/log/messages
典型证据:
Jul 15 10:23:45 CI-Server kernel: Out of memory: Killed process 14257 (gitlab-runner)
3. 起死回生:三种恢复方案实战
3.1 快速重启方案(治标)
# 优雅重启服务(保留正在执行的作业)
$ gitlab-runner restart
# 强制重启(立即终止所有进程)
$ systemctl stop gitlab-runner
$ pkill -9 gitlab-runner # 清理残留进程
$ systemctl start gitlab-runner
适用场景:临时性资源问题,需要快速恢复服务
3.2 进程级深度清理(治本)
# 查找僵尸进程
$ ps aux | grep 'defunct' | grep -v grep
# 清理示例(假设发现残留的bash进程)
$ pstree -p | grep gitlab-runner
# |-gitlab-runner(14257)-+-sh(14300)-+-git(14301)
# | |-bash(14302)
$ kill -9 14302 # 终止卡死的子进程
$ gitlab-runner verify # 验证服务状态
特殊技巧:使用lsof
查找被占用的文件描述符:
$ lsof -p $(pidof gitlab-runner) | grep deleted
3.3 配置调优方案(预防)
修改/etc/gitlab-runner/config.toml
:
concurrent = 4 # 根据CPU核心数调整(建议物理核心数×2)
[[runners]]
executor = "shell"
[runners.custom_build_dir]
[runners.cache]
MaxUploadedArchiveSize = 0 # 禁用缓存(当磁盘满时)
[runners.shell]
memory_limit = 4096 # 限制单个作业内存(单位MB)
参数解析:
concurrent
:控制同时运行的作业数memory_limit
:防止单个作业耗尽内存MaxUploadedArchiveSize
:解决磁盘写满导致失败
4. 应用场景与关联技术
4.1 典型故障场景
场景特征 | 推荐解决方案 | 相关指标阈值 |
---|---|---|
周期性OOM错误 | 内存限制+作业分流 | 内存使用>90% |
SSH连接超时 | 心跳检测+超时设置 | timeout=3600s |
磁盘空间不足 | 缓存清理+日志轮转 | inode使用>80% |
4.2 关联技术:资源监控集成
# 实时监控脚本示例(保存为monitor_runner.sh)
#!/bin/bash
ALERT_THRESHOLD=90
while true; do
MEM_USAGE=$(free | awk '/Mem/{print $3/$2*100}')
if (( $(echo "$MEM_USAGE > $ALERT_THRESHOLD" | bc -l) )); then
echo "$(date) - 内存使用率过高: ${MEM_USAGE}%" >> /var/log/runner_monitor.log
gitlab-runner stop --all
fi
sleep 300
done
5. 技术方案对比分析
5.1 方案优缺点
方案类型 | 优点 | 缺点 | 适用阶段 |
---|---|---|---|
快速重启 | 恢复速度快(<1min) | 可能丢失作业上下文 | 生产环境紧急处理 |
进程清理 | 精准定位问题点 | 需要专业知识 | 开发测试环境 |
配置调优 | 预防性效果显著 | 需要性能测试 | 长期运行维护 |
5.2 性能测试数据参考
在4核8G服务器上的压力测试结果:
并发数 | 平均响应时间 | 失败率
---------------------------------
2 | 23s | 0%
4 | 41s | 5%
8 | TIMEOUT | 100%
结论:建议并发数设置为CPU逻辑核心数的1.5-2倍
6. 必须知道的注意事项
- 日志文件轮转:默认日志可能撑爆磁盘
# 配置logrotate(/etc/logrotate.d/gitlab-runner)
/home/gitlab-runner/.gitlab-runner/*.log {
daily
rotate 7
missingok
compress
}
- 权限安全陷阱
# 错误示范:
$ chmod 777 /home/gitlab-runner # 可能引发提权漏洞
# 正确做法:
$ sudo -u gitlab-runner gitlab-runner install
- 跨版本升级风险
# 正确的升级姿势:
$ gitlab-runner stop
$ curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
$ apt-get install gitlab-runner=15.6.0
7. 事后的总结
通过本文的"现场勘查三部曲"和"复活三式",我们已经建立了从故障发现到恢复的完整链路。但真正的运维高手还需要:
- 建立预警机制:配置Prometheus+Alertmanager监控
- 实施混沌工程:定期模拟故障场景
- 版本控制:严格测试Runner升级版本
未来的持续集成系统正在向弹性伸缩方向发展,结合Kubernetes的自动扩缩容能力,可以期待Runner集群的智能自愈功能。但在那之前,掌握这些底层排查技能仍然是每个DevOps工程师的必修课。
记住:每个神秘的Runner崩溃背后,都有日志留下的线索。愿你的持续集成流水线永远畅通无阻!