一次磁盘占用率 100% 的排查记录

共 3729字,需浏览 8分钟

 ·

2022-10-27 08:36

在公众号后台回复: JGNB ,可获取杰哥原创的 PDF 手册。

大家好,我是杰哥。

最近遇到一个服务器的问题:磁盘满了,占用率 100%~

这个问题太常见了,于是先来排查一波是哪些文件占用了大量磁盘。

一、排查磁盘占用率100%

1.1 查看磁盘使用的大致情况

第一个命令就是 df -h,来查看磁盘的占用情况。df 是 disk free 的缩写,用于显示目前在 Linux 系统上的文件系统磁盘的使用情况统计。

如下图所示,可以看到磁盘占用率 100%。

1d68ff4848eb2a2c1218095177a7e28d.webp

  • 第一列Filesystem代表文件系统的名称。

  • 第二列Size表示文件系统的大小。

  • 第三列Used表示已占用多大的磁盘空间。

  • 第四列Avail表示可用磁盘空间的大小。

  • 第五列Use%表示磁盘使用率多大,100% 表示磁盘占满了。

  • 第六列Mounted On表示挂载在哪个目录。

从上面的结果可以看到有个文件系统占用率为100%,为/dev/sda2,挂载的目录为/,那我们就来看下这个目录下都存放哪些大文件吧。

1.2 查看目录下的大文件

使用 du 命令来显示目录或文件所占用的磁盘空间大小。

        # 先进入到根目录 `/`
cd /
# 列出当前目录或文件的总大小,并按倒叙排序
du -sh /* | sort -nr

找到最大的目录var,占用 100 多个 G。进入到这个目录中,然后再次执行 du 命令

        du -sh /var/* | sort -nr

这样一级一级的找,就能找到占用空间最大的文件了。

最后发现是 Logstash 容器的日志文件占用太大,截图如下。大家看到的占用 4.8G,这是我清理日志之后的大小,之前这个容器占用90多个 G。

2b0c56aab321e1d4c04c684607eff32d.webp

1.3 Logstash 容器为什么占用磁盘这么大

为啥 Logstash 容器会有这么多日志???

我们看下这个日志里面的内容就知道了。使用 tail 命令查看文件的最后 100 行数据。

        tail -n 100 <容器 id >-json.log
# 也可以通过 docker logs 来查看日志
docker logs  --tail=100 159

发现全都是 Logstash 解析日志时打印的信息。如下图所示:

11c61c9c3d81e2d57ac17ecd9c31ea87.webp

每次 Filebeat 采集日志后,传输给 Logstash 后,Logstash 都会打印一条解析后的日志。

而我们的后端服务会打印很多日志,传输给 Logstash 的日志会越来越多,Logstash 又会疯狂的写自己的解析日志,久而久之,磁盘就被占满了。

问题原因找到了,那解决方案是什么呢?

二、容器日志清理方案

  • 方案一:手动清理日志文件,可解燃眉之急,治标不治本。

  • 方案二:脚本定期清理日志文件,缺点是日志文件全丢了,无法追溯。

  • 方案三:限制所有容器的日志文件大小,治本,缺点是需要重新创建容器和启动 docker 镜像。

2.1 方案一:手动清理方案

      cat /dev/null > /var/lib/docker/containers/容器id/容器id-json.log

注意:这里没有使用rm方式来删除文件。使用rm -rf方式删除日志后,通过df -h会发现磁盘空间并没有释放。原因是在Linux或者Unix系统中,通过rm -rf或者文件管理器删除文件,将会从文件系统的目录结构上解除链接(unlink)。如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用。正确姿势是cat /dev/null > *-json.log,当然你也可以通过rm -rf删除后重启docker。

2.2  方案二:脚本定期清理

提供一个清理脚本

      #!/bin/sh 

echo "======== start clean docker containers logs ========"  

logs=$(find /var/lib/docker/containers/ -name *-json.log)  

for log in $logs  
        do  
                echo "clean logs : $log"  
                cat /dev/null > $log  
        done  

echo "======== end clean docker containers logs ========"

给脚本添加权限

      chmod +x clean_docker_log.sh

执行脚本的命令

      ./clean_docker_log.sh

大家可以把执行脚本的命令加到 Linux 的定时任务中就可以了,这里不做展开。

下面要说的是我目前使用的方案。

2.3 方案三:限制 Docker 容器日志大小

新建 /etc/docker/daemon.json,若有就不用新建了。

      vim /etc/docker/daemon.json

配置内容如下:

      {
"log-driver":"json-file",
"log-opts": {"max-size":"500m""max-file":"3"}
}

max-size=500m,表示容器的日志文件大小上限是 500M, max-file=3,表示容器有三个日志,第一个满了 500M之后就写第二个,第二个满了 500M就写第三个,如果第三个满了,就清空第一个日志文件,重新写第一个日志文件。如下图所示:

261252b7c06201ebcd707252e8c9e5e8.webp写了 3 个日志文件,最大不超过 500M

改完之后需要重启 docker 守护进程

      systemctl daemon-reload
systemctl restart docker

另外这种方式只对新建的容器有效的,之前的容器不生效,所以我又把之前的 Logstash 容器删除了,然后重新启动了一个 Logstash 容器。

参考资料

https://www.cnblogs.com/gcgc/p/10521005.html
Linux df 命令 https://www.runoob.com/linux/linux-comm-df.html
Linux du 命令 https://www.runoob.com/linux/linux-comm-du.html

推荐阅读

一次服务器非法重启后导致的故障排查记录

Linux 性能分析工具汇总

Linux 系统时间老是不准怎么办?

Linux 网络抓包分析工具

几个必不可少的 Linux 运维脚本!

8039e99d5fadd38d2fda53841e80a37c.webp

浏览 60
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报