你好,我是悟空。
最近遇到一個服務器的問題:磁盤滿了,佔用率 100%~
這個問題太常見了,於是先來排查一波是哪些文件佔用了大量磁盤。
一、排查磁盤佔用率100%
1.1 查看磁盤使用的大致情況
第一個命令就是 df -h,來查看磁盤的佔用情況。df 是 disk free 的縮寫,用於顯示目前在 Linux 系統上的文件系統磁盤的使用情況統計。
如下圖所示,可以看到磁盤佔用率 100%。
第一列 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。
1.3 Logstash 容器爲什麼佔用磁盤這麼大
爲啥 Logstash 容器會有這麼多日誌???
我們看下這個日誌裏面的內容就知道了。使用 tail 命令查看文件的最後 100 行數據。
tail -n 100 <容器 id>-json.log
# 也可以通過 docker logs 來查看日誌
docker logs --tail=100 159
發現全都是 Logstash 解析日誌時打印的信息。如下圖所示:
每次 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就寫第三個,如果第三個滿了,就清空第一個日誌文件,重新寫第一個日誌文件。如下圖所示:
!](https://img-blog.csdnimg.cn/img_convert/92874089e5414db50649cd6065a4c0c4.png)
改完之後需要重啓 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
關於我
8 年互聯網開發經驗,擅長微服務、分佈式、架構設計。目前在一家大型上市公司從事基礎架構和性能優化工作。
InfoQ 簽約作者、藍橋簽約作者、阿里雲專家博主、51CTO 紅人。
我的所有文章都彙總到這裏了 http://www.passjava.cn</容器>