服务器启动docker报错cannot create temporary directory索引节点100%占用排查

问题

一周内测试服务器出现了3次问题。每次都是redis报错,RDB日志无法写入,设备上没有空间。测试服务器像往常一样更新项目代码并发布。测试服使用docker 去编译和发布项目的环境和项目本身。但是在准备运行 docker 进行项目更新时,却提示异常,内容如下:

$ docker-compose -f xxx.yml up -d --build
[249520] INTERNAL ERROR: cannot create temporary directory!

提示:INTERNAL ERROR: cannot create temporary directory! “不能创建临时的文件夹”?

不应该啊,什么都没动。这时就赶紧查看下服务器的磁盘使用情况

# 查看系统的磁盘容量使用情况
$ df -h
文件系统        容量  已用  可用 已用% 挂载点
...
/dev/nvme0n1p2  468G  128G  317G   29% /
overlay         468G  128G  317G   29% /data/docker/overlay2/xxxx/merged
overlay         468G  128G  317G   29% /data/docker/overlay2/xxxx/merged
...内容同上

PS: 我这里修改了docker目录到 /data/docker ,你们的可能在 /var/lib/docker 这个情自行替换命令中的目录地址。

发现磁盘还有很多的使用空间,那为什么不能创建临时文件呢?于是手动去创建一个空文件试试。结果也是失败。于是又想起来查看下索引节点的使用情况。

# 查看系统的索引节点使用情况
$ df -i
文件系统         Inodes  已用(I) 可用(I) 已用(I)% 挂载点
...
/dev/nvme0n1p2 31227904 31227904       0     100% /
overlay        31227904 31227904       0     100% /data/docker/overlay2/xxxx/merged
overlay        31227904 31227904       0     100% /data/docker/overlay2/xxxx/merged
...内容同上

好家伙,3千万个节点索引全部使用完毕。那么可以排除是其它服务的问题,这个问题就产生在docker的目录上。

这时上网搜,有的说得重启docker,转移目录。有的就是说清理对应文件就行了,一带而过。我觉得自行的随意删除文件,在不了解系统和docker 的情况下,很容易导致镜像或者docker出现问题。

我个人倾向于先保守,再激进。在不停用先有的容器下,先执行下docker自带的清理命令吧 docker system prune。它会帮我们将停止运行的容器,和关联的网络,和 悬空镜像等一些内容清理掉。

PS:docker system prune 还支持一些扩展参数,可以支持清理运行中的容器,所有的镜像等。这里我不想清理镜像,并且所有服务的容器我都没有停止,保证不会误删内容。

# 清理命令
$ docker system prune
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N] y

Deleted Containers:
70dac77db2c98ca3606f54b993f12660bde3cb6effd54a526b51696be64ec92c

Total reclaimed space: 0B

清理之后删除了一些无用的容器,回收空间没有。在查看索引的使用还是百分百。

鉴于docker中的镜像配置一直都没有改过,而且之前部署的一直没有出现问题。那么应该就是某个正在运行的容器出现异常,导致碎文件过多,把索引节点全部使用没了。

排查

基本能确定是docker 某个或某些容器产生的问题,与其一顿乱删,乱怀疑。不如就先找到是哪个目录下产生了那么多的文件。这里我使用了几个命令(来源自网友):

du -h /data/docker/overlay2 --max-depth=1 只查看 overlay2 下一层文件夹的空间占用大小

# 先看下docker 目录下这些镜像和容器产生的目录有没有异常大小的
$ sudo du -h /data/docker/overlay2 --max-depth=1
40K	/data/docker/overlay2/aaa-init
24K	/data/docker/overlay2/aaa
12M	/data/docker/overlay2/bbb
40K	/data/docker/overlay2/bbb-init
36K	/data/docker/overlay2/ccc
...

# 最大的不过几百兆。没有问题,都是在正常的使用范围内。

for i in /data/docker/overlay/2*; do echo $i; find $i | wc -l; done 去循环查找制定目录下的所有文件,统计文件个数返回。 如果需要root权限,可以向下面的写法。

$ sudo -- bash -c 'for i in /data/docker/overlay2/*; do echo $i; find $i | wc -l; done'
/data/docker/overlay2/xxx
9
/data/docker/overlay2/aaa
60499422
/data/docker/overlay2/aaa-init
18
...

$ sudo -- bash -c 'for i in /data/docker/overlay2/aaa/*; do echo $i; find $i | wc -l; done'
./diff
30235375
./link
1
./lower
1
./merged
30264042
./work
2

然后我们就发现了,目录是 aaa 的这个文件夹下,文件居然有6千万个!进入后再次统计,嗯就是这个目录没跑了。

那么现在我们的根源目录找到了,现在只需要知道它是那个容器产生的就行了。docker 高版本以后,这个挂载的目录名称就和容器的id区分开了,所以这两个不能直接进行关联。

于是我又找到了一个命令。

# 查看 overlay2/ 下文件夹对应的容器信息
$ docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.Id}}, {{.Name}}, {{.GraphDriver.Data.WorkDir}}' | grep 这里放目录的名称aaa
68640, 容器的ID, /abcd, /data/docker/overlay2/aaa/work

这样我们就找到对应的容器id,然后可以先stop这个容器。然后执行 docker system prune 命令,帮我们去清理这个容器的目录。因为文件很多,所以这个命令执行会需要很长的时间,耐心等待即可。它不会死机的。(我执行了将近一个小时。。。)

之后再去看 df -i 就发现索引节点,全部都释放出来了。服务器可以正常的创建文件或者文件夹了。

最后。我们这里是某个程序出现错误,导致一直在重试去创建文件。。然后就把索引节点使用光了。。。

参考文章

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值