Docker:Docker删除upper目录下文件再创建,其与merged目录文件iNode不一致(验证中……)
问题描述
磁盘空间不足,经排查发现是docker下的overlay目录下一个服务的容器层(存在于merged和upper)的日志文件占用空间过大。
操作
1、尝试docker的清理磁盘命令
一开始使用命令docker system prune
清理磁盘,该命令用于删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像)。
日志文件没有被清除。
2、尝试直接删除merged目录下文件
因为该目录为读写层,所以打算直接删除该文件,首先尝试直接删除merged目录中的日志文件,发现删除无效,依旧存在。
merged为联合挂载容器层和镜像层产生的容器视图,所以修改该目录,docker容器内部也会修改。
3、尝试删除upper目录下文件
第二次尝试删除upper目录中的日志文件,
是这样考虑的,由于merged目录是upper和lower的联合展示,那么删除upper下的文件,merged也会对应删除(反之亦然)。
却发现upper下文件删除了,但是merged还有。再次删除merged下的日志文件,报错
rm: cannot remove ‘wrapper.log’: Stale file handle
。
过时的文件句柄,说明此时inode指向的block是空的或者存在问题。
4、排查中看到有说与文件系统有关
查询过程中,有看到,CentOS7默认文件系统xfs,与docker的overlay/overlay2存储驱动不匹配,导致容器内删除文件无效。
①重新格式化xfs文件系统,修改参数ftype=1、
②可将centos文件系统格式化为ext4、
③修改docker存储驱动为老的devicemapper、
④宿主机删除(我们的操作就是宿主机删除)(overlay/overlay2的文件系统是OverlayFS,为上层文件系统,主流底层文件系统为ext4和xfs)
网上的解决方案,使用fsck -a <设备号>
命令,自动检查修复文件系统。(尽量别用,对于公司的生产环境影响过大),尝试之后并没有效果。
5、临时解决,重新创建容器
最后我们的解决方案是删除了容器,重新创建的容器。
6、探究问题原因
问题根本原因是什么?
之后又尝试直接删除merged目录下的文件,此时未删除upper目录下文件,发现没有问题,能够删除,不过一会又会创建出来,文件inode值没变,只是权限变了。
复现操作删除upper下文件,发现merged下日志文件依旧存在,且进行删除操作还是报错过时的文件句柄!!
继续探究
尝试硬链接merged下的日志文件到upper。报错 Invalid cross-device link!!
跨文件系统了。
疑惑
后来又看到网上的一些解决方案,联想到自己目前的问题
我要删除的是日志文件,在我进行删除操作时,它对应的docker容器是开启的,也就是说日志文件正在被写入。
rm操作时将该文件从文件结构上解除连接,但是存储空间依旧存在。
外部宿主机merged删除日志文件后,内部容器又将日志文件恢复了,此时的外部文件是容器内创建的,也就是overlay文件驱动。
但是我的宿主机文件系统是xfs,此时造成了文件系统不一致?
排查是否设置ftype,使用命令xfs_info /
,ftype=1 是开启的。说明宿主机可以适配overlayFS文件系统的文件。
底层文件系统是内核的一部分。
继续测试
(验证一下上述疑惑,手动创建文件,发现同样存在该问题,那么就不是上述疑惑了。)
目前有点懵,继续测试在docker容器中创建文件,外部删除会不会有这个情况?
测试中发现一件事情,如果容器创建时有挂载外部卷,那么merged里的文件和容器内的就不是一个inode了,容器内文件和挂载卷文件是一个inode。(merged没有了,出现在宿主机挂载位置)
还会有疑惑Docker的写时复制的影响?
测试容器内创建文件,upper删除造成的影响
容器内创建test文件(inode:1319259),宿主机upper目录删除对应出现的test文件,发现并无影响,对应的merged和容器内都会删除。
再尝试容器创建test文件,命令执行完没有反应?cat test,输出为空,也就是说看不到test文件,但是容器内还存在!!
尝试在upper创建test文件,创建成功但是inode变了(inode:1320457),再去看容器和merged,也出现的test文件,但是inode还是之前那个inode(inode:1319259)
疑惑,文件系统的问题?
然后使用df -Th
查看文件系统类型,发现merged文件系统是overlay,upper是xfs,难道说还是因为类型匹配有问题?
又测试了几个文件系统分别为overlay与xfs的容器,发现都有这个问题!!
是ftype=1这个参数 还是不能很好的适配overlay和xfs吗?
测试ext4(extfs)与overlay2 不存在该问题
换几台服务器,验证一下,是不是和文件系统有关
经测试宿主机文件系统为xfs,docker文件驱动为overlay2,也是存在这个问题。
同样使用df -Th 查看文件系统类型,upper目录是xfs,merged是overlay。
测试结果
测试1
容器内创建文件,
1、merged和容器内删除无影响,
2、upper删除会导致 merged和容器内无法创建,
且upper再次创建同名文件,upper中inode变了(也是新的文件,文件内容是空的),但是merged和容器内还是之前的inode(文件内容也还是之前的),
删除merged下该文件报错无效的文件句柄。
测试2
upper中创建文件,发现存在上述同样的问题。
时隔一段时间后的测试
后来测试一个容器发现没有这个问题,同样的机器为什么会有不同的表现?
创建容器时,如果设置 --privileged=true 的容器删除就没有影响,否则会出现上述问题。这个问题同样存在于 ext4/overlay 的服务器中。
但是事情变得越发奇怪了,
重启容器之后,在 ext4/overlay 的服务器能够删除 merged 目录下的文件。但是 xfs/overlay 还是报错无效的文件句柄。
ext4 如果是通过 -v 挂载出来的,什么问题都没有,因为df -Th都是 ext4。
时隔两年后的评价
如果你看到了这里,我需要说一句 I'm Sorry,时隔快两年,我也看不懂自己写的这是什么玩意,只是依稀还有一些印象。
对于这个问题,现在我有几个困惑点。
- 是否可以stop容器,然后删除。(不能,停止之后删除再启动,只是容器内和upper一致了,但是merged还是旧文件的inode,而且内容还在)
- merged层应该是一种展示层吧,真正的数据在lower和upper。那么在容器运行时,是否会有缓存现象导致数据一直被持有,所以upper删除了,但是容器内和merged还在占用(容器停止后merged下的文件还存在)
- 补充:甚至重启Docker服务,merged下的文件都还在。。。。。