记一次Gitlab Runner服务器磁盘爆满问题
一早起来就发现有几个CI任务失败了,看docker错误日志是磁盘空间不足。我顿时就纳闷起来了。
因为虽然CI服务器磁盘空间只有500GB,还有大量的docker cache,但是我设置的计划任务每小时都会执行一次docker system prune
,不应该会爆满。而且两三天前刚使用docker volume prune
清理过一次volume,就更不应该了。
排查问题
再怎么觉得不科学,事实也已经存在了,只好去排查原因。
先登录到CI服务器上,查看磁盘使用量,发现为/var/lib/docker
单独设置的分区已经满了。这里还好是单独把它分了出来,不然能不能ssh登录还两说呢。
登录上之后,先手动执行docker system prune
,手动挤出来一点空间。
再使用docker system df
查看使用量:
TYPE | TOTAL | ACTIVE | SIZE | RECLAIMABLE |
---|---|---|---|---|
Images | 166 | 9 | 140.6GB | 133GB (94%) |
Containers | 45 | 7 | 290.1GB | 0B |
Local Volumes | 28 | 28 | 6.649GB | 0B (0%) |
Build Cache | 0 | 0 | 0B | 0B |
可得到一个类似上表的结果。(因最初的日志已不存在,此处数据是根据当时场景大致伪造的)。
可以看出磁盘主要是被容器使用掉了,RECLAIMABLE为0,是因为容器还在运行中。
检查容器磁盘使用
确定是容器在占用磁盘之后,使用docker ps -s
查看运行中的容器列表,输出表格中最后一列是其磁盘占用。分实际体积和Virtual体积两部分。
我理解实际体积为运行时产生数据的体积,Virtual体积是实体体积+基础镜像体积。
找到磁盘占用最大的一个镜像,使用docker exec -it <container id> sh
进入镜像的内部。再使用du -h -d 1 .
分析各子目录的磁盘占用。
确定原因
占用磁盘最大的容器,是一个runner。通过du
命令层层定位之后,最后确定到原因是在一个子工程目录内,其webpack
构建失败产生了core dump文件,以.core
结尾。因为core dump
文件体积很大,且产生了多个,所以占据了很大的体积。
恢复
要恢复磁盘也很简单,直接重启这个容器就可以了。
docker restart <container id>
防止问题再次发生
那如何防止问题再次发生呢?
我第一时间想到的,就是像限制 cpu 和 内存一样,限制容器可使用的磁盘空间。
查了下Docker新版本中真的支持这个选项:
Set storage driver options per container
然而不幸的是,我的CI服务器使用的overlay2存储引擎,搭建在ext4文件系统之上,而这个选项只有在使用搭建在 xfs 上的overlay2、btrfs等存储引擎的时候才支持。
那么暂时只能从程序角度来处理了。