出品丨Docker公司(ID:docker-cn)
编译丨小东
每周一、三、五晚6点10分 与您不见不散
简 介
在传统上,设计和实现集中的日志记录总是成为马后炮。要等到各种问题出现,集中的日志记录成为优先事项,人们才会想到用这样的解决方案查询、查看和分析日志,以找到问题的根本原因。但是到了容器时代,在设计使用 Docker 企业版 (Docker EE) 的容器即服务 (CaaS) 平台时,优先解决集中式日志记录是至关重要的。随着在容器中部署的微服务数量不断增多,它们以日志(或事件)形式产生的数据量会发生指数增长,点击以下标题,回顾第一部分内容:
&
应用日志驱动
Docker 提供了多种可用于管理应用日志的日志记录驱动。请查看 Docker 文档获取完整列表,以及关于如何使用它们的详细信息。
一般而言,如果您已经设置了日志记录基础架构,就应该对此现成基础架构使用日志记录驱动。如果您尚没有现成的日志记录系统,那么需要在此处强调某些方面的优点和缺点。
驱动 | 优点 | 缺点 |
无 | 超级安全,因为不记录任何信息 | 没有日志会大大增加故障排除的难度 |
json-file | 默认驱动,docker logs 可使用它,支持标签 | 日志驻留在本地,并不聚合,如果没有限制措施,日志可能会占满本地磁盘 |
syslog | 大多数机器都附带 syslog,它是唯一支持 TLS 以实现加密日志传输的驱动,支持标签 | 需要设置为具有高度可用性 (HA),否则如果其不可用,容器启动时可能发生问题 |
journald | docker logs 也可使用此驱动,因为它在本地记录日志 - 日志聚合停止运行也不会造成影响,它还会收集 Docker 守护进程日志 | 由于日志是二进制格式的,需要执行附加步骤才能将其传输到日志收集器,不支持标签 |
gelf | 默认情况下提供可加索引的字段(container id、host、container name 等),支持标签 | 仅支持 UDP 协议,不支持 docker logs |
fluentd | fluentd 默认提供 container_name 和 container_id 字段,支持多路输出 | 对于本地日志不支持 docker logs |
awslogs | 使用 Amazon Web Services 时可方便地集成,减少了需要维护的基础架构,支持标签 | 用于混合云配置或本地部署安装时并非最理想的选择,不支持 docker logs |
splunk | 可方便地与 Splunk 集成,支持 TLS,高度可配置,支持标签,附加指标 | Splunk 需要有高可用性,否则容器启动时可能发生问题,不支持 docker logs |
etwlogs | 用于在 Windows 上进行日志记录的通用框架,默认可索引值 | 仅可在 Windows 上工作,必须使用其他实用程序将这些日志从 Windows 机器转移到日志聚合 |
gcplogs | 可简单地与 Google Compute 集成,减少了需要维护的基础架构,支持标签 | 用于混合云配置或本地部署安装时并非最理想的选择,不支持 docker logs |
应用日志驱动注意事项
选择应用日志驱动时,请考虑下列因素:
如果日志数据高度敏感,则 syslog 和 splunk 是很好的选择,因为可以配置他们使用 TLS 来传输日志。
journald 日志驱动非常适合用于保留 docker logs 的使用情况以及记录 Docker 守护进程日志。此驱动既方便故障排除,又实现日志可移植性。此驱动的另一个优点是,日志将首先在本地写入,因此减少了对日志记录基础架构的依赖。
如果 Docker EE 集群仅在一个云提供商处存在,则可以使用 awslogs 或 gcplogs。
如果存在现有的 Splunk 安装,则应使用 splunk 日志驱动。
如果环境中存在可以存储日志的 NoSQL 数据库,那么 gelf 和 fluentd 日志驱动都是好选择。
对于开发或测试环境,如果查看日志流比查看索引并搜索日志更为有效,那么使用 json-file 或 journald 可能很有帮助。(如果使用 json-file,请考虑传递 max-size 和 max-file 选项,以免日志填满文件系统。)
日志记录驱动设置导引
要实现全系统的日志记录,请在 /etc/docker/daemon.json 中创建一个条目。例如,使用下列代码来启用 gelf 输出插件:
{
“log-driver":“gelf",
“log-opts":{
"gelf-address":“udp://1.2.3.4:12201",
“tag":"{{.ImageName}}/{{.Name}}/{{.ID}}"
}
}
然后重启 Docker 守护进程。所有日志记录驱动都可以通过使用 /etc/docker/daemon.json 文件以类似的方式配置。在上面的示例中使用了 gelf 日志驱动,tag 字段设置在收集日志时可以搜索和索引的附加数据。请参阅每种日志记录驱动的文档,了解可以从日志驱动设置的其他字段。
使用 /etc/docker/daemon.json 文件设置日志将会分别对每个节点设置默认日志记录行为。这些设置可以被每个服务或每个容器级别的设置覆盖。覆盖默认日志记录行为可能对故障排除很有用,因为可以实时查看日志。
如果在配置 daemon.json 文件使用 gelf 日志驱动的系统上创建服务,则所有在该主机上运行的容器日志都将转至 gelf-address 配置设置的地址。
如果希望使用其他日志记录驱动,例如用于查看来自容器的 stdout 的日志流,则可以临时覆盖默认日志记录行为。
docker service create \
--log-driver json-file --log-opt max-size=10m \
nginx:alpine
然后可以配合 Docker 服务日志,更轻松地识别服务的问题。
Docker 服务日志
docker service logs 是在 Docker EE 的 17.05 版和 17.06 版中推出的。当服务有多个从节点任务时,它可提供多路复用的日志流。只要输入 docker service logs,这些日志就会在第一列显示发起任务名称,然后在右侧的列中显示每个从节点的实时日志。例如:
$ docker service create -d --name ping --replicas=3 alpine:latest ping 8.8.8.8
5x3enwyyr1re3hg1u2nogs40z
$ docker service logs ping
ping.2.n0bg40kksu8e@m00 | 64 bytes from 8.8.8.8: seq=43 ttl=43 time=24.791 ms
ping.3.pofxdol20p51@w01 | 64 bytes from 8.8.8.8: seq=44 ttl=43 time=34.161 ms
ping.1.o07dvxfx2ou2@w00 | 64 bytes from 8.8.8.8: seq=44 ttl=43 time=30.111 ms
ping.2.n0bg40kksu8e@m00 | 64 bytes from 8.8.8.8: seq=44 ttl=43 time=25.276 ms
ping.3.pofxdol20p51@w01 | 64 bytes from 8.8.8.8: seq=45 ttl=43 time=24.239 ms
ping.1.o07dvxfx2ou2@w00 | 64 bytes from 8.8.8.8: seq=45 ttl=43 time=26.403 ms
在尝试查看包含多个从节点的服务的日志输出时,此命令很有帮助。通过实时查看跨多个从节点流式传输的日志,可以即时了解跨整个集群的服务问题,并进行故障排除。
ELK 设置
请参阅 swarm-elk 镜像仓库获取关于在 Docker Swarm 上如何向 ELK 发送日志的信息。此镜像仓库包含一个 Docker Compose 文件,它会设置完整的 ELK 技术栈。该镜像仓库是试验使用 ELK 的 Docker 日志记录的良好起点,但是在将它用于生产之前,也要考虑高可用性和排队系统。
Splunk 设置
Splunk 是另一种流行的日志记录实用程序。要设置 Splunk,请使用此 swarm-splunk 镜像仓库中提供的 Docker Compose 文件,按相应步骤操作。
每个 Splunk 转发程序都连接到本地 Docker 套接字,因此在守护进程级别不需要其他日志驱动配置。连接本地 Docker 套接字也使 Splunk 在拉取日志之外还能拉取 Docker 容器统计信息。
传统应用现代化
没有理由认为只有现代化的应用才能使用容器记录日志。我们可以在不更改任何应用代码的情况下,使传统应用现代化,同时仍然保留现代化的日志记录的优点。
在理想情况下,应用会将日志发送到 stdout/stderr,而 Docker 将这些日志发送到配置的日志记录目标。有时某些应用配置为将日志发送到多个位置。如何捕获这些日志,而又不更改任何应用源代码?
可以创建一个 Docker 存储卷(或多个存储卷),指向应用中日志文件驻留的位置。利用 Docker 模板功能,可以给每个存储卷加上服务 ID(一个整数)后缀。如果有多个服务任务在同一个主机上运行,给存储卷名称加上后缀可以避免任何与日志记录相关的冲突。需要创建一个全局服务,使用目录通配符支持运行日志记录代理程序。最后,可以通过日志记录实用程序设置附加的正则表达式,将文件的源目录转变为带索引的值。
下面的示例显示了如何使用官方的 Tomcat 镜像实现此目的。官方的 Tomcat 镜像在 /usr/local/tomcat/logs 中记录多个文件,这与大多数 Java 应用的行为非常相似。在该路径下,可以找到 catalina.2017-07-06.log、host-manager.2017-07-06.log、localhost.2017-07-06.log、localhost_access_log.2017-07-06.txt 和 manager.2017-07-06.log 等文件。
为日志记录实用程序创建一个挂载 /var/lib/docker/volumes:/logs/volumes 的全局服务。
为使用与此一般示例类似的规则记录日志的日志记录代理程序创建日志记录规则:“/log/volumes/*/_data/*.log"。
启动对存储卷使用基于 go 的模板操作的服务:
启动该服务时,使用这些参数:
docker service create \
-d \
--name prod-tomcat \
--label version=1.5 \
--label environment=prod \
--mount type=volume,src="{{.Task.Name}}",dst=/usr/local/tomcat/logs \
--replicas 3 \
tomcat:latest
如果两个从节点在同一个节点上调度,则将在主机 prod-tomcat.1.oro7h0e5yow69p9yumaetor3l 和 prod-tomcat.2.ez0jpuqe2mkl6ppqnuffxqagl 上创建两个包含日志的存储卷。
只要日志记录代理程序支持通配符,并且通过检查索引节点(而不是文件)来处理所有日志轮替,那么应该就会收集日志。
如果应用将日志记录到多个位置,则尝试建立从日志到单个目录的符号链接,或向存储卷添加描述性名称。如果已将描述性名称添加到存储卷名称,则任何类型的提取都需要经过更新才能容纳该更改。(即使用 grok)
大多数日志记录器应该会收集文件路径以及日志内容。通过将日志文件驻留的存储卷转为可加索引的字段,就可以从这些类型的应用搜索和聚合信息。下面是一个示例,它使用 grok 模式,并创建了两个新的可索引字段 CONTAINER_NAME 和 FILENAME。
match => { "path" => "/log/volumes/%{DATA:CONTAINER_NAME}/_data/%{GREEDYDATA:FILE_NAME}" }
CONTAINER_NAME 将匹配来自容器的 stdout 流输出,从而方便基于容器的日志进行过滤。
在 swarm-elk 镜像仓库中可以找到更多关于某镜像仓库的信息和一个工作示例。
Windows 日志记录
ETW 日志记录驱动将容器日志作为 ETW 事件转发。ETW 代表 Event Tracing in Windows(Windows 中的事件跟踪),是用于在 Windows 中跟踪应用的通用框架。每个 ETW 事件都包含一条消息,其中含有日志及其上下文信息。然后客户端可以创建 ETW 侦听器来侦听这些事件,并将它们转发到可以收集和分析日志的位置。
要在 Windows 上使用 ETW 驱动,请使用标志 --log-driver=etwlogs 创建服务或运行容器:
下面是一条示例事件消息:
container_name: backstabbing_spence,
image_name: windowsservercore,
container_id: f14bb55aa862d7596b03a33251c1be7dbbec8056bbdead1da8ec5ecebbe29731,
image_id: sha256:2f9e19bd998d3565b4f345ac9aaf6e3fc555406239a4fb1b1ba879673713824b,
source: stdout,
log:Hello world!
总 结
Docker 在日志记录方面提供了很多选项,在采用平台时设计日志记录策略会很有帮助。对大多数系统来说,将日志数据留在主机上是不够的。如果具有索引和搜索的能力,以及自助服务平台,就可以让运维人员和开发人员获得更顺利的体验。
点击下列标题,阅读更多干货
如果本文对你有帮助,欢迎分享到朋友圈!获取更多Docker实用技巧,扫描下图二维码!