前言
公司线上报警群又开始报警了,磁盘空间超过80%,作为兼职运维工作的测试人员,慌的一批, 赶紧下手排查回复。
报警信息
信息源
报警信息如下,
通过报警信息,可以看到是 Prometheus 告警显示某台机器的磁盘使用率超过 80% ,接下来看看 监控命令是怎么写的
监控命令
登录 Prometheus 监控网站,可以看到监控命令如下:
(max by(device, instance) (node_filesystem_size_bytes{device=~"/dev/.*",fstype!=""}) - max by(device, instance) (node_filesystem_avail_bytes{device=~"/dev/.*",fstype!=""})) / max by(device, instance) (node_filesystem_size_bytes{device=~"/dev/.*",fstype!=""}) * 100 >= 80
这个 PromQL 查询用于 监控文件系统磁盘使用率,它会找出 磁盘使用率超过 80% 的挂载点。我们来逐步解析:
查询分解
计算已用磁盘空间
(max by(device, instance) (node_filesystem_size_bytes{device=~"/dev/.*",fstype!=""})
-
max by(device, instance) (node_filesystem_avail_bytes{device=~"/dev/.*",fstype!=""})
node_filesystem_size_bytes:文件系统总大小(字节)node_filesystem_avail_bytes:文件系统可用空间(字节)max by(device, instance):按device(磁盘设备名)和instance(主机实例)分组,取最大值(避免重复数据)device=~"/dev/.*":只匹配/dev/开头的设备(物理磁盘、分区等)fstype!="":排除未定义文件系统类型的记录- 结果 :得到每个磁盘设备的 已用空间 (总大小 - 可用空间)。
计算使用率百分比
(已用空间) / max by(device, instance) (node_filesystem_size_bytes{...}) * 100
- 用 已用空间 除以 总空间 ,再乘以 100,得到使用率百分比。
排查过程
了解了大背景后,我们正式进入排查。
1. 确认磁盘使用情况
登录目标机器,验证磁盘状态:
# 查看整体磁盘使用情况
df -h
执行后,输出结果如下:
Filesystem Size Used Avail Use% Mounted on
udev 3.8G 0 3.8G 0% /dev
tmpfs 768M 732K 767M 1% /run
/dev/vda1 148G 120G 28G 81% /
tmpfs 3.8G 0 3.8G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 3.8G 0 3.8G 0% /sys/fs/cgroup
tmpfs 768M 0 768M 0% /run/user/0
从输出结果可以看出,根目录 / 占用了 81% 的空间。
- 这里
/是挂载点,对应的设备是/dev/vda1,它们会被上述 PromQL 查询覆盖。
额外知识点:如果只想监控特定挂载点(如 / 或 /var)
需要在查询中显式指定 mountpoint 标签:
(
max by(device, instance, mountpoint) (node_filesystem_size_bytes{device=~"/dev/.*", mountpoint="/", fstype!=""})
-
max by(device, instance, mountpoint) (node_filesystem_avail_bytes{device=~"/dev/.*", mountpoint="/", fstype!=""})
)
/
max by(device, instance, mountpoint) (node_filesystem_size_bytes{device=~"/dev/.*", mountpoint="/", fstype!=""})
* 100 >= 80
接下来,查看根目录下的文件大小(按大小排序),执行如下命令:
du -sh /* 2>/dev/null | sort -h
这条命令用于快速分析 Linux 根目录 / 下各子目录的磁盘占用情况,并按排序输出。
du -sh /*# 计算根目录下所有一级子目录的总大小2>/dev/null# 屏蔽无权限访问的目录报错(如/proc,/sys)sort -h# 按大小排序结果
执行后,输出结果如下:
0 /bin
0 /dev
0 /lib
0 /lib32
0 /lib64
0 /libx32
0 /proc
0 /sbin
0 /sys
4.0K /mnt
4.0K /srv
12K /media
16K /lost+found
80K /home
92K /tmp
732K /run
5.4M /etc
145M /boot
2.7G /opt
11G /usr
21G /root
79G /var
从输出结果,可以看出/var 目录占用了 79G 空间,这是最大的目录。
额外知识点:
du 需要递归统计每个目录下所有文件大小,执行上面命令会有点慢,我们可以扫描可疑的大目录,命令如下
du -sh /var /usr /home /opt 2>/dev/null | sort -h
2. 定位大文件/目录
快速找出占用空间最多的目录:
第一步,我们已经确认 /var 是占用最多的目录,继续深入,查询 /var 目录下子目录大小
du -h --max-depth=1 /var 2>/dev/null | sort -h
- --max-depth=1:仅统计 /var 下的一级子目录(不递归子目录的子目录)
执行后,输出结果如下,
4.0K /var/local
4.0K /var/mail
4.0K /var/opt
12K /var/www
28K /var/spool
36K /var/tmp
1.8M /var/backups
98M /var/log
114M /var/cache
79G /var
79G /var/lib
从输出结果可以看出,/var/lib 目录占用了 79G 空间,这是最大的目录,继续深入查询 /var/lib 目录下子目录大小,执行命令
du -h --max-depth=1 /var/lib | sort -h
执行后,输出结果如下,
4.0K /var/lib/dbus
4.0K /var/lib/dhcp
4.0K /var/lib/git
4.0K /var/lib/lsb
4.0K /var/lib/man-db
4.0K /var/lib/misc
4.0K /var/lib/os-prober
4.0K /var/lib/plymouth
4.0K /var/lib/private
4.0K /var/lib/python
4.0K /var/lib/resolvconf
4.0K /var/lib/rpm
4.0K /var/lib/update-notifier
8.0K /var/lib/logrotate
8.0K /var/lib/sudo
8.0K /var/lib/ubuntu-release-upgrader
8.0K /var/lib/vim
12K /var/lib/AccountsService
12K /var/lib/chrony
12K /var/lib/initramfs-tools
12K /var/lib/locales
12K /var/lib/update-manager
16K /var/lib/grub
16K /var/lib/polkit-1
28K /var/lib/pam
40K /var/lib/php
132K /var/lib/nginx
260K /var/lib/ucf
296K /var/lib/cloud
424K /var/lib/systemd
444K /var/lib/containerd
608K /var/lib/usbutils
2.3M /var/lib/ubuntu-advantage
3.2M /var/lib/command-not-found
34M /var/lib/dpkg
293M /var/lib/apt
78G /var/lib/docker
79G /var/lib
好了,到这里可以确定/var/lib/docker 目录占用了 78G
3. 检查 Docker 磁盘占用
从上一步,我们知道/var/lib/docker 目录占用了比较多的空间,接下来就可以检查 Docker 磁盘占用,执行如下命令:
docker system df
执行后,输出结果如下:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 3 2 1.431GB 397.6MB (27%)
Containers 9 0 19.89kB 19.89kB (100%)
Local Volumes 15 0 83.74MB 83.74MB (100%)
Build Cache 1319 0 73.76GB 73.76GB
真相大白 :Docker 构建缓存是罪魁祸首!
通过输出结果,发现 Build Cache(构建缓存)独占 73.76GB ,且完全可回收!
4. 清理构建缓存
一键清理所有缓存
docker builder prune --all
--all:强制清理所有构建缓存(包括未被引用的层)。- 效果 :73.76GB 空间立即释放!
深度清理
也可以删除所有未使用的镜像、容器、卷、网络和缓存
docker system prune -a --volumes
注意 :此操作会删除所有未被使用的资源(谨慎操作)。
我这里主要是构建缓存造成的占用率很高,清除缓存之后,再次执行df -h, 发现空间已经恢复正常,关键输出结果如下,
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 148G 36G 106G 26% /
可以看到已经从开始的 81% ,变为了现在的 26%。
预防措施
限制构建缓存大小
编辑 Docker 配置文件 /etc/docker/daemon.json:
{
"builder": {
"gc": {
"enabled": true,
"defaultKeepStorage": "10GB"
}
}
}
重启 Docker:
sudo systemctl restart docker
设置定期清理任务
通过 Crontab 每周自动清理:
0 3 * * 0 docker builder prune --all -f && docker system prune -a -f --volumes
优化 Dockerfile
- 使用
.dockerignore排除非必要文件。 - 将高频变化的指令(如
RUN apt-get update)放在文件后部。
最后
经过层层排查,发现是 Docker 构建缓存占用了比较多的空间,导致磁盘空间占用率较高,清理构建缓存后,恢复正常, 磁盘告警终于消失了,报警群又恢复了往日的安静。
附录:常用命令速查表
| 命令 | 作用 |
|---|---|
docker system df | 查看 Docker 磁盘占用 |
docker build prune --all | 清除构建缓存 |
docker system prune -a --volumes | 清理所有未使用资源 |
du -h --max-depth=1 /var/lib | sort -h | 分析目录大小 |