最近发现有的仓库在运行CICD时报出error: RPC failed; curl 18 transfer closed with outstanding read data remaining
。而简单的项目(静态项目)则不会出现这个问题。
Curl 18错误是CURLE_PARTIAL_FILE
(via),引发这个问题的可能性有:
- Git clone期间磁盘空间不足问题
- Git浅克隆有关
- Git+HTTP之间的通信问题,分块传输编码有关(我是这个原因)
- Nginx代理缓冲问题
推荐按照这个顺序排查问题。
一、Git Clone期间磁盘空间不足
在CICD中,Git Clone由Runner管理。因cache目录磁盘空间不足引起这个情况时,可以通过重新部署runner到一个更大的分区来解决。
由于我使用Helm安装的runner,因此修改yaml
文件中RUNNER_CACHE_DIR
RUNNER_BUILDS_DIR
部分。
envVars:
value: /data/k8s/gitlab/cache/runner
- name: RUNNER_BUILDS_DIR
value: /data/k8s/gitlab/cache/builds
- name: DOCKER_DRIVER
其他安装方式请借鉴官网文档。
二、Git浅克隆有关(Shallow cloning)
当遇到很大的仓库(比如几个G)时,我们必须优化Gitlab。
默认情况下,Gitlab和Runner始终执行完整克隆。就相当于把所有Tag、Branch这些都Clone到Runner cache中,对于文件体积大仓库或者历史冗长的仓库会造成很大的性能浪费。
理想情况下,应该始终使用GIT_DEPTH
小于10的配置,这意味着Runner会执行浅克隆。
#gitlab-ci.yaml
variables:
GIT_DEPTH: 10
其实每个人都遇到过这个报错了,这不仅仅是Gitlab上会遇到的。在加入一个Team时,准备Clone一个不断迭代的项目也会遇到,太常见了。
值得一提的是,我使用Kubernetes运行Runner的环境是docker+machine,Gitlab默认采用GIT_STRATEGY: fetch
策略对此是有局限性的,可以设置为GIT_STRATEGY: none
策略,这会禁止Gitlab完成任何fetch和checkout命令,而原本的这些工作由你在gitlab-ci.yaml中做实现。
只有在很大的仓库时才需要考虑这么做。
三、Git+HTTP之间的通信问题
如果以上2个方式依然无法解决报错,那么通常情况下,可以认定是由于分块传输引起,而处理这一事务的是Nginx。
首先确保Nginx反代理配置不会产生多余的步骤,比如我一开始手残写成来proxy_pass https://:真实域名
,结果造成来多次连接……修正后,我的配置如下:
#仅供参考
upstream app_name {
server 127.0.0.1:8444;
}
server {
listen 443 ssl;
server_name git.app_name.com;
#SSL
...
client_max_body_size 0;
location / {
proxy_pass https://app_name;
}
}
另一个要注意的就是磁盘空间大小变化。简单粗暴一点就是看df -h
,可以用一个shell命令来观察:
while true; do df; sleep 1; done
通过观察CICD runner 克隆过程中,磁盘空间使用率的增加表明nginx正在进行某些操作。有可能是nginx响应缓冲proxy_buffering
(默认开启)引发的问题,可以根据自己的理解判断是否将其关闭。
启用缓冲后,nginx会尽快从代理服务器收到响应,并将其保存到proxy_buffer_size和proxy_buffers指令设置的缓冲区中。如果整个响应都无法容纳到内存中,则可以将一部分响应保存到磁盘上的临时文件中。写入临时文件由proxy_max_temp_file_size和proxy_temp_file_write_size指令控制。
via: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering
除此意外,还可以检查Gitlab Rails应用程序的日志(production.log,独角兽日志)和Gitlab Workhouse日志。借此来找到有针对性的问题根源。
# 进入容器
docker exec -ti gitlab /bin/bash
# 输出日志
sudo gitlab-ctl tail
# 查看某一个程序的日志
sudo gitlab-ctl tail gitlab-rails/api_json.log
本文至此结束,感谢大家的阅读,有描述不对的地方还望大家留言指出。
发表回复