关于du和df不一致的问题排查说明
1. 背景
客户反馈有3台服务器的df和du相差较大,df查出来的磁盘占用和du查出来文件占用相差了1T左右,需要咨询和查找对应的原因 (df -h /data 是1.6T; du -sh /data 是 677G;
2. 排查思路
2.1. du命令参数澄清
du -sh 命令会重复计算 overlayfs 占用的空间, 计算结果约为实际占用空间的2倍. 建议使用 du -shx 命令查看占用空间. 现场 du -shx /data 是345G, 和df结果差1.2T左右.
2.2.确认被删除的没有释放的文件句柄
登陆到对应的服务器,执行如下命令,以检查服务器中是否有文件已经被删除,但是依然有应用程序在使用,从而导致句柄没有释放。这种情况下,df统计到的数据是认为文件还没有被删除(句柄被程序占用),然后du则是统计实际的文件占用,从而差异。
#在先关的服务器上执行如下命令,寻找文件已经被删除,但是没有被释放句柄的文件
losf | grep delete > /tmp/lsof.txt
#统计这种情况下,被占用的文件总大小
cat /tmp/lsof.txt | awk '!a[$(NF-2)]++ {print $(NF-3)}'
#单位是字节(byte), 可以将输出结果粘贴到excel中计算加和.
说明:
- 造成lsof|grep deleted场景的原因有多种,一般是由于文件被上删除导致,但是删除的命令不一定是rm, 也可能是find xxx -delete, 或者其他脚本/函数。
- 一些不合理使用的应用程序(服务),内部进行日志滚动或者数据清理时,如果不注意句柄的回收,都有可能会导致该问题。
- 由于产生的原因较多,运维手段一般通过history命令过滤mv / rm / delete 等关键字,但是如果封装在脚本或者函数里面,则难以发现。
2.3. 检查隐藏文件
由于du命令进行分析是,无法统计隐藏文件,因此需要改进对应的命令,并检查是否包含隐藏文件
# 统计,包含隐藏文件
du -shx /data 是计算了隐藏文件的
# 统计,不包含隐藏文件
du -shx /data/*
# 经过使用命令,没有发现隐藏文件,因此隐藏文件也可以排除,还需要进一步定位原因
ls -lat /data
2.4. 检查磁盘挂载异常
2.4.1. 检查磁盘是否被重新挂载
通过如下命令,查看是否包含重复的挂载点,加以判断磁盘是否有重复挂载问题,通过截图来看,没有出现重复挂载的现象。
#查看磁盘挂载
lsblk
2.4.2. 检查磁盘挂载前是否将上面的文件清理
如果磁盘曾经被卸载/重新挂载,如果在重新挂载前,没有把磁盘的内容进行清理,直接挂载到文件系统中。则通过常规的ls也看不到(因为文件系统并不识别占用的文件,然后文件缺失在磁盘中占用里块)。
#新建临时目录
mkdir /tmpmount
#将/data 绑定到 /tmpmount,对应的文件(包括绑定前没有被清理的文件)会在/tmpmount中显示
mount --bind /data /tmpmount
# 分别统计/tmpmount对应的目录
df -Th /tmpmount
du -sh /tmpmount
# 统计占用较大的问题
while read p; do echo du -sh $p; du -sh ${p/\/data\//\/tmpmount\/}; done <<<"$(findmnt -l -o target | grep /data/)"
/tmpmount中的du和df差别依然很大,并通过ls /tmpmount查看没有发现特殊的文件或者目录。并且/tmpmount和/data占用空间相差不大, 说明不是重复挂载的原因.
综合如上2个分析,可以排除磁盘被异常挂载的场景
2.5. 检查被删除pod的diff文件,该种类型的操作不会被lsof -s|grep deleted统计到
我们在内部测试环境分析和复线,如果在服务器中cd到pod的overlay2目录,并删除diff路径下的文件,则不会统计到lsof -s|grep deleted中。从upper层(diff目录)删了以后,从merge层虽然ls不出来这个删掉的文件,但是直接ls这个文件还是可以显示出来,操作overlayfs的upper层是不合规的行为。从该场景分析,查找history中寻找可疑的命令
发现了可疑的命令 \find 7 -name 'ESData Barad Comm*.dat|xargs rm -f {},从而怀疑是曾经在服务器上进行了非标删除操作
3.1. 问题解决
3.1.1. remount相关容器的overlayfs
该操作不会影响pod内部程序的相关状态,操作相对安全
#获取对应的pod,并获取对应的docker信息,获取docker的overlay目录
docker inspect {dockerid}|grep -i workerdir
#获取mount信息
mount -l |grep {overlay}
#remount信息,xxx为overlay的路径(执行时间较长,如果文件正在被读写,可能会卡住)
mount -o remount xxxxx
3.2. 问题修复建议
如果发现类似文件, 优先 remount overlayfs, 如果remount失败, 建议重启对应pod或者服务器, 问题也能修复
du -sh 命令会重复计算 overlayfs 占用的空间, 计算结果约为实际占用空间的2倍. 建议使用 du -shx 命令查看占用空间