问题现象
之前已经做好了gitlab-runner自动化构建公司首页,正常用了几天都没有问题。但是某天上午收到同事反馈首页内容没有更新。登录gitlab查看CI/CD状态,确实是失败状态。
排查过程
查看到日志错误:
Running with gitlab-runner 14.10.1 (f761588f)
on auto_compile_www ksmdDdXw
Preparing the "shell" executor
00:00
Using Shell executor...
Preparing environment
00:00
Running on iZwz9fzztquqeuad3z8pccZ...
Getting source from Git repository
08:58
Fetching changes...
Reinitialized existing Git repository in /home/gitlab-runner/builds/ksmdDdXw/0/product/www/.git/
fatal: unable to access 'https://gitlab-ci-token:[MASKED]@gitlab.xxx.com/product/www.git/': The requested URL returned error: 504
Cleaning up project directory and file based variables
00:04
ERROR: Job failed: exit status 1
粗略一看是504超时了。仔细分析内容的话可以知道每个时间的上面都是不同阶段。
- 第一段使用shell执行器符合预期
- 第二段从仓库获取源符合预期
- 第三段拉取修改,可以看到路径不是我们脚本内定义的路径,但查看以前成功的日志都是有此阶段,可以看到此阶段是失败了。
- 着重研究第三阶段失败的原因
分析:
- 既然是第三阶段最后抛异常,给我的感觉是客户端runner应该没有问题,至少客户端尝试去拉取代码了。可以怀疑是脚本不对,或者是脚本拉取代码有异常。但尝试手动执行调用的shell脚本都正常。
- 手动执行脚本没有问题,这也不能完全断定调用没有问题。于是修改脚本内容为echo,再测试CI/CD发现仍然是上面报错,没有脚本内容。可以得出结论并没有走到shell脚本步骤,前面拉取代码都是预处理。
- 接下来可以怀疑是runner的问题,在客户端执行了gitlab-runner verify,反馈正常,在gitlab查看状态正常。最后重装客户端runner,也依旧报错,至此可以完全排除是客户端runner问题。
- 再次分析报错内容,根据流程我们可以知道,虽然没有执行到自定义的脚本,但是客户端明显是在runner的流程下尝试拉取代码的,只是最后超时了。重心需要放到超时上,再观察超时地址是https的地址,我突然想到,也许runner的预处理阶段根本不是跟我们脚本一样使用的ssh协议,而是使用CI的token验证,用https协议获取的代码,那么问题极大可能是https协议问题,于是做了如下验证:
[root@iZwz9fzztquqeuad3z8pccZ 123]# time git pull https://gitlab.xxx.com/product/www.git Username for 'https://gitlab.xxx.com': yuc Password for 'https://yuc@gitlab.xxx.com':
我们通过http协议拉取代码,再配合gitlab的product_json.log日志,可以看到日志中有验证用户通过,但是就没有后续了,一直等待ng返回超时,至此基本上是可以断定https协议无法正常获取代码,但是runner又需要在我们脚本之前使用https协议获取一次代码。既然问题定位了,那么可有两种解决方案:一是解决gitlab当前https协议异常问题,二是解决runner预处理阶段使用ssh协议/或者干脆不拉取代码。
- 尝试了上面两种方案都失败了。git pull https协议卡住完全找不到有用的日志,或者说日志太多了不知道该怎么去排查。runner预处理阶段也无法使用ssh协议,或者不拉取代码。
解决
既然是突然无法正常使用https协议,那么就重启gitlab吧。也算是解决问题了。