fluent bit 不能直接采集 go 应用 stdout,因其 input: tail 默认只监控文件,而容器运行时将 stdout 转为动态路径日志文件,硬编码易漏日志或权限失败;应优先让 go 应用写结构化 json 日志到明确路径文件,再由 fluent bit tail 读取。

Fluent Bit 为什么不能直接收 Go 应用 stdout
Go 程序默认把日志打到 os.Stdout 和 os.Stderr,但 Fluent Bit 的 input: tail 默认只监控文件,不抓容器 stdout —— 容器运行时(如 Docker 或 containerd)会把 stdout 转成日志文件,路径取决于 runtime 配置,不是固定值。硬写 /var/log/containers/*.log 很容易漏日志或权限失败。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 优先让 Go 应用把日志写入文件(比如
app.log),再用 Fluent Bit 的tail输入插件读取,路径明确、权限可控 - 如果必须走 stdout,在 Kubernetes 中要确认 CRI 日志路径(
containerd通常是/var/log/pods/*/*/*.log,docker是/var/lib/docker/containers/*/),且 Fluent Bit Pod 需挂载对应宿主机目录 - 避免用
input: exec调journalctl,Go 应用若没走 systemd-journald,就根本不会进 journal
Go 日志格式怎么配才不被 Fluent Bit 解析丢字段
Fluent Bit 的 parser 插件对日志格式很敏感:默认的 regex 解析器一旦匹配失败,整条日志就变成单个 log 字段,时间戳、level、msg 全挤在一起,后续过滤和路由全失效。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- Go 应用输出结构化日志时,**强制用 JSON 行格式(JSON Lines)**,每行一个合法 JSON 对象,例如:
{"level":"info","ts":"2024-04-10T12:34:56Z","msg":"request completed","status":200} - Fluent Bit 配置里用
Parser json,别用regex;同时确保Key_Name log(默认值)与实际字段名一致 - 如果用第三方库如
zerolog或zap,关掉 color、stacktrace 等非 JSON 输出选项,否则解析会中断 - 测试解析是否生效:在 Fluent Bit 启动时加
-v参数,看日志里有没有[filter] parsed keys: level, ts, msg这类提示
Fluent Bit + Go 在 Kubernetes 里怎么避免日志重复
Kubernetes 环境下日志重复是高频问题:Go 应用写文件 → Fluent Bit tail → 输出到 ES;同时 kubelet 又把同一份文件软链进 /var/log/pods/ → Fluent Bit 再次 tail,结果一条日志发两遍。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- Fluent Bit 的
tail输入必须设Path_Key filename,并在filter阶段用grep或lua过滤掉/var/log/pods/下的重复路径 - Go 应用日志文件路径避开
/var/log/pods/和/var/log/containers/,比如写到/app/logs/app.log,然后只挂载该目录到 Fluent Bit - 禁用 Fluent Bit 的
db(数据库)功能时,注意重启后会重读全部日志——用DB /fluent-bit/tail-db.db记录 offset,否则每次启动都刷历史
Go 应用要不要自己集成 Fluent Bit 的 HTTP 接口
Fluent Bit 提供了 http 输入插件,监听 :2020 端口接收 JSON 日志,看起来 Go 应用可以直接 http.Post 发送。但实际不推荐:HTTP 增加延迟、失败无重试、应用需维护连接池、还绕过了容器日志生命周期管理。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 除非有强实时性要求(比如审计日志秒级入库),否则坚持「应用写文件 → Fluent Bit tail」模式,更稳定、可观测、易调试
- 如果真要用 HTTP 方式,Go 侧必须实现带 backoff 的重试(
net/http默认无重试),并捕获connection refused、timeout等错误降级为本地文件写入 - Fluent Bit 的
http输入默认不校验 Content-Type,Go 发送时务必设Content-Type: application/json,否则解析可能失败
最麻烦的其实是时间戳处理:Go 用 time.Now().UTC() 写日志,Fluent Bit 却可能按本地时区解析。不统一的话,ES 里查“最近一小时”永远少半小时。










