磁盘说 “我还行”,Inode 已躺平 —— GitLab 被小文件 “挤爆” 的荒诞排查记
文章共1578个词,5958个字符,阅读大约需8分钟
背景
今天一大早遇到一个棘手的问题,团队有同事那边反馈说:gitlab报错500了,无法正常提交代码。
现象
1.登录机器查看,刚打了一部分命令,按tab想自动补全一下,但是出现提示:
cd /op<按下Tab键>-bash: 无法为立即文档创建临时文件: 设备上没有空间
2.敲命令也感觉卡卡的。
3.gitlab报错500了,其他服务也有部分不太正常。
查找问题
初步怀疑是存储满了,于是进行df -h查看:
[root@test docker]# df -h
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 32G 0 32G 0% /dev
tmpfs 32G 0 32G 0% /dev/shm
tmpfs 32G 26M 32G 1% /run
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/vda1 493G 349G 123G 74% /
/dev/vdb1 20G 45M 19G 1% /docker_data
···
overlay 493G 349G 123G 74% /var/lib/docker/overlay2/d3a798b987313c5fb09135596557a148b462050884cebeed5433c8003f64a213/merged
···
tmpfs 6.3G 0 6.3G 0% /run/user/0
还有123g可用呢,存储也没满。为什么磁盘没满,服务却无法正常访问了?
尝试解决
先简单清理了一下/var/log/目录下的文件,重启了一下gitlab,发现正常了。但是过了一会儿,又开始报500,看来没有解决根本问题。
探寻答案
经过翻阅资料才知道,一般有这几种情况:
- 1.磁盘空间耗尽:文件系统的数据块已用完
- 2.inode耗尽:文件系统的元数据节点已用完(即使磁盘还有空间)
- 3.临时文件目录问题:/tmp目录权限或空间问题
- 4.Docker资源占用:容器或镜像占用大量空间
有的网友说是/var/spool/postfix/maildrop/目录,被邮件临时文件占满;
还有网友说是docker的overlay目录占满。经过查看,发现这两种情况都并非当前场景。
经过一番仔细排查,发现是Inode耗尽。
执行df -i查看Inode占用,不看不知道,一看吓一跳😮:
[root@test ~]# df -i
文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点
devtmpfs 8223273 382 8222891 1% /dev
tmpfs 8225887 1 8225886 1% /dev/shm
tmpfs 8225887 744 8225143 1% /run
tmpfs 8225887 16 8225871 1% /sys/fs/cgroup
/dev/vda1 32768000 32768000 0 100% /
/dev/vdb1 1310720 13 1310707 1% /docker_data
···
overlay 32768000 32768000 0 100%
···
tmpfs 8225887 1 8225886 1% /run/user/0
抓出目录元凶
遍历并统计所在路径下各个文件夹的文件数,可以先从根目录开始:
# /var/lib
[root@test lib]# for i in *; do echo $i; find $i |wc -l; done
···
containerd
32
containers
2
jenkins
32415654
···
yum
11229
jenkins居然占用了这么多!!!
突然想起来:之前因为系统比较老旧centos7.9.2009,东西也较多,不便清理。
但是打包需要很新的pnpm-10。
于是打包采用了折中的方案,拉取代码之后,使用docker挂载的方式进行编译,进而导致了编译后没有及时清理,项目越积越多的情况。
初步清理之后的数据🧹:
[root@test ~]# df -i
文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点
devtmpfs 8223273 382 8222891 1% /dev
tmpfs 8225887 2 8225885 1% /dev/shm
tmpfs 8225887 815 8225072 1% /run
tmpfs 8225887 16 8225871 1% /sys/fs/cgroup
/dev/vda1 32768000 16013963 16754037 49% /
/dev/vdb1 1310720 13 1310707 1% /docker_data
···
overlay 32768000 16013963 16754037 49%
/var/lib/docker/overlay2/7ab1b8ef92018e8d7d32e7fba513e12099ca570d5e9fcbbd30728e97f58e5228/merged
···
tmpfs 8225887 1 8225886 1% /run/user/0
深度清理之后
清理掉了所有pnpm产生的过期node_modules文件,以及项目历史构建信息
[root@test ~]# df -i
文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点
devtmpfs 8223273 382 8222891 1% /dev
tmpfs 8225887 2 8225885 1% /dev/shm
tmpfs 8225887 815 8225072 1% /run
tmpfs 8225887 16 8225871 1% /sys/fs/cgroup
/dev/vda1 32768000 3569900 29198100 11% /
/dev/vdb1 1310720 13 1310707 1% /docker_data
···
overlay 32768000 3569900 29198100 11%
/var/lib/docker/overlay2/1b9e9fd8627510c9b164cb7ae850b09c7013fcd0c9c8f74fea67e1b27d00af76/merged
···
tmpfs 8225887 1 8225886 1% /run/user/0
反应飞快,gitlab和其他服务也正常了!🥳
解决方案与优化建议
既然问题已经解决,为了防止未来再次发生此类“隐形”故障,建议从以下两个维度进行加固:
A. 自动化清理策略 (针对 Jenkins)
既然已知是 Jenkins 构建产物导致,我们可以在流程上做限制:
- 构建后清理:在 Jenkins Job 的配置中,务必勾选 "Delete workspace before build starts"(构建前删除工作区)或使用
ws.clean()指令。 - 自动清理插件:安装 Workspace Cleanup Plugin 或 Build Discarder Plugin,设置保留最近 N 次构建记录,自动删除旧的构建目录。
- Docker 优化:如果使用 Docker 构建,确保使用
--rm参数,或者定期执行docker system prune清理悬空镜像和容器(虽然本次主要是宿主机上的 Jenkins 目录问题,但 Docker 也会产生大量小文件)。
B. 监控告警升级
传统的磁盘监控(监控磁盘使用率)无法发现此问题,我们可以增加 Inode 监控:
- 监控指标:增加对
df -i结果的监控,重点关注 IUse%。 - 告警阈值:建议在 Inode 使用率达到 80%-85% 时就发出预警,因为清理海量小文件通常比清理大文件更耗时。
- 巡检脚本:可以编写一个简单的脚本,定期扫描服务器上文件数量最多的前 10 个目录,防患于未然。
jenkins中产生的构建产物没有及时清理导致的,构建内容过多,其中QA和frontend产生的node_modules小文件占比非常多,导致了这次3241万个Inode被占满,影响到了gitlab和其他服务的正常运行。
目前已加入打包📦完毕自动清理,完美避免了此类情况发生,同时做好inode和磁盘的监控,做到防患于未然。
最后总结
这次故障是一个典型的Inode 耗尽案例。它提醒我们:
运维监控不能只看容量:Inode、进程数、端口数等资源同样重要。
前端工程化带来的副作用:现代前端开发(Node.js, npm/pnpm)虽然提高了开发效率,但也给服务器带来了巨大的文件系统压力。
文档信息
- 作者: 运维技术团队 - 辣个男人Devin
- 发布日期: 2026年03月19日
- 适用系统: Linux
- 参考链接:
https://cloud.tencent.com/developer/article/1990129