第三章 日志采集与处理:日志标准化、Fluentd/Fluent Bit 部署、日志采集 Pipeline 设计
日志这东西,说起来简单,做起来全是坑。我见过太多团队,业务跑得好好的,一出问题就抓瞎——日志散落在各个服务器上,格式五花八门,想查个东西得 ssh 到每台机器上 grep。嗯,这显然不是云原生该有的样子。
这一章,我们就来聊聊怎么把日志这件事做规范、做自动、做可靠。说白了,就是让日志真正成为可观测性的基石,而不是一堆没人看的垃圾文件。
3.1 日志标准化:从源头解决问题
我个人习惯,在搭建日志体系之前,先定标准。为什么?因为日志采集和处理最头疼的问题,就是格式不统一。你想想看,Java 应用打的是 JSON,Nginx 打的是自定义格式,数据库日志又是另一套——采集端要写一堆解析规则,维护成本极高。
标准化的核心原则:
- 结构化:所有日志必须是 JSON 格式。别再用纯文本了,解析起来太痛苦。
- 字段统一:时间戳、日志级别、服务名、TraceID、消息体,这些字段每个日志都必须有。
- 时间戳规范:统一使用 ISO 8601 格式,带时区信息。比如
2025-01-15T10:30:00.123+08:00。 - 级别明确:只允许 DEBUG、INFO、WARN、ERROR、FATAL 这五个级别,别自己发明。
一个标准日志示例:
{
"timestamp": "2025-01-15T10:30:00.123+08:00",
"level": "ERROR",
"service": "order-service",
"trace_id": "abc123def456",
"span_id": "span001",
"message": "数据库连接超时",
"stack_trace": "com.example.dao.DbException: ...",
"extra": {
"user_id": "9527",
"order_id": "ORD20250115001"
}
}
我在项目中遇到过,有些团队觉得 JSON 日志太大,占用磁盘空间。其实这是个误区。日志压缩后,JSON 和纯文本的体积差距微乎其微。而且,JSON 带来的解析效率和可读性提升,远远超过那点存储成本。
3.2 Fluentd 与 Fluent Bit:选谁?怎么搭?
说到日志采集器,Fluentd 和 Fluent Bit 是绕不开的两个工具。很多人问我:「到底该用哪个?」我的回答是:看场景。
Fluentd 和 Fluent Bit 的对比:
| 特性 | Fluentd | Fluent Bit |
|---|---|---|
| 语言 | Ruby + C | C |
| 内存占用 | ~60MB | ~650KB |
| 插件生态 | 极其丰富(1000+) | 丰富(~150) |
| 吞吐量 | 中等 | 高 |
| 适用场景 | 复杂路由、数据转换 | 边缘采集、轻量部署 |
我个人习惯的部署模式是:Fluent Bit 做采集端,Fluentd 做聚合端。说白了,就是让 Fluent Bit 跑在每台机器或每个 Pod 里,负责轻量采集和简单过滤;然后把数据发给中心的 Fluentd 集群,由 Fluentd 做复杂的路由、转换和输出。
部署建议:
- 在 Kubernetes 中,Fluent Bit 以 DaemonSet 方式部署,每个节点一个 Pod。
- Fluentd 以 Deployment 方式部署,根据日志量调整副本数。
- 两者之间用 Forward 协议通信,支持负载均衡和故障转移。
3.3 日志采集 Pipeline 设计
Pipeline 这个词听起来高大上,其实就是「数据流」。日志从产生到存储,中间经过哪些环节,每个环节做什么事,这就是 Pipeline 要解决的问题。
一个典型的日志 Pipeline 包含四个阶段:
- 采集(Input):从文件、标准输出、系统日志等源头读取日志。
- 解析(Parser):把非结构化日志转成结构化数据。
- 过滤(Filter):丢弃无用日志、添加缺失字段、修改日志级别。
- 输出(Output):写入 Elasticsearch、Kafka、S3 等目标。
我曾经踩过一个坑:把所有日志一股脑全送到 Elasticsearch,结果磁盘直接爆了。后来才意识到,过滤阶段有多重要。你想想看,DEBUG 日志在开发环境有用,到了生产环境就是噪音。所以,Pipeline 里一定要加过滤规则。
一个完整的 Fluent Bit Pipeline 配置示例:
[SERVICE]
flush 1
log_level info
parsers_file parsers.conf
[INPUT]
name tail
path /var/log/containers/*.log
tag kube.*
parser docker
refresh_interval 5
[FILTER]
name grep
match kube.*
regex log ^(?=.*ERROR|.*WARN)
[FILTER]
name modify
match kube.*
add cluster production
rename log message
[OUTPUT]
name forward
match kube.*
host fluentd.observability.svc
port 24224
这个配置做了几件事:
- 从容器日志文件采集,每 5 秒刷新一次。
- 只保留 ERROR 和 WARN 级别的日志(生产环境建议这么做)。
- 添加一个
cluster字段,方便区分环境。 - 把
log字段重命名为message,统一字段名。 - 最后发给 Fluentd 集群做进一步处理。
注意: 过滤规则要谨慎。我曾经见过有人把 INFO 日志全丢了,结果排查问题时发现关键信息就在 INFO 里。建议至少保留 WARN 及以上级别,INFO 级别按需保留。
3.4 避坑指南:日志采集的常见问题
做日志采集这么多年,我总结了几条血泪教训:
- 不要用 hostPath 挂载日志目录:在 Kubernetes 里,用 hostPath 会导致日志采集和 Pod 生命周期耦合。建议用 emptyDir 或者 sidecar 模式。
- 注意日志轮转:应用自己会做日志轮转,Fluent Bit 也要配置好
rotate_wait,防止文件被删了还在读。 - 控制日志速率:有些应用在出错时会疯狂打日志,瞬间把采集器打挂。加个
throttle过滤器,限制每秒最多处理多少条。 - 监控采集器本身:Fluent Bit 挂了怎么办?它的日志也要采集,形成闭环监控。
嗯,这一章的内容差不多就这些。日志标准化是基础,Fluentd/Fluent Bit 是工具,Pipeline 是架构。三者结合起来,才能搭建一个可靠、高效的日志采集体系。下一章,我们会聊聊日志的存储和检索,到时候再细说 Elasticsearch 的那些坑。