引言
系统运行一段时间之后难免容器会出现问题,出现问题并不可怕,可怕的是不知道问题出现在哪里,这个时候查看当前容器运行的日志就能够排查出一些问题
正文
日志存储位置
在Linux系统中 Docker 启动后,日志默认会以 json-file
的格式存储于 /var/lib/docker/containers/容器ID/容器ID-json.log
下
1 2 3 4 5 6 7 8 9
| -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
|
不建议去这里直接读取内容,而是使用 docker logs -f
来实时查看,如果使用 docker Compose,则可以通过 docker-compose logs 容器ID/名称
来查看
日志驱动
Docker 的默认是 json-file
会将容器的日志保存在 json 文件中,Docker 负责格式化其内容并输出到 STDOUT 和 STDERR
支持的驱动
驱动 |
描述 |
none |
运行的容器没有日志,docker logs 也不返回任何输出 |
local |
日志以自定义格式存储 |
json-file |
日志格式为JSON,默认 |
syslog |
将日志消息写入syslog |
journald |
将日志消息写入journald |
gelf |
将日志消息写入 Graylog 扩展日志格式(GELF)端点,例如 Graylog 或 Logstash |
fluentd |
将日志消息写入 fluentd (转发输入) |
awslogs |
将日志消息写入Amazon CloudWatch Logs |
splunk |
使用HTTP事件收集器将日志消息写入splunk |
etwlogs |
将日志消息写为Windows事件跟踪(ETW)事件,仅适用于Windows平台 |
gcplogs |
将日志消息写入Google Cloud Platform(GCP)Logging |
logentries |
将日志消息写入Rapid7 Logentries |
local
local驱动,记录从容器的 STOUT/STDERR 的输出,并写到宿主机的磁盘,默认为每个容器保留100MB日志,存储位置在
1
| /var/lib/docker/containers/容器id/local-logs/容器id.log
|
可配置项
选项 |
注释 |
max-size |
每个日志文件最大的大小(k,m,g) |
max-file |
最大日志文件数量 |
compress |
是否压缩 |
配置路径
1 2 3 4 5 6 7
| $ vim /etc/docker/daemon.json { "log-driver": "local", "log-opts": { "max-size": "10m" } }
|
json-file
记录从容器的 STOUT/STDERR 的输出 ,用 JSON
的格式写到文件中,日志中包含输出日志、时间戳和输出格式
日志保存在
1
| /var/lib/docker/containers/容器ID/容器ID-json.log
|
可配置项
选项 |
注释 |
max-size |
每个日志文件最大的大小(k,m,g) |
max-file |
最大日志文件数量 |
labels |
与日志记录相关的标签列表 |
env |
与日志记录相关的环境变量列表 |
env-regex |
与日志记录相关的环境变量正则 |
compress |
是否压缩 |
配置方式
1 2 3 4 5 6
| $ vim /etc/docker/daemon.json { "registry-mirrors": ["http://f1361db2.m.daocloud.io"], "log-driver":"json-file", "log-opts": {"max-size":"50m", "max-file":"1"} }
|
syslog
将日志路由到 syslog 服务器,可接收如下字段
- level:日志级别
- timestamp:时间戳
- hostname:日志主机
- facillty:系统模块
- 进程名和进程ID
Journald
将容器的日志发送到 systemd journal,可以使用 journal API 或者使用 docker logs
来查日志
查看容器驱动
可以通过如下命令查看系统当前设置的驱动
1
| docker info|grep "Logging Driver" | docker info --format '{{.LoggingDriver}}'
|
也可以通过如下命令查看某个容器的驱动
1
| docker inspect -f '{{.HostConfig.LogConfig.Type}}' 容器id
|
设置容器驱动
可以在 /etc/docker/daemon.json 配置默认系统容器驱动
1 2 3
| { "log-driver": "syslog" }
|
也可以在启动容器时设置 --log-driver
参数
1
| docker run -itd --log-driver json-file 镜像名
|
限制容器日志大小
从上面可以知道 Docker 容器日志存储在文件中,容器销毁后日志也被一并删除
如果容器一直运行并且一直产生日志,容器日志会导致磁盘空间爆满,如何解决这个问题?
查看下日志大小情况
1
| find /var/lib/docker/containers/ -name '*.log' -exec ls -lh {} \;
|
限制日志文件的大小方式有挺多种
设置容器日志大小
新建 /etc/docker/daemon.json
,有就编辑,添加 log-dirver
和 log-opts
参数
1 2 3 4 5
| { "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
这两个参数设置之后说明,一个容器最多保存 1500M(3 * 500)
日志,超过范围的日志不会被保存,文件中保存的是最新的日志,文件会自动滚动更新
设置完成之后,需要重新 docker
1
| systemctl restart docker
|
注意:设置的日志大小,只对 新建的容器有效
我们可以看到 hostconfig.json
文件的变化如下
设置之前
1 2 3 4 5
| ... "LogConfig": { "Type": "json-file", "Config": {} }
|
设置之后
1 2 3 4 5 6 7 8
| ... "LogConfig": { "Type": "json-file", "Config": { "max-file": "3", "max-size": "500m" } }
|
k8s中的容器日志
在 k8s 集群中 Docker 容器日志/var/lib/docker/containers/容器ID/目录
的文件如下
1 2 3 4 5
| -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容器)关联了这些文件,查看 config.v2.json
配置文件
1 2 3 4
| "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",
|
查看 /var/lib/docker/containers/<容器id>/hostconfig.json
发现有如下设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "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, //其他参数没有列出来 ...... ...... }
|
说明一个容器中日志文件的大小最大为100m,最多10个文件,一个容器的日志最多保存1000m日志数据
查看 /etc/docker/daemon.json
发现有如下配置
1 2 3 4 5 6 7 8
| { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "10" } }
|
下面列出了一个容器的日志文件达到设置值的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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
|
其他
清空日志脚本
1 2 3 4 5 6 7 8 9
| #!/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 ========
|