更改docker的日志引擎为 journald

在 docker 原生支持的众多日志引擎中, 结合实际生产环境的需求, 最终选择了众多linux 发行版都默认支持的 journald 日志系统, journald 日志系统是 systemd 自带的服务, 在实际使用过程中, 上手很快, 而且很符合线上查看 docker 日志的习惯与需求

docker原生支持的日志引擎

  • none 关闭 docker 的回显日志, docker logs 看不到任何输出
  • json-file 把每个 container 的回显日志打到每个 container 的内部, 形式为json 文件
  • syslog 把所有 container 的回显日志打到系统的 syslog 中
  • journald 把所有 container 的回显日志打到系统的 journald 服务中
  • fluentd 把所有 container 的回显日志打到 fluentd 服务中
  • gelf 把所有 container 的回显日志打到支持 GELF(Graylog Extended Log Format) 格式的服务中, 比如 Graylog 或 Logstash

以上原生的日志引擎是最常用的6种,其中 json-file 是 docker 默认使用的日志系统

为什么选择了journald

  • 首先排除了 none 的日志引擎, 因为它抛弃了宿主机中所有 container 的回显日志
  • 之所有排除 json-file 是因为在实际使用中, 有的 container 在启动后有大量的回显日志, 尤其在程序内部报错时打出的日志信息尤其巨大, 而该 json 文件会放到磁盘对应该 container 的文件夹中越来越大, 常常因为某几个 container 的 json 日志而撑爆整个宿主机的磁盘
  • syslog 日志收集的方式我在使用 harbor 私有镜像服务的时候见过, harbor 官方提供的部署方式中, 所有的 container 的日志都集中收集在某一个 container 中, 执行 docker logs 的时候会提示你 "logs" command is supported only for "json-file" and "journald" logging drivers (got: syslog)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# syslog 在 harbor 中的应用解析

#harbor 服务由多了 container 组成, 其中有一个 container 的名字叫 "harbor-log" 这个就是整个 harbor 服务日志的大本营

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55917fe77a5d nginx:1.11.5 "nginx -g 'daemon off" 5 weeks ago Up 5 weeks 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx
66a5f3fd3c41 vmware/harbor-jobservice:0.5.0 "/harbor/harbor_jobse" 5 weeks ago Up 5 weeks harbor-jobservice
732e69978f61 vmware/harbor-ui:0.5.0 "/harbor/harbor_ui" 5 weeks ago Up 5 weeks harbor-ui
61678dddbc21 library/registry:2.5.0 "/entrypoint.sh serve" 5 weeks ago Up 5 weeks 5000/tcp registry
18a49a051913 vmware/harbor-db:0.5.0 "docker-entrypoint.sh" 5 weeks ago Up 5 weeks 3306/tcp harbor-db
aac08df72abb vmware/harbor-log:0.5.0 "/bin/sh -c 'crond &&" 5 weeks ago Up 5 weeks 0.0.0.0:1514->514/tcp harbor-log

# 除了 "harbor-log" 这个容器之外, 所有容器的日志类型都是如下指定的

"LogConfig": {
"Type": "syslog",
"Config": {
"syslog-address": "tcp://127.0.0.1:1514",
"tag": "proxy"
}
},

# 所有容器的回显日志都发送到了 "127.0.0.1:1514" 这个地址, 而这个地址就是 "harbor-log" 容器对外映射的端口

# 可以看出 harbor 的用法是单独创建一个容器用来收集所有相关容器的日志

这个模式在我们生产环境中并不适用, 因为无法通过 docker logs 直接查看日志, 而是需要到指定的容器中去找, 这对于研发查看日志拍错来说无疑是个巨大的麻烦.所以这个日志引擎也不适用于我们的生产环境

  • fluentd 和 gelf 这两个日志服务类型一般是配合 elasticsearch/kibana 来一起使用, 因为回显日志是程序回显, 不是业务日志回显, 所以没有进入到 elasticsearch 分析的需求, 业务日志一部分在 nginx 那一层就分析了, 还有的是通过把日志目录挂载出来, 让宿主机的 Log 服务去处理的. 因为规模比较小, 所以暂时用不到这个重的日志服务. 如果你需要分析很多 container 的日志, 可以考虑使用 fluentd 或 logstash

小结: 因为量级不够大, 用不到 fluentd 和 logstash; 因为研发有需求通过 docker logs 快速查看日志, 所以不能用 syslog; 因为 json-file 有让日志文件无止境变大的问题, 而清掉这个日志只能通过停止⏹docker 服务后才能echo > filename被重定向掉, 否则会引起 docker 服务的崩溃; 最终选择了现在大多数 Linux 发行版默认支持的 journald 日志服务.

更改 docker 的默认存储引擎

1
2
3
4
> vim /etc/docker/daemon.js
{
"log-driver": "journald"
}

只需在 json 配置文件中加入一行日志引擎的配置即可, 最后重启 docker 服务

可以通过 docker info 查看更改后的日志引擎

指定 container 启动时的存储引擎

1
2
3
docker run \
--log-driver=journald \
alpine ash

更换为 journald 日志引擎后, 所有使用 journald 引擎的 container 依然可以通过 docker logs containerName 的方式查看回显日志, 也可以在宿主机中使用 journalctl 命令来查看日志的集合,以下是 journalctl 的常用配置及用法简介

journald 配置文件

journald 的配置文件存放在 /etc/systemd/journald.conf

默认的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[Journal]
#Storage=auto 存储为自动模式, 其他模式有无日志模式, 纯内存模式和纯磁盘模式
#Compress=yes 默认启动压缩功能
#Seal=yes 默认加密, 日志文件为二进制文件, 无法 vim或tail 查看
#SplitMode=uid
#SyncIntervalSec=5m
#RateLimitIntervalSec=30s
#RateLimitBurst=1000
#SystemMaxUse= 精确设置日志可以占用的最大磁盘空间
#SystemKeepFree= 保证系统剩余的空间大小
#SystemMaxFileSize=
#SystemMaxFiles=100
#RuntimeMaxUse=
#RuntimeKeepFree=
#RuntimeMaxFileSize=
#RuntimeMaxFiles=100
#MaxRetentionSec=
#MaxFileSec=1month
#ForwardToSyslog=no
#ForwardToKMsg=no
#ForwardToConsole=no
#ForwardToWall=yes
#TTYPath=/dev/console
#MaxLevelStore=debug
#MaxLevelSyslog=debug
#MaxLevelKMsg=notice
#MaxLevelConsole=info
#MaxLevelWall=emerg

journald 默认配置下, 默认日志最大限制为所在文件系统容量的 10%

默认配置下, journald 的日志存放在 /var/log/journal 下, 如果该目录在根分区下, 且根分区空间大小为10G, 那么 journald 存放日志最大的大小为1G, 超出1G 后将删除最早的日志

也可以精确指定占用的空间大小

1
SystemMaxUse=50M

其他 journald 的配置也没有细研究过, 主要还是没有需求~ 😆

journalctl 的使用

  • journalctl 从头查看所有日志
  • journalctl -b 查看本次开机后的所有系统引导日志 journalctl -b -1 显示上次开机后的系统引导日志, 以此类推
  • journalctl -f 类似于 tail -ftailf
  • journalctl /usr/bin/dockerd 后加程序的绝对路径,可以显示该程序的所有日志信息
  • journalctl -xe systemd 启动程序失败时会提示你使用这个命令查看错误信息, 其中x 表示在日志输出中增加一些解释性的短文本, e表示立即跳转至日志的尾部

journald 使用注意事项

在 journald 日志引擎的实际使用中, 我们发现了另一个问题, 就是 journald 的默认配置文件中的一个问题. 在 journald 默认的配置文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
root@larry-ali:~# cat /etc/systemd/journald.conf
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See journald.conf(5) for details.

[Journal]
#Storage=auto
#Compress=yes
#Seal=yes
#SplitMode=uid
#SyncIntervalSec=5m
#RateLimitInterval=30s
#RateLimitBurst=1000
#SystemMaxUse=
#SystemKeepFree=
#SystemMaxFileSize=
#SystemMaxFiles=100
#RuntimeMaxUse=
#RuntimeKeepFree=
#RuntimeMaxFileSize=
#RuntimeMaxFiles=100
#MaxRetentionSec=
#MaxFileSec=1month
#ForwardToSyslog=yes
#ForwardToKMsg=no
#ForwardToConsole=no
#ForwardToWall=yes
#TTYPath=/dev/console
#MaxLevelStore=debug
#MaxLevelSyslog=debug
#MaxLevelKMsg=notice
#MaxLevelConsole=info
#MaxLevelWall=emerg

有以下几个非常重要的优化项目

  • ForwardToSyslog=yes
  • ForwardToWall=yes

以上两个参数默认都是 yes 意味着 journald 收集日志后还会转发到 syslog 中

由此造成的影响是: journald 虽然可以乖乖的按照上面的配置进行日志的清理, 但是 syslog 却不在 journald 的控制范围之内

在日志量很大的情况下, 我们发现 syslog 中的日志量也变得巨大, 而且里面都是容器的日志, 所以我们需要把上面两个参数的值改为no

禁止🚫journald 收到日志后转发给 syslog

更改完配置文件后, 重启 journald 服务 systemctl restart systemd-journald.service


参考文档

docker 日志引擎官方文档: https://docs.docker.com/engine/admin/logging/overview/

journald 配置文件官方文档: https://www.freedesktop.org/software/systemd/man/journald.conf.html#

journalctl 命令官方文档: https://www.freedesktop.org/software/systemd/man/journalctl.html#

journalctl 中文man手册:http://www.jinbuguo.com/systemd/journalctl.html

journald.conf 中文手册:http://www.jinbuguo.com/systemd/journald.conf.html

journald 初级指南:http://os.51cto.com/art/201405/440886.htm