过年期间发现年前给k8s里的一些服务配置了filebeat采集log以后,磁盘占用开始飞涨,半个月时间涨了几十个G。
df -h看,占用不正常的path都是overlay2相关的。但神奇的是,逐一检查这些path后,没有任何一个path的大小有异常,这就说不通了。
先按原因是overlay导致的来找找线索。
类似的磁盘占用高的情况,一种原因是因为docker container太多,导致老的container的数据没有及时清理的原因。这种的话用类似docker system prune清理一下就可以了。
另一种原因是docker log rotate设置的不合理导致的。如果是这种原因,可以检查/var/lib/docker/containers/*/*-json.log文件,应该是会很大。解决方法是修改/etc/docker/daemon.json文件的配置。
这两种情况的讨论具体可以看 https://forums.docker.com/t/some-way-to-clean-up-identify-contents-of-var-lib-docker-overlay/30604/29 。还有其他一些stackoverflow的讨论,大同小异。
然而我的情况这两种都不符合。既然文件小但是占用大,是不是有文件标记了删除但是没有正确释放,比如 https://www.jb51.net/article/186031.htm 。
就用lsof | grep -i deleted来看哪些文件被删除了但是没有释放。 根据结果,确实是filebeat导致log文件没有释放。
https://www.elastic.co/guide/en/beats/filebeat/current/faq-deleted-files-are-not-freed.html
根据filebeat的文档,filebeat会保持打开文件handler,即使文件被删除。就是说,正常情况下,filebeat打开文件直到文件结尾(EOF),如果在EOF前,该文件被删除,就会导致文件虽然被删除了,但是由于handler还在,该文件占用的磁盘空间没有正确释放。
对于k8s log(docker log),有关于log rotate的配置。因此如果log的量过大,而filebeat性能又不足的时候,就会导致filebeat还没有处理完log文件,该log文件就已经被docker清理掉的情况,这就会导致看起来通过du -sh查看log文件不大,但是df -h查看磁盘空间并没有被释放。
所以说根据filebeat的文档,保护性的解决方案是设置一个close_timeout,这样的话就保证以外情况下磁盘空间也可以正确释放,只是会导致在删除文件后,还没来得及处理的log会丢掉。当然根本的解决方案还是调整log的量到正确的范围。log量过大无非是安慰自己“出事有log”,实际用起来不一定有多少帮助。