一次磁盤占用率 100% 的排查記錄
在公眾號后臺回復: JGNB ,可獲取杰哥原創(chuàng)的 PDF 手冊。
大家好,我是杰哥。
最近遇到一個服務器的問題:磁盤滿了,占用率 100%~
這個問題太常見了,于是先來排查一波是哪些文件占用了大量磁盤。
一、排查磁盤占用率100%
1.1 查看磁盤使用的大致情況
第一個命令就是 df -h,來查看磁盤的占用情況。df 是 disk free 的縮寫,用于顯示目前在 Linux 系統(tǒng)上的文件系統(tǒng)磁盤的使用情況統(tǒng)計。
如下圖所示,可以看到磁盤占用率 100%。
-
第一列
Filesystem代表文件系統(tǒng)的名稱。 -
第二列
Size表示文件系統(tǒng)的大小。 -
第三列
Used表示已占用多大的磁盤空間。 -
第四列
Avail表示可用磁盤空間的大小。 -
第五列
Use%表示磁盤使用率多大,100% 表示磁盤占滿了。 -
第六列
Mounted On表示掛載在哪個目錄。
從上面的結果可以看到有個文件系統(tǒng)占用率為100%,為/dev/sda2,掛載的目錄為/,那我們就來看下這個目錄下都存放哪些大文件吧。
1.2 查看目錄下的大文件
使用 du 命令來顯示目錄或文件所占用的磁盤空間大小。
#?先進入到根目錄?`/`
cd?/
#?列出當前目錄或文件的總大小,并按倒敘排序
du?-sh?/*?|?sort?-nr
找到最大的目錄var,占用 100 多個 G。進入到這個目錄中,然后再次執(zhí)行 du 命令
du?-sh?/var/*?|?sort?-nr
這樣一級一級的找,就能找到占用空間最大的文件了。
最后發(fā)現(xiàn)是 Logstash 容器的日志文件占用太大,截圖如下。大家看到的占用 4.8G,這是我清理日志之后的大小,之前這個容器占用90多個 G。

1.3 Logstash 容器為什么占用磁盤這么大
為啥 Logstash 容器會有這么多日志???
我們看下這個日志里面的內容就知道了。使用 tail 命令查看文件的最后 100 行數據。
tail?-n?100?<容器?id?>-json.log
#?也可以通過?docker?logs?來查看日志
docker?logs??--tail=100?159
發(fā)現(xiàn)全都是 Logstash 解析日志時打印的信息。如下圖所示:

每次 Filebeat 采集日志后,傳輸給 Logstash 后,Logstash 都會打印一條解析后的日志。
而我們的后端服務會打印很多日志,傳輸給 Logstash 的日志會越來越多,Logstash 又會瘋狂的寫自己的解析日志,久而久之,磁盤就被占滿了。
問題原因找到了,那解決方案是什么呢?
二、容器日志清理方案
-
方案一:手動清理日志文件,可解燃眉之急,治標不治本。 -
方案二:腳本定期清理日志文件,缺點是日志文件全丟了,無法追溯。 -
方案三:限制所有容器的日志文件大小,治本,缺點是需要重新創(chuàng)建容器和啟動 docker 鏡像。
2.1 方案一:手動清理方案
cat?/dev/null?>?/var/lib/docker/containers/容器id/容器id-json.log
注意:這里沒有使用rm方式來刪除文件。使用rm -rf方式刪除日志后,通過df -h會發(fā)現(xiàn)磁盤空間并沒有釋放。原因是在Linux或者Unix系統(tǒng)中,通過rm -rf或者文件管理器刪除文件,將會從文件系統(tǒng)的目錄結構上解除鏈接(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
執(zhí)行腳本的命令
./clean_docker_log.sh
大家可以把執(zhí)行腳本的命令加到 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就寫第三個,如果第三個滿了,就清空第一個日志文件,重新寫第一個日志文件。如下圖所示:
寫了 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
推薦閱讀

