3. 日志采集层设计

日志采集层是集中运维平台的数据入口,它决定了日志能否被完整、及时、低损耗地送往后端存储与检索系统。很多平台在建设初期只关注 Elasticsearch 的索引和 Kibana 的展示,却忽略了采集层的资源占用、背压处理和格式解析能力,最终出现日志丢失、字段错乱、节点被采集器拖垮等问题。本节围绕 Filebeat、Logstash、Fluentd 三类主流采集器,从定位、能力、资源特征到部署拓扑逐层展开,并给出可落地的选型依据。

三类采集器的定位差异

Filebeat 是 Elastic 官方推出的轻量级日志采集器,使用 Go 编写,核心职责是“读取文件、按行切分、发送事件”。它内置了背压感知、文件状态记录(registry)、多行合并和少量处理器(processor),但几乎不做复杂解析。它的优势是资源占用低,单实例内存通常在几十 MB 量级,适合部署在每台业务服务器上作为“第一跳”采集代理。

Logstash 是重量级的日志管道工具,基于 JVM,插件生态极其丰富。它擅长做字段解析、条件分支、多源输入、多目标输出,例如用 grok 解析 Nginx 访问日志、用 mutate 做字段重命名、用 date 插件统一时间戳。代价是资源消耗高,JVM 启动和运行通常需要数百 MB 到数 GB 内存,因此不适合直接铺满所有业务机。

Fluentd 是 CNCF 项目,使用 Ruby 编写(部分核心用 C 优化),以“统一日志层”为设计目标。它通过 plugin 体系支持数百种输入输出,配置采用标签路由(tag + match),在 Kubernetes 和云原生环境中使用广泛。它的资源占用介于 Filebeat 与 Logstash 之间,结构化路由能力突出,但 grok 类正则解析生态不如 Logstash 成熟。

采集层三类组件能力与部署位置对比 业务服务器(边缘节点) Filebeat 轻量 · 低内存 · 文件读取 Fluent Bit / Fluentd 标签路由 · 云原生友好 Logstash(不推荐直铺) JVM 高内存 · 解析强 采集对象 应用日志 / Nginx / 系统日志 容器 stdout / 文件轮转 汇聚/解析层(可选) Logstash 集群 grok 解析 · 字段清洗 条件分支 · 多路输出 Kafka 缓冲对接 消息缓冲(Kafka) 削峰填谷 · 解耦采集与写入 多消费者 · 重放能力 Topic 按业务划分 背压与限流 队列满 → 暂停读取 registry 记录偏移量 避免日志丢失与重复 存储与检索层 Elasticsearch 索引 · 分片 · 副本 ILM 生命周期管理 Kibana / 查询服务 可视化 · 检索 · 告警 按字段过滤与聚合 写入侧关键约束 批量 bulk 写入 索引模板与 mapping 避免字段爆炸 控制单条日志大小 Beats 协议 forward / http bulk 写入 查询请求 背压反馈

选型依据:从四个维度判断

第一,看部署位置。业务服务器数量多、资源紧张时,优先选择 Filebeat 或 Fluent Bit 作为边缘采集器;如果业务机本身资源充足且需要就地解析,也可以直接部署 Logstash,但通常不推荐。第二,看解析复杂度。日志格式固定、字段简单时,Filebeat 的 processor 或 Fluentd 的 filter 足够;如果存在大量非结构化文本、需要 grok 正则、多行堆栈合并、条件路由,Logstash 的插件生态更省事。第三,看生态与团队技能。已经使用 Elastic 全家桶的团队,Filebeat + Logstash + Elasticsearch 的链路最顺;Kubernetes 环境则 Fluent Bit/Fluentd 与容器日志、标签体系结合更自然。第四,看吞吐与可靠性要求。高吞吐场景应引入 Kafka 作为缓冲,采集器只负责“可靠投递”,解析和写入由下游消费者完成,避免采集器因后端抖动而阻塞业务。

典型部署拓扑

常见拓扑有三种。第一种是“直连型”:Filebeat 直接输出到 Elasticsearch,链路短、延迟低,适合日志量不大、字段简单的场景,但缺少缓冲,后端故障时容易触发背压。第二种是“汇聚型”:Filebeat 发送到 Logstash 集群,由 Logstash 统一解析后写入 Elasticsearch,适合需要复杂解析和多路输出的场景,但 Logstash 集群需要独立扩容和监控。第三种是“缓冲型”:Filebeat → Kafka → Logstash/消费者 → Elasticsearch,采集与解析解耦,Kafka 承担削峰和重放,适合大规模、多业务线、对可靠性要求高的平台。实际生产中,第三种拓扑最为常见,也是本课程后续平台开发的主线。

关键配置示例

以 Filebeat 采集 Nginx 访问日志并发送到 Kafka 为例,核心配置如下(示例参数,需按实际环境调整):

filebeat.inputs:
- type: filestream
  id: nginx-access
  paths:
    - /var/log/nginx/access.log
  fields:
    service: nginx
    env: prod
  fields_under_root: true
  parsers:
    - ndjson:
        target: ""
        add_error_key: true

output.kafka:
  hosts: ["kafka1:9092", "kafka2:9092", "kafka3:9092"]
  topic: "logs-nginx"
  partition.round_robin:
    reachable_only: true
  required_acks: 1
  compression: gzip
  max_message_bytes: 1000000

processors:
  - add_host_metadata: ~
  - add_cloud_metadata: ~

这段配置中,filestream 输入负责读取文件并记录偏移量,fields 为事件打上业务和环境标签,output.kafka 将事件批量写入 Kafka。required_acks: 1 表示 leader 写入成功即返回,兼顾吞吐与可靠性;compression: gzip 降低网络带宽;max_message_bytes 控制单条消息上限,避免超大日志阻塞管道。部署后应观察 Filebeat 的 harvester 数量、Kafka 的写入延迟和 topic 堆积量,判断采集是否健康。

选型时不要只看“功能最强”,而要看“链路最稳”。采集器是日志平台的第一道关口,它的稳定性直接决定后续检索和告警的可信度。边缘节点优先轻量,复杂解析尽量后移,缓冲层按需引入。

部署时的常见判断点

判断采集是否正常,可以看三个信号:一是 Filebeat 日志中是否出现 Harvester started 和 Non-zero metrics,说明文件被正确读取;二是 Kafka topic 的 messages in per second 是否与业务日志产生速率大致匹配;三是 Elasticsearch 索引的文档数是否持续增长且没有大量 mapper_parsing_exception。如果出现采集器内存持续上涨,优先检查多行合并配置和 registry 文件大小;如果出现日志重复,检查 Kafka 消费端是否关闭了自动提交或 Filebeat 是否被重复启动。把这些判断点纳入日常巡检,采集层才能真正成为平台可靠的数据底座。