赞
踩
在Linux系统中docker启动后日志存储在/var/lib/docker/containers/容器ID/
目录中,启动一个容器后,容器ID目录中会生成如下文件:
-rw-r----- 1 root root 10325 Nov 16 14:09 12f7f218aa3ba42cf58e3a77ab7ff615c3b06cb04c8d2f22561592c2ea2d3126-json.log
drwx------ 2 root root 4096 Nov 16 14:07 checkpoints
-rw------- 1 root root 3664 Nov 16 14:07 config.v2.json
-rw-r--r-- 1 root root 1514 Nov 16 14:07 hostconfig.json
-rw-r--r-- 1 root root 13 Nov 16 14:07 hostname
-rw-r--r-- 1 root root 174 Nov 16 14:07 hosts
drwx------ 2 root root 4096 Nov 16 14:07 mounts
-rw-r--r-- 1 root root 108 Nov 16 14:07 resolv.conf
-rw-r--r-- 1 root root 71 Nov 16 14:07 resolv.conf.hash
每个容器的日志默认都会以 json-file 的格式存储于/var/lib/docker/containers/<容器id>/<容器id>-json.log
下,不过并不建议去这里直接读取内容,因为容器的日志则可以通过 docker logs
命令来访问,而且可以像 tail -f
一样,使用 docker logs -f
来实时查看。如果使用 Docker Compose,则可以通过 docker-compose logs <服务名>
来查看。
从上面可以知道docker容器日志存储在文件中,容器销毁后/var/lib/docker/containers/<容器id>/
目录会被自动删除,所以容器日志也被一并删除。如果容器一直运行并且一直产生日志,容器日志会导致磁盘空间爆满,如何解决这个问题?
新建/etc/docker/daemon.json
,若有就不用新建了。添加log-dirver和log-opts参数,如下:
# vim /etc/docker/daemon.json
{
"registry-mirrors": ["http://f613ce8f.m.daocloud.io"],
"log-driver":"json-file",
"log-opts": {"max-size":"500m", "max-file":"3"}
}
max-size=500m
,意味着一个容器日志大小上限是500M
max-file=3
,意味着一个容器最多有三个日志,分别是:容器id-json.log
、容器id-json.log.1
、容器id-json.log.2
, 当日志文件的大小达到500m时,自动划分文件保存,最多划分3个文件
这两个参数设置之后说明,一个容器最多保存1500m(3 * 500)日志,超过范围的日志不会被保存,文件中保存的是最新的日志,文件会自动滚动更新。
# 重启docker守护进程
systemctl daemon-reload
# 重启docker
systemctl restart docker
设置完成之后,需要删除容器,并重新启动容器,我们可以看到/var/lib/docker/containers/<容器id>/hostconfig.json
文件的变化如下:
设置log-opts
之前:
cat hostconfig.json
# 其中的LogConfig如下
"LogConfig": {
"Type": "json-file",
"Config": {}
}
设置log-opts
之后:
cat hostconfig.json
# 其中的LogConfig如下
"LogConfig": {
"Type": "json-file",
"Config": {
"max-file": "3",
"max-size": "500m"
}
}
在k8s集群中docker容器日志/var/lib/docker/containers/容器ID/
目录的文件如下:
-rw-r----- 1 root root 27K Oct 30 19:45 830b17595b2c5cac86e9294b00e90d90e867d7d67489b4e4ee47f847d4726efb-json.log
drwx------ 2 root root 4.0K Oct 30 19:44 checkpoints
-rw------- 1 root root 24K Oct 30 19:44 config.v2.json
-rw-r--r-- 1 root root 2.1K Oct 30 19:44 hostconfig.json
drwx------ 2 root root 4.0K Oct 30 19:44 mounts
与docker容器目录相比少了一些文件:hostname、hosts、resolv.conf、resolv.conf.hash
k8s通过sandbox(pause容器,关于pause容器的介绍可以查阅资料)
关联了这些文件,通过查看cat config.v2.json
可以发现如下配置:
"HostnamePath": "/var/lib/docker/containers/27c9b0c0d1d7c8c7db515f96d5ae8c50ef7aeea02ecddcaa6546ea233dc5445c/hostname",
"HostsPath": "/var/lib/kubelet/pods/88f3a665-fdd1-4ad5-b0e0-0b613f762b4c/etc-hosts",
"ShmPath": "/var/lib/docker/containers/27c9b0c0d1d7c8c7db515f96d5ae8c50ef7aeea02ecddcaa6546ea233dc5445c/mounts/shm",
"ResolvConfPath": "/var/lib/docker/containers/27c9b0c0d1d7c8c7db515f96d5ae8c50ef7aeea02ecddcaa6546ea233dc5445c/resolv.conf",
使用命令cat /var/lib/docker/containers/<容器id>/hostconfig.json
查看hostconfig.json
的内容,发现有如下设置:
{
"Binds": [
"/var/lib/kubelet/pods/e268cba1-95c6-4c16-904c-6be0b70344ea/volumes/kubernetes.io~secret/default-token-7vpxg:/var/run/secrets/kubernetes.io/serviceaccount:ro",
"/var/lib/kubelet/pods/e268cba1-95c6-4c16-904c-6be0b70344ea/etc-hosts:/etc/hosts",
"/var/lib/kubelet/pods/e268cba1-95c6-4c16-904c-6be0b70344ea/containers/demo/eee5300c:/dev/termination-log"
],
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {
"max-file": "10",
"max-size": "100m"
}
},
"NetworkMode": cd "container:ab24db5934f3a0153d9deb3c2de054c87148c3919f1bc2b1d2c11c4c8a2c8c57",
"PortBindings": null,
//其他参数没有列出来
......
......
}
下面列出了一个容器的日志文件达到设置值的情况:
total 927M
drwx------ 2 root root 4.0K Sep 9 14:51 checkpoints
-rw------- 1 root root 24K Sep 9 14:51 config.v2.json
-rw-r----- 1 root root 69M Nov 16 14:21 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log
-rw-r----- 1 root root 96M Nov 16 07:24 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.1
-rw-r----- 1 root root 96M Nov 15 21:49 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.2
-rw-r----- 1 root root 96M Nov 15 12:04 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.3
-rw-r----- 1 root root 96M Nov 15 02:21 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.4
-rw-r----- 1 root root 96M Nov 14 16:47 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.5
-rw-r----- 1 root root 96M Nov 14 07:11 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.6
-rw-r----- 1 root root 96M Nov 13 21:35 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.7
-rw-r----- 1 root root 96M Nov 13 11:57 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.8
-rw-r----- 1 root root 96M Nov 13 02:21 f627a603df6e162645d6e29ad27b379b1b92607ea3a95667bcfcd851d9695f38-json.log.9
-rw-r--r-- 1 root root 2.2K Sep 9 14:51 hostconfig.json
drwx------ 2 root root 4.0K Sep 9 14:51 mounts
设置完日志大小和个数后,cat hostconfig.json没有任何变化,还是设置之前的个数和大小表情包
日志分两类,一类是 Docker 引擎日志
;另一类是 容器日志
。
Docker 引擎日志
一般是交给了 Upstart
(Ubuntu 14.04) 或者 systemd
(CentOS 7, Ubuntu 16.04)。前者一般位于 /var/log/upstart/docker.log
下,后者一般通过 jounarlctl -u docker
来读取。不同系统的位置都不一样,SO上有人总结了一份列表,我修正了一下,可以参考:
系统 | 日志位置 |
---|---|
Ubuntu(14.04) | /var/log/upstart/docker.log |
Ubuntu(16.04) | journalctl -u docker.service |
CentOS 7/RHEL 7/Fedora | journalctl -u docker.service |
CoreOS | journalctl -u docker.service |
OpenSuSE | journalctl -u docker.service |
OSX | ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/log/docker.log |
Debian GNU/Linux 7 | /var/log/daemon.log |
Debian GNU/Linux 8 | journalctl -u docker.service |
Boot2Docker | /var/log/docker.log |
容器的日志
则可以通过 docker logs
命令来访问,而且可以像 tail -f
一样,使用 docker logs -f
来实时查看。如果使用 Docker Compose,则可以通过 docker-compose logs <服务名>
来查看。
如果深究其日志位置,每个容器的日志默认都会以 json-file
的格式存储于 /var/lib/docker/containers/<容器id>/<容器id>-json.log
下,不过并不建议去这里直接读取内容,因为 Docker 提供了更完善地日志收集方式 - Docker 日志收集驱动
。
关于日志收集,Docker
内置了很多日志驱动,可以通过类似于 fluentd
, syslog
这类服务收集日志。无论是 Docker
引擎,还是容器,都可以使用日志驱动。比如,如果打算用 fluentd
收集某个容器日志,可以这样启动容器:
$ docker run -d \
--log-driver=fluentd \
--log-opt fluentd-address=10.2.3.4:24224 \
--log-opt tag="docker.{{.Name}}" \
nginx
其中 10.2.3.4:24224
是 fluentd
服务地址,实际环境中应该换成真实的地址。
docker容器日志导致主机磁盘空间满了。docker logs -f container_name
噼里啪啦一大堆,很占用空间,不用的日志可以清理掉了。
在linux上,容器日志一般存放在/var/lib/docker/containers/container_id/
下面, 以json.log结尾的文件(业务日志)很大,查看各个日志文件大小的脚本docker_log_size.sh,内容如下:
#!/bin/sh
echo "======== docker containers logs file size ========"
logs=$(find /var/lib/docker/containers/ -name *-json.log)
for log in $logs
do
ls -lh $log
done
# chmod +x docker_log_size.sh
# ./docker_log_size.sh
如果docker容器正在运行,那么使用rm -rf
方式删除日志后,通过df -h
会发现磁盘空间并没有释放。原因是在Linux或者Unix系统中,通过rm -rf
或者文件管理器删除文件,将会从文件系统的目录结构上解除链接(unlink)。如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用。正确姿势是cat /dev/null > *-json.log
,当然你也可以通过rm -rf
删除后重启docker。接下来,提供一个日志清理脚本clean_docker_log.sh
,内容如下:
#!/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
但是,这样清理之后,随着时间的推移,容器日志会像杂草一样,卷土重来。
上述方法,日志文件迟早又会涨回来。要从根本上解决问题,需要限制容器服务的日志大小上限。这个通过配置容器docker-compose的max-size选项来实现
nginx:
image: nginx:1.12.1
restart: always
logging:
driver: “json-file”
options:
max-size: “5g”
重启nginx容器之后,其日志文件的大小就被限制在5GB,再也不用担心了。
新建/etc/docker/daemon.json,若有就不用新建了。添加log-dirver和log-opts参数,样例如下:
# vim /etc/docker/daemon.json
{
"registry-mirrors": ["http://f613ce8f.m.daocloud.io"],
"log-driver":"json-file",
"log-opts": {"max-size":"500m", "max-file":"3"}
}
max-size=500m,意味着一个容器日志大小上限是500M,
max-file=3,意味着一个容器有三个日志,分别是id+.json、id+1.json、id+2.json。
// 重启docker守护进程
# systemctl daemon-reload
# systemctl restart docker
注意:设置的日志大小,只对新建的容器有效。
如果是要清除全部日志的话,直接一条语句就能清除:
find /var/lib/docker/containers/ -name *-json.log | awk ‘{print "echo > "$1}’ | sh
简单一点,linux 上执行
truncate -s 0 /var/lib/docker/containers//-json.log
问一下,设置的容器日志大小上限超过了docker会怎么办?
被清理?
为什么要添加log-dirver参数?
A:你可以查看docker官方文档的log-driver配置选项,daemon的配置参数列表 网页链接
Q:不加也可以,不加就用默认的了,此文讲的是如何限制日志大小,就不要把无关的写上去了
docker容器导致主机磁盘空间满了
如何清理Docker容器日志?
如何找出docker容器日志文件
容器日志一般存放在/var/lib/docker下面,可使用如下命令查看各个日志的文件大小
ls -lh $(find /var/lib/docker/containers/ -name *-json.log)
如何清理日志
如果docker容器正在运行,那么使用rm -rf 方式删除日志后,通过df -h会发现磁盘空间并没有释放
原因:在Linux或者Unix系统中,通过rm或者文件管理器删除文件将会从文件系统的目录结构上解除链接(unlink).然而如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用
正确姿势是cat /dev/null > *-json.log,当然你也可以通过rm删除后重启docker
清理脚本:
#!/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 =========================="
示例:ocker inspect jenkins | grep LogPath | cut -d ':' -f 2 | cut -d ',' -f 1 | xargs echo | xargs truncate -s 0
这种方式应该更简单
Q:
请问为什么我使用这个命令不行?执行后给出如下提示:
[1] 27441
[java@docker-test data]$ cut:选项需要一个参数 – d
Try ‘cut --help’ for more information.
什么原因呢?
A:
解析错了,用这个吧:docker inspect 【container name】| grep LogPath | cut -d ‘:’ -f 2 | cut -d ‘,’ -f 1 | xargs echo | xargs truncate -s 0
【container name】直接替换成容器名称,例如:docker inspect jenkins | grep LogPath | cut -d ‘:’ -f 2 | cut -d ‘,’ -f 1 | xargs echo | xargs truncate -s 0
rancher的介绍中也有docker相关的 “docker调优”:https://docs.rancher.cn/rancher2x/install-prepare/best-practices/docker.html
1、新建/etc/docker/daemon.json,若有就不用新建了
2、添加log-dirver和log-opts参数,样例如下
"log-driver":"json-file",
"log-opts":{ "max-size" :"100m","max-file":"1"}
max-file=3,意味着一个容器有三个日志,分别是id+.json、id+1.json、id+2.json
3、重启
sudo systemctl daemon-reload
sudo systemctl restart docker
这样就好啦,注意:只对新建的容器有效
参考资料:
https://docs.docker.com/engine/admin/logging/overview/#configure-the-logging-driver-for-a-container
===============================
清除大日志文件
容器日志一般存放在/var/lib/docker下面,可使用如下命令查看各个日志的文件大小
ls -lh $(find /var/lib/docker/containers/ -name *-json.log)
如何清理日志
如果docker容器正在运行,那么使用rm -rf 方式删除日志后,通过df -h会发现磁盘空间并没有释放
原因:在Linux或者Unix系统中,通过rm或者文件管理器删除文件将会从文件系统的目录结构上解除链接(unlink).然而如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用
正确姿势是cat /dev/null > *-json.log,当然你也可以通过rm删除后重启docker
Kubernetes对于容器实例的日志收集,并没有提供原生的解决方案。但提供使用 kubectl logs
命令查看容器实例运行时的日志。kubectl logs
命令实现的基本原理为:容器运行时默认将标准输出和标准错误中的日志输出到磁盘上保存。保存至主机目录:/var/lib/docker/containers/container_id/
目录。用户调用kubectl logs
命令时,kubelet
读取对应的日志文件中的数据,将数据回传给master,再由master返回到用户。从而实现用户对日志的查看。
腾讯云容器服务利用kubectl logs
命令,实现在控制台即可查看对应容器实例的日志,并且提供查看某个特定时间段的日志的功能,这极大的方便了用户对容器实例中的程序进行定位和跟踪。但是,由于在容器实例日志保存在本地,当程序中大量打印日志时,很容易造成主机上的磁盘空间大量被占用。在日志服务上线一段时间后,发现用户遇到这种情况时,一般是手动去清理日志。我们就考虑是不是有比较简单的方式,在集群节点对日志进行定期清理和回卷。
logrotate是个十分有用的工具,它可以自动对日志进行截断(或轮循)、压缩以及删除旧的日志文件。例如,你可以设置logrotate,让/var/log/foo日志文件每30天轮循,并删除超过6个月的日志。配置完后,logrotate的运作完全自动化,不必进行任何进一步的人为干预。
但如果按照之前的部署方式,需要手动在每个节点上都安装和配置对应logrotate工具。如果通过Kubernetes容器服务编排的能力,将logrotate通过Kubernetes中服务的方式部署到各个节点上,这样既可以实现只需要一次部署,部署到所有节点。并且通过容器的方式保证了logrotate配置的一致性。
logrotate方案
方案的具体实现是在Kubernetes集群中,创建DaemonSet资源实现。DaemonSet资源会在每个Node节点上都部署一个logrotate的容器实例,并且在容器实例中设置映射主机的log日志目录,从而实现日志的定时清理和回卷。
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: logrotate
spec:
template:
metadata:
labels:
app: logging
id: logrotate
name: logrotate
spec:
containers:
- name: logrotate-es
image: blacklabelops/logrotate
securityContext:
privileged: true
volumeMounts:
- name: containers
mountPath: /var/lib/docker/containers
- name: varlog
mountPath: /var/log/docker
- name: logs
mountPath: /logs
env:
- name: LOGS_DIRECTORIES
value: "/var/lib/docker/containers /var/log/docker"
- name: LOGROTATE_INTERVAL
value: "hourly"
- name: LOGROTATE_OLDDIR
value: "/logs"
volumes:
- hostPath:
path: /var/lib/docker/containers
name: containers
- hostPath:
path: /var/log/docker
name: varlog
- hostPath:
path: /var/log/containers/
name: logs
使用这个yaml文件,可以直接在Kubernetes中进行部署。
# kubectl create -f logrotate_ds.yaml
daemonset "logrotate" created
在示例的yaml文件中,logrotate服务将按照定时(1小时)的对日志进行回卷,回卷超过5个副本后则会对日志进行清理。如果有需要,可以修改相应的参数,设置不同的回卷规则和清理规则。详细的参数说明可以参考:https://github.com/blacklabelops/logrotate。
由于Kubernetes的日志收集,底层是通过docker来实现。而docker提供了一定的日志回卷和清理功能。可以通过在dockerd的启动参数中,增加log-opts()参数实现对日志的回卷和清理,其中max-size参数设置日志一个副本的最大值,max-file设置日志的最大的副本数。超过这个副本数则会对日志进行删除。
具体的修改过程包括三个步骤:
1、创建/etc/dockerd/daemon.json
{
"log-driver":"json-file",
"log-opts":{
"max-size" :"10m","max-file":"3"
}
}
参数说明: 设置单个容器日志超过10M则进行回卷,回卷的副本数超过3个就进行清理。
2、修改dockerd 服务配置文件
在 /etc/systemd/system/multi-user.target.wants/dockerd.serviced文件中添加dockerd启动参数–config-file=/etc/docker/daemon.json
3、重新启动dockerd服务
systemctl daemon-reload
service dockerd restart
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。