在 亚马逊云科技Logs 容器日志驱动程序中使用非阻塞模式防止日志丢失

作者:韦斯利·佩蒂特 | 202

简介

为了提高可观察性和故障排除,建议将容器日志从计算平台运送到运行在集中式日志服务器上的容器。在现实世界中,日志服务器有时可能无法访问或无法接受日志。在为日志服务器故障进行设计时,需要在架构上进行权衡。服务所有者必须从以下注意事项中进行选择:

  1. 应用程序是否应该停止响应流量(或执行工作)并等待集中式日志服务器恢复?(即,准确的审核日志的优先级是否高于服务可用性?)
  2. 应用程序是否应该在缓冲日志的同时继续提供流量,希望日志服务器在缓冲区满之前恢复。在极少数情况下,当日志目标不可用时,您是否应该接受丢失日志的风险?

在容器 日志驱动程序 中 ,这种权衡是通过首先考虑配置参数 阻塞 非阻塞 来实现 的。在 亚马逊云科技 帖子《 选择容器日志选项以避免背压 》中 ,Rob Charlton 探讨了这种权衡,并解释了如何测试应用程序在 AW SLogs 容器日志驱动程序的默认 阻塞 模式下的行为。

在这篇文章中,我们将深入探讨 非阻塞问题 ,并展示使用 亚马逊云科技Logs 日志驱动程序进行日志丢失测试的结果。

解决方案概述

awsLogs 驱动程序模式

在亚马逊弹性容器服务( Amazon ECS )中, 亚马逊云科技Logs 日志驱动程序 从容器的标准输出和标准输出中 捕获日志,然后通过 putLogEvents API 将其上传到亚马逊 云观 日志。 日志驱动程序支持 模式设置 ,可以按如下方式配置:

  • 阻止( 默认 ):当无法立即将日志发送到 Amazon CloudWatch 时,从容器代码调用 写入 stdout stderr 将阻止并停止代码的执行。应用程序中的日志线程将阻塞,这可能会阻止应用程序运行并导致运行状况检查失败和任务终止。如果无法创建所需的日志组或日志流,则容器启动会失败。
  • 非阻塞:当无法立即将日志发送到 Amazon CloudWatch 时,它们将存储在配置了最大缓冲区大小设置的内存缓冲区中。当缓冲区填满时,日志就会丢失。从容器代码中写入 stdout 或 stderr 的调用 不会阻塞 并将立即返回。使用亚马逊弹性计算云 (Ama zon EC2 ) 上的 Amazon ECS, 如果无法创建所需的日志组或日志流,容器 启动不会失败 。使用 亚马逊云科技 Fargate 上的 A mazon ECS , 如果无论配置什么模式,都无法创建日志组或日志流,则 容器启动总是会失败

Diagram which shows an application writing logs to the stdout pipe, which are sent to CloudWatch Logs by the AWSLogs driver. CloudWatch Logs is unreachable, consequently nothing moves through the stdout pipe and the application blocks.

我应该切换到非默认的非阻塞模式吗?

由于默认阻塞模式存在应用程序可用性风险,服务所有者可以考虑改为切换到非阻塞模式。这就提出了以下问题:

  • 你应该如何选择最大缓冲区大小?默认 1 MB 大小能否防止日志丢失?
  • 非阻塞模式会导致高速登录的应用程序丢失日志吗?

为了回答这些问题,亚马逊云科技 团队在非阻塞模式下对 亚马逊云科技Logs 驱动程序进行了大规模的日志提取测试。

建议使用什么值作为最大缓冲区大小?

如果您选择非阻塞模式,则本次测试中推荐的 Amazon ECS 任务定义设置如下:

"logConfiguration": {
    "logDriver": "awslogs",
    "options": {
        "mode": "non-blocking",
        "max-buffer-size": "25m",
    }
}

哪些变量决定缓冲区应该有多大?

影响所需的最大缓冲区大小的主要变量是应用程序输出数据的频率和日志吞吐量。

使用 CloudWatch 指标中的 In comingBytes 指标来跟踪日志组的摄取率 。 假设所有容器的发送速率大致相同,则可以将日志组摄取速率除以容器数量。然后,您将获得 每个单独集装箱的 费率

建议高估每个容器的日志吞吐量;日志输出偶尔可能会激增,尤其是在事件发生期间。如果可能,请在负载测试或最近的事件中计算您的吞吐量。使用一分钟或更短时间间隔内的峰值日志输出速率来考虑吞吐量的激增。

测试发现了什么?

请注意,本文中讨论的结果并不能保证性能。我们只是在分享我们运行的测试结果。

以下是中央日志服务器可用且运行状况良好的主要发现。

  • 最大缓冲区大小>= 4MB 在容器的日志输出速率小于 2 Mb/s 时不会显示任何日志丢失。
  • 最大缓冲区大小 >= 25 MB 在容器的日志输出速率小于 5MB/s 时不会显示任何日志丢失。
  • 超过 6 Mb/s,亚马逊云科技Logs 驱动程序的性能难以预测和稳定。例如,在缓冲区为 100 MB 和 7 Mb/s 时出现异常值测试失败。如果您以 6+ Mb/s(持续或突发)的速度登录,则可能无法防止偶尔丢失日志。
  • Amazon EC2 上的 Amazon ECS 启动类型与 亚马逊云科技 Fargate 启动类型的结果相似。

本文档提供了测试结果的简单摘要。完整的基准测试结果、分析和按启动类型和日志大小细分的数据可以在 GitHub 上找到 。

测试是如何进行的?

用于基准测试的代码可以在 GitHub 上找到。亚马逊 EC2 测试是在 Docker 版本 v 20.10.25 上进行的。亚马逊云科技 Fargate 测试是在 平台版本 1.4 上进行的。

每次运行的日志丢失测试都是一个 Amazon ECS 任务,使用 亚马逊云科技Logs 驱动程序向亚马逊 CloudWatch Logs 发送 1 GB 的日志数据。然后,该任务会查询 Amazon CloudWatch Logs 以找回所有日志事件,并检查收到了多少日志事件。每条日志消息都有一个唯一的 ID,它是一个可预测的序列号。测试使用 1 KB 和 250 KB 大小的单个日志消息运行。

执行了数千次测试,以获取足够的数据,以便对日志丢失进行有意义的统计分析。

我怎么知道缓冲区是否已满并且日志丢失?

不幸的是,使用 亚马逊云科技Logs 日志驱动程序,无法看到非阻塞模式缓冲区丢失的日志。发生丢失时,Docker 守护程序不会发出任何日志语句或指标。请对 GitHub 上的日志丢失指标提案发表评论 。

缓冲区大小如何影响我的应用程序的可用内存?

最大缓冲区大小设置控制 go 切片 中消息的 字节大小。 它不直接限制内存的使用,因为 Go 是一种垃圾收集语言。一个测试套件指出,平均而言,队列的实际大小相当小,通常小于 500 KB。在延迟或日志吞吐量增加期间,缓冲区大小偶尔会攀升到极限。这意味着,由于 Go 垃圾回收,缓冲区使用的内存每时每刻都有很大的不同,实际内存使用量可能会超过配置的大小。

计算平台会影响缓冲区大小吗?

在测试中,我们发现结果与在亚马逊 EC2 和 亚马逊云科技 Fargate 上启动的 Amazon ECS 任务相似。

跨区域发送日志时,非阻塞模式安全吗?

由于与 CloudWatch 的连接延迟较低,因此在向测试任务所在区域的亚马逊 CloudWatch API 发送日志时,亚马逊云科技Logs 驱动程序可以持续以更高的速率上传。跨区域日志上传不太可靠。此外,它违反了区域隔离的最佳实践。跨区域日志推送也会产生更高的网络成本。

测试结果

请注意,本文中讨论的结果并不能保证性能。我们只是在分享我们运行的测试结果。请访问 GitHub 查看按计算平台(亚马逊云科技 Fargate 与 Amazon EC2)和日志消息大小等维度细分的完整数据表。

区域内测试运行摘要

以下是大约 17,000 次区域内测试运行的热图摘要。阴影框内的注释百分比是最差测试运行中的日志丢失百分比。红色阴影越深,观察到的对数损失就越多。请注意,日志输出速率小于 2 Mb/s 的所有测试运行均未丢失日志。

Heat map image which summarizes the test results. The heat map shows that log loss is very likely with a less than 12 MB buffer and more than 2 MB/s log output rate from the container.

跨区域测试运行摘要

任务在 us-west-2 中运行,上传到美国东部的 Amazon CloudWatch。

结果表明,跨区域日志上传的可靠性较低,需要更大的缓冲区大小才能防止日志丢失。

Heat map image showing test results for cross-region test runs. The heat map shows log loss for most combinations of buffer size and log output rate from the container. A 40MB or larger buffer and less than 2 MB/s log output rate from the container is required for low risk of log loss.

结论

在这篇文章中,你学到了:

  • 在应用程序可用性和日志丢失之间进行权衡,容器日志驱动程序阻塞和非阻塞。
  • 在不同的最大缓冲区大小值下,亚马逊云科技Logs 驱动程序在非阻塞模式下的性能。
  • 不建议跨区域上传日志,如果使用非阻塞,则丢失日志的风险要高得多。
  • 如何找到自己的每个容器的日志输出速率。
  • 使用非阻塞状态的 亚马逊云科技Logs 驱动程序无法监控日志丢失。

在考虑应用程序可用性和日志丢失之间的权衡时,你应该决定你的用例是需要阻塞模式还是非阻塞模式。如果您选择了应用程序可用性方面的权衡,那么您应该选择非阻塞模式下的 亚马逊云科技Logs 驱动程序还是其他日志收集解决方案?大多数其他日志收集解决方案,例如 带有 FireLens 的 Fluen t B it ,仅支持将 日志 存储在有限的缓冲区中,但不会阻碍应用程序 端的权衡。但是,其他解决方案可能更易于 调整 监控 ,以防止日志丢失。如果您在非阻塞模式下选择 亚马逊云科技Logs 驱动程序,那么考虑到每个容器的日志输出速率,最大缓冲区大小的值适合您的风险承受能力?我们建议仔细查看 GitHub 上的完整测试结果 。鉴于结果,我们建议将最大缓冲区大小设置为25m;并确保所有日志上传都在区域内,因为跨区域日志推送非常不可靠。

Wesley Pettit

韦斯利·佩蒂特·

韦斯利·佩蒂特是亚马逊 ECS 的软件工程师,专注于可观测性。他是 CNCF 日志路由项目 fluent/fluent-bit 的维护者。


*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您发展海外业务和/或了解行业前沿技术选择推荐该服务。