公司使用的openstack的备份服务组件karbor,要查询所使用的备份nas磁盘使用率的需求,根据以前的查询语句,很快写出如下的prom sql
100-topk(1,node_filesystem_free{device=~":/.*"}*100/node_filesystem_size{device=~":/.*"})
不久后,同事过来说给出的使用率不严谨,和在系统上通过df -h的命令不一样,分别是prom:10%,df结果是11%。嘴上说着差异不大不用管,身体却很实诚,马上去主机上通过df -h查看了使用率
:/var/lib/docker/nfs 147G 15G 125G 11% /var/lib/docker/volumes/volume-nfs/_data
通过prom sql查询出来的结果
{component="node",device=":/var/lib/docker/nfs",fstype="nfs",hostname="xxx",instance="xxx",instance_ip="xxx",job="job:monitor",mountpoint="/var/lib/docker/volumes/volume-nfs/_data",node_type="controller",system="QHC-CORE"} 9.978290691634598
确实有点差异,同事说df计算的使用率更严谨,但具体怎么算的也不清楚,同时看到df -h的结果size并不等于used+avail之和,于是就在网上查询相关的文章,看到了这篇文章谁吃了你的硬盘空间?(1) 诡异的df算法
主要的原因就是每个分区有一个给管理员的预留空间,保证即使普通用户写满其空间,管理员还可以进行操作,普通用户的可使用空间是总空间减去预留空间,该文章并给出了具体的预留空间计算规则
reserved = fsu_blocksize * (fsu_bfree - fsu_bavail)
然后看了node_exporter的源码,核心的代码在github.com/prometheus/node_exporter/collector/filesystem_linux.go的101行
stats = append(stats, filesystemStats{
labels: labels,
size: float64(buf.Blocks) * float64(buf.Bsize),
free: float64(buf.Bfree) * float64(buf.Bsize),
avail: float64(buf.Bavail) * float64(buf.Bsize),
files: float64(buf.Files),
filesFree: float64(buf.Ffree),
ro: ro,
})
根据前面的算法,其实主要是将分母由磁盘总空间修改为磁盘总空间减去预留空间,写出如下prom sql
100-topk(1,node_filesystem_avail{device=~":/.*"}*100/(node_filesystem_size{device=~":/.*"}-(node_filesystem_free{device=~":/.*"}-node_filesystem_avail{device=~":/.*"})))
计算结果是10.5,基本与df -h四舍五入后的结果。
{component="node",device=":/var/lib/docker/nfs",fstype="nfs",hostname="node4",instance="xxxx",instance_ip="xxxx",job="job:monitor",mountpoint="/var/lib/docker/volumes/volume-nfs/_data",node_type="controller",system="QHC-CORE"} 10.51730188811679