Upvotes 分享 PDF

Docker参考架构:Docker日志记录设计和最佳实践

介绍

传统上,设计和实施集中式日志记录是经过深思熟虑的。 直到问题出现时,优先级转移到集中式日志记录解决方案来查询,查看和分析日志,因此可以找到问题的根本原因。 然而,在容器时代,在设计带有Docker企业版(Docker EE)的容器即服务(CaaS)平台时,确定集中式日志记录的优先级至关重要。 随着容器中部署的微服务数量的增加,它们以日志(或事件)形式生成的数据量呈指数增长。

你会学到什么

该参考体系结构提供了Docker日志工作方式的概述,解释了Docker日志的两个主要类别,然后讨论了Docker日志记录最佳实践。

了解Docker日志记录

在深入考虑设计之前,从Docker日志记录的基础开始很重要。

Docker支持用于存储和/或流化主容器进程的容器 stdoutstderr日志的不同日志记录驱动程序(pid 1 < / T3>)。 默认情况下,Docker使用json-file日志记录驱动程序,但可以通过设置log-driver的值来将其配置为使用多个其他驱动程序 > in /etc/docker/daemon.json,然后重新启动Docker守护程序以重新加载其配置。

日志驱动程序设置适用于重新配置守护进程后启动的ALL容器(在重新配置日志记录驱动程序不会导致容器使用更新的配置后重新启动现有容器)。 要覆盖默认容器日志记录驱动程序,请使用 - log-driver - log-opt选项运行容器。 另一方面,群集模式服务可以通过使用docker service update --log-driver&lt; DRIVER_NAME&gt;来更新,以便随时使用不同的日志记录驱动程序。 --log-opt&lt;选项列表&gt; &lt;服务名称&gt;

Docker Engine的日志怎么样? 这些日志通常由默认系统管理器记录器处理。 大多数现代发行版(CentOS 7,RHEL 7,Ubuntu 16等)使用systemd,它使用journald进行记录,journalctl用于访问日志。 要访问引擎日志,请使用journalctl -u docker.service

Docker日志类别和来源

现在已经介绍了Docker日志记录的基础知识,本节将介绍它们的类别

Docker日志通常分为两类:基础架构管理应用程序日志。 大多数日志根据需要访问日志的角色自然落入这些类别。

  • 运营商主要关注平台的稳定性以及服务的可用性。

  • 开发人员更关心他们的应用程序代码以及他们的服务如何执行。

为了建立一个自助服务平台,运营商和开发人员都应该能够访问他们所需的日志,以便履行其职责。 DevOps实践表明,在服务可用性和性能方面存在共同的全面责任。 但是,每个人都不应该需要访问平台上的每个日志。 例如,开发人员只需要访问他们的服务和集成点的日志。 运营商更关心Docker守护进程日志,UCP和DTR可用性以及服务可用性。 由于开发人员和操作员都应该知道服务可用性,因此存在一些重叠。 通过访问每个角色所需的日志,可以在问题发生时减少故障排除,并减少平均解决时间(MTTR)。

基础架构管理日志

基础架构管理日志包括Docker Engine的日志,运行UCP或DTR的容器以及部署的任何集装箱化的基础架构服务(可以考虑集装箱化的监视代理)。

Docker引擎日志

如前所述,默认情况下,Docker Engine日志由操作系统的系统管理员捕获。 这些日志可以发送到集中式日志记录服务器。

UCP和DTR系统日志

UCP和DTR被部署为Docker容器。 他们的所有日志都在容器的STOOUT/STDERR中捕获。 Docker Engine的默认日志记录驱动程序捕获这些日志。

UCP可以配置为使用远程系统日志记录。 这可以在安装后从UCP UI为其所有容器完成。

注意:建议在安装UCP和DTR之前配置Docker Engine默认日志记录驱动程序,以便所选日志记录驱动程序捕获它们的日志。 这是由于无法在创建容器的日志记录驱动程序后更改它。 唯一的例外是ucp-agent,它是作为Swarm服务部署的UCP的一个组件。

基础设施服务

基础设施运营团队部署集装箱化的基础设施服务,用于各种基础设施运营,如监控,审计,报告,配置部署等。 这些服务也会产生需要捕获的重要日志。 通常,它们的日志仅限于其容器的STOOUT/STDERR,所以它们也会被Docker Engine默认日志记录驱动程序捕获。 如果不是,他们需要分开处理。

应用程序日志

应用程序生成的日志可以是自定义应用程序日志和应用程序主进程的STDOUT / STDERR日志的组合。 如前所述,所有容器的STDOUT / STDERR日志都由Docker Engine默认日志记录驱动程序捕获。 所以,不需要执行任何自定义配置来捕获它们。 如果应用程序具有自定义日志记录(例如将日志写入容器内的/var/log/myapp.log),那么考虑这一点很重要。

Docker日志设计注意事项

了解Docker日志的类型很重要。 定义哪些实体最适合消费和拥有它们也很重要。

分类Docker日志

主要有两类:基础设施日志和应用程序日志。

确定组织所有权

根据组织的结构和政策,决定这些类别是否与现有团队有直接映射。 如果他们不这样做,那么定义负责这些日志类别的正确组织或团队非常重要:

类别
系统和管理日志 基础设施运营
应用程序日志 应用操作

如果组织属于更大的组织,这些类别可能过于宽泛。 将他们细分为更具体的所有者团队:

类别
Docker引擎日志 基础设施运营
基础设施服务 基础设施运营
UCP和DTR日志 UCP / DTR操作
应用程序A日志 应用程序A操作
应用程序B日志 应用程序B操作

一些组织不区分基础架构和应用程序操作,因此他们可能会将这两个类别组合在一起,并由一个操作团队拥有它们。

类别
系统和管理日志 基础设施运营
应用程序日志 基础设施运营

选择合适的模型以明确定义每种日志类型的适当所有权,从而减少平均解决时间(MTTR)。 一旦确定了日志类型的组织所有权,现在应该开始调查正确的日志记录解决方案以进行部署。

收集日志记录基础设施

Docker可以轻松地与现有的日志工具和解决方案集成。 日志记录生态系统中的大多数主要日志记录工具都开发了Docker日志记录或提供了适当的文档来与Docker集成。

选择日志记录解决方案:

  1. 允许实施前一部分定义的组织所有权模式。 例如,一些组织可能会选择将所有日志发送到单个日志记录基础架构,然后为功能团队提供正确的访问级别。
  2. 该组织最熟悉! 这是必须的!
  3. 有Docker集成:预先配置的仪表板,稳定的Docker插件,正确的文档等。

Docker企业版日志

在Docker企业版中,为了历史和系统维护的目的,存储所有容器日志是一个不错的主意。 建议您以可转位方式收集某些容器的输出,主要是出于策略原因并快速了解集群事件。 在下面的章节中,我们将分解一些可能对组织有用的Docker EE组件和某些日志。

UCP

容器名称 日志中的信息
ucp-controller UCP API日志,用户和登录
UCP-AUTH-API UCP和DTR使用的身份和身份验证集中服务
ucp-auth-store 存储认证配置以及用户,组织和团队的数据
ucp-auth-worker 执行预定的LDAP同步并清除认证和授权数据
ucp-client-root-ca 证书颁发机构签署客户端软件包
ucp-cluster-root-ca 证书颁发机构签署客户端软件包
ucp-metrics 用于指标收集
ucp-kv etcd服务用于存储UCP配置
ucp-proxy TLS代理,允许从本地Docker引擎到UCP组件的安全访问
ucp-swarm-manager Docker Swarm的管理容器(经典)提供向后兼容性

注:

  1. ucp-controller - 此容器记录群集的所有登录尝试和一般用法。 出于审计目的,这包含集群日志记录使用方面最重要的日志。
  2. ucp-kv - 这个容器可以很好地监视以确保群集上的法定数量不会丢失。 如果法定人数丢失,最好设置警报。

DTR

名称 日志中的信息
dtr-api- 执行DTR业务逻辑并提供DTR Web应用程序和API
dtr-garant- 管理DTR认证
dtr-jobrunner- 在后台运行清理作业
dtr-nautilusstore- 存储安全扫描数据
dtr-nginx- 接收HTTP和HTTPS请求并将它们代理到其他DTR组件,默认情况下监听主机的端口80和443
dtr-notary-server- 接收,验证和提供内容信任元数据,并在推送或拉入启用Content Trust的DTR时查阅
dtr-notary-signer- 为内容信任元数据执行服务器端时间戳和快照签名
dtr-registry- 实现用于拖拽Docker图像的功能,还处理图像的存储方式
dtr-rethinkdb- 将持久性存储库元数据存储在数据库中

一些值得注意的日志可能在以下设置正则表达式:

  1. dtr-registry- - 解析这个容器将显示客户端IP,用户以及群集的一般用法。
  2. dtr-nginx- - 此容器将所有推送,拉出和API调用记录到集群。
  3. dtr-rethinkdb- - 此容器中的日志包含有关RethinkDB的法定状态的信息。 这是很好的监控和法定人数的任何损失提醒。

HTTP路由网格

默认情况下,HTTP路由网格不会将任何请求记录到STDOUT 要从HRM登录,请运行以下命令:

docker service update --env-add DEBUG=1 ucp-hrm

日志将从HTTP路由网格输出。 如果在引擎级别配置日志驱动程序,则日志输出将遵循引擎级别的配置。

应用程序日志驱动

Docker有几个可用的日志驱动程序,可用于管理应用程序日志。 查看Docker docs以获取完整列表以及有关如何使用它们的详细信息。

作为一般规则,如果您已经拥有日志记录基础架构,那么您应该使用该现有基础架构的日志记录驱动程序。 如果您没有现有的测井系统,则有几个值得强调的优点和缺点。

驱动 优点 缺点
没有 超安全,因为没有任何记录 更难解决没有日志的问题
JSON文件 默认情况下,docker logs可以使用它,支持标签 日志驻留在本地并且不聚合,如果没有限制,日志可以填充本地磁盘
系统日志 大多数机器都带有系统日志,只有支持加密日志传送的TLS的驱动程序支持标签 需要设置为高可用性(HA),否则在容器启动时如果不可用,可能会出现问题
journald docker logs也适用于这个驱动程序,因为它在本地进行日志记录 - 日志聚合器可以在不受影响的情况下关闭,这还收集Docker守护程序日志 由于日志日志采用二进制格式,因此需要采取额外的步骤将它们发送到日志采集器,无需标签支持
GELF 默认情况下提供可索引字段(容器ID,主机,容器名称等),标签支持 仅支持UDP协议,不支持docker logs
fluentd 默认提供container_namecontainer_id字段,fluentd支持多个输出, 没有docker日志支持本地日志
awslogs 使用亚马逊网络服务时易于集成,维护的基础设施更少,标签支持 对于混合云配置或内部部署安装而言,不是最理想的解决方案,不支持docker logs
Splunk的 与Splunk轻松集成,支持TLS,高度可配置,标签支持和其他指标 Splunk需要具备高可用性或容器启动时可能出现的问题,无需支持docker logs
etwlogs 用于登录Windows的通用框架,默认可索引值 只能在Windows上运行,这些日志必须从Windows机器运送到具有不同实用程序的日志聚合器
gcplogs 与Google Compute简单集成,维护的基础设施更少,标签支持 对于混合云配置或内部部署安装而言,不是最理想的解决方案,不支持docker logs

应用程序日志驱动注意事项

选择应用程序日志驱动程序时请考虑以下事项

  • 如果日志数据高度敏感,那么syslogsplunk是很好的选择,因为它们可以配置为使用TLS传输日志。
  • journald日志驱动程序非常适合保留docker日志的使用情况以及日志记录Docker守护程序日志。 此驱动程序可以同时更轻松地排除故障并记录可移植性。 该驱动程序的另一个优点是日志将首先在本地写入,从而减少对日志记录基础结构的依赖。
  • If the Docker EE cluster exist solely on a single cloud provider, then awslogs or gcplogs can be used.
  • 如果有现有的Splunk安装,则使用splunk日志驱动程序。
  • 如果在可以存储日志的环境中存在NoSQL数据库,那么gelffluentd日志驱动程序是一个不错的选择。
  • 对于开发或测试环境,使用json-filejournald可能对查看日志流而非索引和搜索日志更有用。 (如果使用json-file,则考虑传递max-sizemax-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日志驱动程序的示例中,标记字段设置了收集日志时可以搜索和索引的其他数据。 请参阅每个日志记录驱动程序的文档,以查看可以从日志驱动程序设置哪些附加字段。

使用/etc/docker/daemon.json文件设置日志将以每个节点为基础设置默认日志记录行为。 这可以在每个服务或每个容器级别上覆盖。 覆盖默认日志记录行为对于故障排除可能很有用,因此可以实时查看日志。

如果在daemon.json文件配置为使用gelf日志驱动程序的系统上创建服务,则所有容器日志将运行该主机将转到设置gelf-address配置的位置。

如果不同的日志记录驱动程序是首选的,例如从容器的stdout查看日志流,则可以覆盖默认的日志记录行为ad-hoc。

docker service create \
      -–log-driver json-file --log-opt max-size=10m \
      nginx:alpine

然后,这可以与Docker服务日志结合使用,以更轻松地识别服务问题。

Docker服务日志

docker service logs was introduced in version 17.05 of and version 17.06 of Docker EE. 当服务有多个副本任务时,它提供多路复用的日志流。 通过输入docker服务日志&lt; service_id&gt;,日志将在第一列中显示始发任务名称,然后在右侧列中显示每个副本的实时日志。 例如:

$ 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设置

有关如何在Docker群集上将日志发送到ELK的信息,请参阅swarm-elk存储库 该回购包含一个Docker Compose文件,用于设置完整的ELK堆栈。 对于使用ELK进行Docker日志记录实验来说,存储库是一个很好的起点,但在以生产方式使用之前,还要考虑高可用性和排队系统。

Splunk设置

Splunk是另一种流行的日志记录工具。 要设置Splunk,请遵循使用此swarm-splunk存储库中可用的Docker Compose文件的步骤。

每个Splunk转发器连接到本地Docker套接字,因此它不需要在守护程序级别进行额外的日志驱动程序配置。 连接到本地套接字还允许Splunk除了日志之外还提取Docker容器统计信息。

现代化传统应用

没有理由认为使用容器进行日志记录仅适用于现代应用程序。 可以对传统应用程序进行现代化改造,并且在不改变任何应用程序代码的情况下仍具有现代化日志记录的额外优势

理想情况下,应用程序会登录到stdout/stderr,并且Docker将这些日志发送到配置的日志记录目标。 有时某些应用程序被配置为登录到多个位置。 如何捕获这些日志而无需更改任何应用程序源代码?

可以创建一个Docker卷(或多个卷)指向这些日志文件驻留在应用程序中的位置。 通过利用Docker模板,可以为每个卷添加服务任务ID(一个整数)。 如果多个服务任务在同一主机上运行,​​则在卷名上放置后缀可防止发生任何与日志记录相关的冲突。 需要创建一个全局服务来运行带目录通配符支持的日志代理。 最后,可以通过将文件的源目录转换为索引值的日志实用程序来设置附加的正则表达式。

以下示例显示了如何使用官方的Tomcat图像完成此操作。 正式的Tomcat镜像会在/ usr / local / tomcat / logs中记录多个文件,这与大多数Java应用程序所做的很相似。 在该路径中,诸如catalina.2017-07-06.loghost-manager.2017-07-06.loglocalhost.2017- 07-06.loglocalhost_access_log.2017-07-06.txtmanager.2017-07-06.log可以找到。

  1. 为挂载/ var / lib / docker / volumes:/ logs / volumes的日志工具创建全局服务。

  2. 为使用类似于此通用示例的规则记录的日志记录代理创建日志记录规则:“/ log / volumes / * / _ data / * .log”

  3. 在卷上使用基于走向的模板启动服务:

    启动服务时,请使用以下参数:

    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.oro7h0e5yow69p9yumaetor3lprod-tomcat.2.ez0jpuqe2mkl6ppqnuffxqagl

  4. 只要日志记录代理支持通配符并通过检查inode(而不是文件)来处理任何日志轮转,那么应该收集日志。

  5. 如果应用程序记录到多个位置,则尝试将日志符号链接到单个目录或向该卷添加描述性名称。 如果描述性名称被添加到卷名称中,则需要更新任何类型的提取以适应该更改。 (即用grok

  6. 大多数记录器应该收集文件路径以及日志内容。 通过将日志文件所在的卷转换为可索引字段,可以从这些类型的应用程序中搜索和聚合信息。 以下是一个使用grok模式的示例,并创建两个新的可索引字段CONTAINER_NAMEFILENAME

    match => { "path" => "/log/volumes/%{DATA:CONTAINER_NAME}/_data/%{GREEDYDATA:FILE_NAME}" }
    
  7. CONTAINER_NAME将与容器中的stdout流的输出匹配,从而可以轻松地根据容器的日志进行过滤。

有关工作示例的更多信息可以在swarm-elk repo中找到。

Windows日志记录

ETW日志记录驱动程序将容器日志转发为ETW事件。 ETW代表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在日志记录方面提供了很多选项,在采用该平台时有一个日志记录策略会很有帮助。 对于大多数系统,将日志数据留在主机上是不够的。 能够进行索引,搜索并拥有自助服务平台,可为运营商和开发人员带来更流畅的体验。