背压、缓冲区和日志 Sidecar

发布: (2026年2月15日 GMT+8 15:32)
9 分钟阅读
原文: Dev.to

Source: Dev.to

(未提供要翻译的正文内容。如果您把需要翻译的文本粘贴在这里,我可以为您将其翻译成简体中文。)

9 PM – 一切的起点崩溃

我正随意地在 YouTube 上浏览时,Slack 的一条通知打破了寂静:我们的日志 sidecar 已崩溃 – 退出码 137

乍一看,这似乎是一个简单的背压问题。 “增大缓冲区,或许调一下限制,然后重新部署。”

事实并非如此。

这次崩溃把我带入了 Fluent Bit 的块生命周期、文件系统缓冲,以及一个认识:即使是看似“简单”的日志 sidecar,也会表现得像一个小型分布式系统——伴随而来的全部权衡。

在本文中,我想分享这段旅程中的经验和教训。

我们的设置

  • Fluent Bit 作为 sidecar 与每个应用容器一起运行。
  • 它的职责很简单:收集来自应用程序的日志,进行处理,并将其转发到外部日志平台。

为什么 Fluent  Bit 会 OOM

大多数 OOM 情况都归结为 管道内部的不平衡

原因影响
输出慢 – 下游系统滞后,而输入持续摄取日志反压累积 → 内存使用上升
过滤或处理负载重 – 过滤器暂时增加内存占用同上
摄取无限制 vs 缓冲区限制 – 日志量超过配置的内存限制Sidecar 成为瓶颈

可见性问题

关于容器突发崩溃的棘手之处在于缺乏可见性。当 sidecar 被杀死时,我们失去了调试所需的关键信号。我们的容器级内存图表看起来很平稳,这让崩溃更加令人困惑。

后来我们意识到,自己并没有 实时 观察内存。

我们最终看到峰值的方式

  1. 启用了 Memory Input Plugin
  2. 通过 Fluent Bit 日志检查内部指标。

就在这时我们终于发现——出现了外部监控看不到的突发内存峰值。

实验时间线

第一次迭代 – “限制内存能解决吗?”

# Example: cap memory per input
Mem_Buf_Limit 5M
  • 我们的预期: 限制内存 → 防止 OOM。
  • 实际情况:
    • 当达到限制时,输入会被暂停
    • 应用程序没有暂停;它仍然持续输出日志。
    • 由于我们使用的是forward 输入插件(没有上游持久化),输入被暂停意味着日志丢失

结果:内存压力得到控制,但可靠性受到了影响。

第二次迭代 – “磁盘缓冲能拯救我们吗?”

# Enable filesystem buffering
storage.type filesystem
  • 目标:将压力从 RAM 转移到磁盘,同时保持持久性。
  • 结果:sidecar 仍然因 OOM 错误崩溃

仅靠磁盘缓冲不足以解决问题。

第三次迭代 – “内存还流向哪里?”

我们意识到 输入并不是唯一的 RAM 消耗者——过滤器和输出同样会占用内存。

组件内存影响
过滤器 / 解析器(例如 JSON、Multiline)暂时保存记录;在我们的案例中,JSON 解析器是主要的内存消耗者。
输出可能进行压缩、重试或从磁盘重新加载块。即使使用文件系统缓冲,块在刷新前也必须重新加载到内存中。

我们尝试的措施

  • 增加容器的 CPU 与内存——显而易见,但违背了“轻量 sidecar”的目标。
  • 将部分解析工作下移至下游——降低了解析器的内存压力。
  • 调整输出的 backlog 限制——限制一次性加载到 RAM 的块数量。

系统保持稳定……直到下一次崩溃。

新症状 – 退出码 139(段错误)

[2019/01/09 17:06:01] [error] [plugins/in_forward/forward_fs.c:218 errno=28] No space left on device
[2019/01/09 17:06:01] [error] [in_forward] could not register file into fs_events

容器以 139 退出——出现段错误。
日志显示 errno=28 → “设备上没有剩余空间”。

日志 sidecar 如何耗尽磁盘

  • ECS Fargate 为每个任务提供 20 GB 的临时存储——看似足够用于缓冲。
  • 输入摄取指标输出刷新指标 进行对比,出现了明显的模式:摄取速率 ≫ 刷新速率。

实际发生的情况

  1. 内存缓冲区被填满。
  2. 数据块溢写到磁盘。
  3. 输出从磁盘加载块并尝试刷新。
  4. 突然出现摄取峰值,而刷新速率保持不变(或受限)。
  5. 磁盘使用量增长速度超过了排空速度 → 磁盘填满 → ENOSPC → 段错误

只要这种失衡持续足够长的时间,磁盘填满不仅是可能的——而且是必然的。

限流与缓解策略

层级操作
Application- 抽样
- 去重
- 强制执行严格的生产日志级别
Fluent Bit- 限制每个输出的磁盘使用量
- 达到限制时丢弃最旧的块
- 应用 throttle filter 进行突发控制
Operations- 当摄取持续超过处理能力时发出警报
- 增加临时存储(短期缓冲,非永久性解决方案)

要点

  • 内存压力并非唯一问题——磁盘耗尽也可能在相同的不平衡下出现。
  • 日志 sidecar 实际上是一个 小型分布式系统;必须将其管道(输入 → 过滤 → 输出)整体对待。
  • 实时可观测性(内存、磁盘、摄取/刷新速率)对于在失衡导致容器崩溃前捕获问题至关重要。
  • 调整 单一参数(例如 Mem_Buf_Limit)而不考虑下游影响可能导致数据丢失或新的故障。

通过对三个实验的迭代、暴露隐藏的指标,最终加入适当的速率限制和磁盘使用保护,我们将一个不稳定、易崩溃的 sidecar 转变为日志管道中可靠的组件。

观察

  • 物理学。
  • 当你生成数据的速度超过了移动它的速度时,压力会累积。
  • 在我们的案例中——它通过磁盘耗尽而泄漏。
  • 日志是基础设施。它需要防护措施。
  • 如果你不为突发情况设计,突发情况就会决定你的故障。
  • 好奇你会如何不同地处理它。
0 浏览
Back to Blog

相关文章

阅读更多 »