日志空间管理实际应用

引出

近日在服务器空间不足的报警经常出现,经过排除系日志占用,分析后发现使用Docker容器的服务器空间占用是日志占用的2倍,观察系统空间

 df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       50G  47.4G   2.5G   95% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
udev            988M   12K  988M   1% /dev
tmpfs           201M  476K  200M   1% /run
none            5.0M     0  5.0M   0% /run/lock
none           1001M  164K 1001M   1% /run/shm
none            100M     0  100M   0% /run/user
/dev/xvdf1      493G  4.6G  463G   1% /Sioeye

可见整个xvda1卷的空间已不足,马上满了 查看docker标准输出json日志

ll -h /var/lib/docker/containers/*/*-json.log
-rw-r----- 1 root root 13.8G Oct 11 14:00 /var/lib/docker/containers/2b6643f688a5234165fa1c3ad151f50bc4e7e4126020037584a0a39597d63f73/2b6643f688a5234165fa1c3ad151f50bc4e7e4126020037584a0a39597d63f73-json.log
-rw-r----- 1 root root 7.7G Oct 11 14:01 /var/lib/docker/containers/331768f0a8f5461a433cd317108be3703c5c2d0fa587596cb55545d3d91b1f06/331768f0a8f5461a433cd317108be3703c5c2d0fa587596cb55545d3d91b1f06-json.log
-rw-r----- 1 root root 12.4G Oct 11 13:59 /var/lib/docker/containers/8b78072e9819975ced653883b53e905bc1bab7dced597121c62264aa97835479/8b78072e9819975ced653883b53e905bc1bab7dced597121c62264aa97835479-json.log

可发现三个容器的标准输出日志占用了大量空间。

解释

Docker处理日志的时候多数是采用Docker logs <container>命令,因为docker默认采用的log-driver是json-file,所以Docker会捕捉每一个容器进程STDOUTS和STDERR,保存在磁盘文件.json.log中供Dockerlogs命令查询。

但我们在处理日志的时候是已经将应用程序日志写入日志文件中,并挂载到宿主机上,所以docker 的json-file日志相当于重复记录了整个日志,导致空间浪费。

处理

这个时候可以将json-file直接清理掉,注意不能直接删除文件,删除后所占用的空间并不会释放,这是因为 在Linux或者Unix系统中,通过rm或者文件管理器删除文件将会从文件系统的目录结构上解除链接(unlink).然而如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用

正确姿势是: > *-json.log,当然也可以通过rm删除后重启docker

解决

通过定时脚本执行清空超过一定大小的json.log

实现如下

#!/bin/bash 
#清理docker 日志 
container_path=/var/lib/docker/containers 
for container_shortid in $(docker ps -a -q);do 
    container_id=$(docker inspect -f '``.`Id`' $container_shortid)
    [ -f ${container_path}/${container_id}/${container_id}-json.log ] || continue 
    log_size=$(ls -l ${container_path}/${container_id}/${container_id}-json.log | awk '{print $5}')
    #log size great than 1G , 
    if [ ${log_size} -gt 1073741824 ] ;then
       echo "$(docker inspect -f '``.`Name`' ${container_id}) ${container_id}-json.log $(date +%F\ %T) size is:  $[${log_size}/1073741824]G $[${log_size}%1073741824/1048576]M $[${log_size}%1073741824%1048576/1024]K $[${log_size}%1073741824%1048576%1024]B = $(echo "scale=2;${log_size}/1073741824" | bc)G "
       : > ${container_path}/${container_id}/${container_id}-json.log
    fi
done

输出:/microsrv_zuul 3d03e47c87df387e8e963b854cc3de37b310f03ffcf36a476b2191388c8fd74e-json.log 2017-10-13 05:32:41size is:   3G 884M 973K 59B = 3.86G

添加crontab每天执行即可