上一篇讲完了性能调优的系统方法。这一篇进入演进对比阶段,把 Logstash、Beats 和 Elasticsearch Ingest Pipeline 三者并排放,回答一个工程决策问题:同样是把数据搬进 ES,三种路径在哪里分叉,分叉的依据是什么。

核心问题:轻量采集用 Beats,简单解析下沉到 Ingest Pipeline,复杂转换才留给 Logstash——这条分工逻辑背后的资源、能力和可靠性代价是什么?

本篇的三方现状以 Logstash 9.5.x、Elasticsearch 8.19/9.x 的 ingest 文档、Filebeat 与 Elastic Agent 9.x 为准,数据取自 2026-08。全系列统一的版本前提见第 01 篇。

三者的定位

Elastic Stack 的数据接入层有三个层次,各自定位不同:

1
2
3
4
5
6
7
8
9
10
11
12
数据源

├─▶ [Beats / Elastic Agent] Go 语言,轻量级进程,低资源
│ │ Beats 单一职责;Agent 单进程整合多个采集器
│ │
│ ├─▶ [ES Ingest Pipeline] 运行在 ES 节点内,无独立进程,简单变换
│ │
│ └─▶ [Logstash] JVM 进程,插件生态最大,复杂转换,PQ 可靠性
│ │
│ └─▶ Elasticsearch

└─▶ Elasticsearch(直接写入)

Beats 是采集层:靠近数据源部署,读取文件、采集指标、接收网络数据,把原始数据发往下游。Filebeat、Metricbeat、Packetbeat 各自只做一件事。

Elastic Agent 是同一层的后继形态:它把 Filebeat、Metricbeat 这些采集器合并进单一进程,由 Fleet 集中下发配置,并用 integration 预打包好字段映射、Ingest Pipeline 和仪表板。8.x 之后的新部署里,"边缘采集层"默认指的就是它。在本篇的三个决策维度(资源、变换能力、输出目标)上,Agent 与 Beats 落在同一格,差别在运维模型而非能力上限;它如何改变整张接入图,见第 17 篇。

Ingest Pipeline 是 ES 内部的轻量变换层:当索引文档时,ES 节点可以先把文档交给 pipeline 处理,再写入分片。它没有独立进程、没有磁盘队列,处理能力受 ES 集群节点资源约束。

Logstash 是独立的重量级 ETL 引擎:JVM 进程、持久队列、多输入多输出、条件路由,插件生态在三者里最大(logstash-plugins 组织下有 276 个公开插件仓库,取数 2026-08),也是能力最强、资源消耗最高的一个。

资源对比

三者的资源消耗不在一个量级,但下表里两类内存数字的口径不同,不能直接相除:

组件 运行时 内存口径 典型值 启动时间
Filebeat Go 原生 进程 RSS 数十 MB 量级 < 1 s
Metricbeat Go 原生 进程 RSS 数十 MB 量级 < 1 s
Ingest Pipeline 运行在 ES 节点内 共享 ES JVM 堆 无独立进程 无独立启动
Logstash JVM + JRuby JVM 堆配置 + 堆外 官方建议 heap 4–8 GB,默认 1 GB 秒级到数十秒

Beats 那两行是进程实际驻留内存,Logstash 那行是 JVM 堆的配置值。把两者放进同一个除法会得出"Logstash 比 Filebeat 重几十倍"的错误结论:Logstash 的实际占用要在堆之外再加 metaspace、JRuby 运行时、每条启用 PQ 的管道常驻的 mmap 页(默认页 64 MB,至少 head + tail 两页即 128 MB),以及默认与堆等大的 direct memory。官方 JVM 设置文档给的算例是 10 条启用 PQ 的管道配 4 GB 堆,总内存约 9.4 GB(native 1.4 GB + direct 4 GB + heap 4 GB)。

启动时间同样只能给量级。Logstash 官方文档没有启动耗时基准,实测值随插件数量和 PQ 待恢复数据量变化很大。要拿到自己环境的数字,量 [logstash.runner] 首行日志到 Pipelines running 之间的时间差。

Beats 的低资源消耗让它可以在每台主机上部署,紧贴数据源。Logstash 的堆内加堆外开销决定了它通常作为中心化聚合节点运行,而不是每台机器各跑一个实例。

Beats:边缘采集的设计

Beats 系列各成员的共同特征:

1
2
3
4
5
6
7
8
9
10
11
12
13
Beats 内部结构
┌────────────────────────────────────────────┐
│ Input (harvester) │
│ 读文件 / 采集指标 / 监听网络 │
│ │ │
│ Publisher Queue (内存) │
│ │ │
│ Output │ │
│ ├── Elasticsearch(可带 ingest pipeline)│
│ ├── Logstash │
│ ├── Kafka │
│ └── Redis / 文件 │
└────────────────────────────────────────────┘

Filebeat 的核心机制是 harvester + registry。harvester 读文件,registry 记录每个文件的读取偏移量(inode + offset),实现断点续传。Beats 向下游确认送达后才推进 registry,这是其 at-least-once 的保证机制。

Beats 的处理能力是有限的:只能做极简单的字段添加(add_fields)、事件类型标记(event.type)和少量内置模块提供的字段映射。复杂的正则解析、多字段关联、聚合、跨源路由,超出了 Beats 的设计范围。

Ingest Pipeline:ES 内部的轻量变换

Ingest Pipeline 是 ES 5.0 引入的功能,让文档在被索引前先经过一组 processor 处理:

1
2
3
4
5
6
7
8
9
10
11
12
PUT /_ingest/pipeline/parse-nginx
{
"processors": [
{ "grok": { "field": "message",
"patterns": ["%{COMBINEDAPACHELOG}"] } },
{ "date": { "field": "timestamp",
"formats": ["dd/MMM/yyyy:HH:mm:ss Z"] } },
{ "set": { "field": "event.kind",
"value": "event" } },
{ "remove": { "field": "message" } }
]
}

常用 processor:grokdissectdatesetremoverenamesplitconvertgeoipuser_agentfingerprintenrichreroutescript(Painless)。官方 processor 参考页的措辞是"includes over 40 configurable processors",在 8.19 文档里去重可数出 45 个。

Ingest Pipeline 的关键约束:

  • 没有独立进程:pipeline 在 ES 的 ingest 节点上执行,消耗的是 ES 的 CPU 和内存,重计算会影响索引性能。
  • 没有持久队列:文档在 bulk 请求里进来,处理失败可以配置 on_failure,但没有 Logstash 那样的磁盘队列缓冲。
  • 输出限于当前集群,但集群内的目标可以按内容改:reroute processor 能把文档改写到另一个索引或 data stream。它有两种模式——设 destination 指定静态目标,或不设 destination 进入 data stream 模式,后者只适用于符合 <type>-<dataset>-<namespace> 命名规范的 data stream 且不能改 type。一个要紧的语义:reroute 执行后当前 pipeline 的其余 processor 全部跳过,final pipeline 也跳过,所以一条 pipeline 里最多只会执行一个 reroute,它提供的是互斥的单目标改写,不是多目标扇出。写到另一个 ES 集群、Kafka 或文件,仍然只有 Logstash 能做。
  • 跨文档聚合做不到,跨索引关联可以:每个 pipeline 只处理单个文档,无法在文档之间做聚合;但 enrich processor 按官方描述能"enriches documents with data from another index",从另一个索引取数据补进当前文档。

决策矩阵

1
2
3
4
5
6
7
8
9
10
11
12
场景                                      推荐路径
──────────────────────────────────────────────────────────────────────
纯日志采集,不做任何变换 Beats / Elastic Agent ──▶ ES
轻量解析(一个 grok + date) Beats / Elastic Agent ──▶ ES + Ingest Pipeline
字段补充(geoip、user_agent) Beats / Elastic Agent ──▶ ES + Ingest Pipeline
Elastic 生态内的标准数据源(nginx、k8s…) Elastic Agent integration(预打包 pipeline)
按内容写同一集群内的不同索引/data stream Ingest Pipeline 也可(reroute),Logstash 也可
写不同 ES 集群,或写非 ES 目标 必须 Logstash
写多个输出(ES + Kafka + S3) Logstash
多来源汇总 + 统一字段归一化 Beats / Elastic Agent ──▶ Logstash ──▶ ES
需要 PQ 兜底(数据不可重放的源) Logstash(开启 PQ)
复杂聚合、跨事件关联 Logstash 或 Flink/Spark

一个实用的判断顺序。先问"要同时写几个不同的目标系统":同一集群内换索引,reroute 就够了;要同时写多个集群或多个系统,只有 Logstash 能做。再问"变换有多复杂":超过两个 processor 的链条、有条件分支的,Ingest Pipeline 的可维护性下降,Logstash filter 更适合。最后问"资源预算":每台机器都要跑的场景,只有 Beats 或 Elastic Agent 可接受。

三路径组合:Beats → Logstash → ES

最常见的生产部署是三层叠加:

1
2
3
4
[应用服务器]                [中心处理节点]              [存储]
Filebeat ──┐
Filebeat ──┼──▶ Logstash ──▶ Elasticsearch
Metricbeat─┘ (filter + PQ)

Beats 在每台机器上以极低资源运行,负责文件读取和断点续传;Logstash 作为中心聚合节点,汇总多台机器的日志,做复杂解析和路由;ES 只负责存储和查询。

这种部署把各层的关注点分离:Beats 解决"如何可靠地把文件内容送出来",Logstash 解决"如何把杂乱数据变成结构化文档",ES 解决"如何存储和查询"。

把边缘层换成 Elastic Agent,这张图仍然成立:

1
2
3
4
5
6
[应用服务器]                     [中心处理节点]              [存储]
Elastic Agent ──┐
Elastic Agent ──┼──▶ Logstash ──▶ Elasticsearch
Elastic Agent ──┘ (elastic_agent input
▲ + filter + PQ)
└── Fleet 下发配置

Elastic Agent 的 output 可以指向 Logstash,Logstash 侧用 elastic_agent input 接收——官方插件文档写明它是 beats input 的下一代,两者共用同一份代码。所以引入 Elastic Agent 不等于必须绕开 Logstash:需要 PQ 兜底或多目标路由时,中间这层照样保留。Agent 直连 ES 与经由 Logstash 两条路各自的取舍,见第 17 篇。

Beats 直连 ES 时可以同时指定 Ingest Pipeline,在文档被 ES 接收时做轻量处理。这条路可以省去 Logstash 进程,但代价是处理逻辑分散在 Beats 配置和 ES pipeline 两处,调试成本上升。

模式提炼

本篇只收敛资源分层这一个维度:运行时差异见第 16 篇,把资源、运行时、生态归位置三者合成一条完整选型规则的是第 17 篇。

1
2
3
4
5
6
7
8
9
10
模式:按资源边界分层

- 边缘层(每台机器):用资源消耗极低的工具,只做采集和传输
- 中间层(集中部署):用有能力做复杂变换、有队列缓冲的工具
- 存储层(ES):把简单的字段变换内嵌为 Ingest Pipeline,减少外部进程数

分层依据:
每台机器都要跑 → 内存预算是数十 MB 量级,排除 JVM
只在集中节点跑 → JVM 的堆内加堆外开销可以接受
不想多一个进程 → 能内嵌进 ES 的部分下沉到 Ingest Pipeline

这个模式不局限于 Elastic Stack。AWS 的 Kinesis Firehose(边缘传输)+ Lambda(轻量变换)+ S3/Redshift(存储)是同一个三层结构的云原生版本。

工程迁移表

能力维度 Beats Elastic Agent Ingest Pipeline Logstash
资源占用 极低(Go 原生) 低(单进程整合多采集器) 共享 ES 节点 高(JVM 堆内 + 堆外)
部署位置 每台数据源机器 每台数据源机器 ES 节点内 独立中心节点
配置下发 各机器本地文件 Fleet 集中下发 ES API 本地文件 / 集中管理
字段变换能力 极简(内置模块) integration 预打包 pipeline 40+ processor 最强(插件生态最大 + 完整条件分支)
多输入聚合
多输出路由 否(单一 output) 否(限 Elastic 生态目标) 集群内可改索引(reroute
本地落盘缓冲 可选(queue.disk 否(无 PQ 等价物) 是(PQ + DLQ)
条件路由 有限(if + reroute 是(完整条件语法)
启动开销 可忽略 可忽略 无独立启动 秒级到数十秒

常见误解

误解一:“Beats 只是 Logstash 的简化版”。两者的设计定位不同,不是同一产品的高低配。Beats 是轻量边缘采集器,Logstash 是重量中心处理器,在架构里处于不同的层,通常配合使用而不是互相替代。

误解二:“Ingest Pipeline 可以替代 Logstash 做所有解析”。Ingest Pipeline 缺少持久队列和多目标输出。当解析逻辑超过两三个 processor 的简单链条、或者需要同时写多个目标系统时,Ingest Pipeline 就不够用了。

误解三:“每台机器都应该跑 Logstash”。Logstash 的 JVM 开销在每台机器部署时通常无法接受。每台机器跑 Beats 或 Elastic Agent,集中部署 Logstash,是资源与能力的合理分配。

误解四:“Beats 没有可靠性保证”。Filebeat 的 registry 机制保证了文件读取的断点续传,配合 Logstash 的 ACK 或 ES 的确认机制,可以实现端到端 at-least-once。真正需要区分的是队列类型:默认的内存队列 queue.mem 容量 3200 条事件,在途数据的安全完全依赖下游确认;但 Filebeat 同样提供磁盘队列 queue.disk,当前文档标注为 GA,指定 max_size 即可启用(默认 10 GB,数据落在 ${path.data}/diskqueue,成功发送后删除)。所以"Beats 没有进程本地的落盘缓冲"不成立,准确的说法是它有但不默认开,代价与 Logstash PQ 同源——每条事件多一次磁盘写读。

误解五:“Ingest Pipeline 不能按内容决定文档写到哪里”。reroute processor 可以按字段值改写目标索引或 data stream,这条约束现在只剩一半:换同一集群内的索引可以,换集群或换非 ES 目标不行。判断时该问的是"目标是不是同一个集群",而不是"目标是不是同一个索引"。

练习

  1. 搭建一个 Filebeat → ES 的最小管道,在 Filebeat 的 output 里配置 pipeline: parse-nginx,用第二节的 parse-nginx pipeline 对采集到的 nginx 日志做 grok 解析。对比在 Logstash 里做同样解析的配置量差异,记录两种方式的行数和调试难度。

  2. 把练习 1 的 Filebeat 改成 Filebeat → Logstash → ES,在 Logstash 里用 grok filter 做同样的解析,并加一个条件路由:status >= 500 的事件除了写入主索引,还要额外发一份到告警索引。然后试着只用 Ingest Pipeline 实现同样效果,说明 reroute 为什么不够——它改写目标而不是复制一份,且执行后会跳过 pipeline 里其余全部 processor。

  3. 思考题:给定场景——50 台应用服务器每台产生日志,日志需要解析后写入两个 ES 集群(生产和归档)。对比三种方案的资源消耗和运维复杂度:(a) 每台跑 Logstash;(b) 每台跑 Filebeat,中心跑 2 台 Logstash;© 每台跑 Filebeat 直连 ES + Ingest Pipeline,另外用 Logstash 处理需要写双集群的部分。

系列导航

序号 主题
00 导读:核心对象是 event,骨架是三段管道
01 架构:JRuby、JVM 与 pipeline 的运行形态
02 event 模型:@timestamp、@metadata 与字段引用
03 codec:字节流与 event 的边界转换
04 input 插件:拉取、监听与 Beats 接入
05 Grok 的本质:命名正则加预定义 pattern
06 dissect 与结构化 filter:放弃回溯换吞吐
07 常用 filter 组合:mutate、date、geoip 与条件
08 output 插件:Elasticsearch output 与批量写入
09 pipeline 执行模型:worker、batch 与背压
10 内存队列 vs 持久队列:可靠性的分界线
11 死信队列(DLQ):无法处理的 event 去哪
12 Multiple Pipelines 与 pipeline-to-pipeline
13 监控:Node Stats API、hot threads 与瓶颈定位
14 性能调优:JVM heap、批处理与持久队列磁盘
15 Logstash vs Beats vs Ingest Pipeline:该用谁(本篇)
16 Logstash vs Fluentd vs Vector:日志管道的三种取舍
17 Logstash 的演进与 Elastic Agent 的冲击

参考资料