EFK 学习思路
本文为EFK日志系统入门指南,面向需要排查线上问题的开发者,重点讲解如何高效使用Kibana查询日志。文章提出"先理解数据流,再掌握查询技巧"的学习路径,将EFK拆解为Fluentd采集、Elasticsearch存储和Kibana查询三个核心环节。重点详细介绍了Kibana查询语言KQL,包括字段匹配、布尔组合、通配符、范围查询等实用语法,并给出7个典型查询场景示例。通过本文
EFK 学习思路
本文面向完全没有用过 EFK 的人,从零开始建立一套完整的 EFK 日志排查能力。文章不会涉及运维搭建、集群部署,只聚焦一件事:
让你学会用 Kibana 查日志、用 Elasticsearch 理解存储、用 Fluentd 理解日志从哪来。
读完本文,你应该能够独立在 Kibana 里查到任何你需要的日志,并用它们排查问题。
一、先记住:你学 EFK,到底是为了什么?
很多人一听到 EFK,会下意识想到:
- Elasticsearch 很复杂
- Kibana 页面很多
- Fluentd 配置看不懂
- 感觉像运维或者平台同学才需要学
但如果你的工作经常要:
- 看线上日志
- 排查 Bug
- 回溯故障时间点
- 分析某个服务是否异常
- 给别人提供日志证据
那你学 EFK,本质上是在学:
如何更快地从海量日志里找到问题。
先记住一句总口诀:
先搞清数据怎么进来,再学怎么查,再学怎么看趋势,最后学怎么拿日志支撑结论。
一句话理解:
EFK = 日志采集 + 日志存储 + 日志查询分析。
二、先建立整体脑图
2.1 EFK 分别是什么
| 组件 | 作用 | 你需要掌握到什么程度 |
|---|---|---|
| Fluentd / Fluent Bit | 采集日志、补充元数据、转发日志 | 明白工作原理与数据流 |
| Elasticsearch | 存储日志、建立索引、支持查询 | 概念理解与查询应用 |
| Kibana | 搜索日志、分析字段、做图表和看板 | 精通使用者 |
2.2 一张图记住数据流
应用日志
│
├─ 容器标准输出 / 日志文件
│
↓
Fluentd / Fluent Bit
│
├─ 采集日志
├─ 补充上下文信息(Pod、命名空间、标签等)
└─ 转发到 Elasticsearch
│
↓
Elasticsearch
├─ 按索引存储日志
└─ 支持查询、聚合、过滤
│
↓
Kibana
├─ 搜索日志
├─ 查看字段
├─ 做图表
└─ 组装监控看板
2.3 你真正要形成的能力
学 EFK,不是去背每个组件的配置项,而是形成下面这四个能力:
- 知道日志是怎么流进来的
- 知道日志现在存在哪里
- 知道怎么快速把目标日志查出来
- 知道怎么把日志变成可分析、可汇报的信息
三、Kibana 学习思路(最重要,投入 80% 精力)
这是你最主要的战场。
因为在绝大多数日常工作里,你真正直接操作最多的,不是 Elasticsearch,也不是 Fluentd,而是 Kibana。
3.1 先明确目标:你要达到什么水平?
你的目标不是"会点页面点击",而是达到:
精通使用者级别:看到一个问题,能迅速用 Kibana 把相关日志捞出来、筛出来、看出规律、形成结论。
3.2 Kibana 最核心的四件事
四、Kibana 第一件事:会搜(KQL 查询语言详解)
这是基础中的基础。Kibana 的搜索核心是 KQL(Kibana Query Language),一套专为日志搜索设计的查询语言。
4.1 KQL 的基础语法
4.1.1 最简单的查询:字段精确匹配
field:value
这是 KQL 最基本的形式。
示例:
| 查询语句 | 含义 |
|---|---|
log.level:error |
查找日志级别为 error 的日志 |
service.name:user-service |
查找 user-service 服务的日志 |
kubernetes.pod.name:api-server-7d8f9 |
查找特定 Pod 的日志 |
kubernetes.namespace:production |
查找生产命名空间的日志 |
注意:
- 字段名和值之间用冒号
:分隔 - 值如果包含空格或特殊字符,用双引号括起来:
message:"user login failed"
4.1.2 布尔组合:AND / OR / NOT
KQL 支持三种逻辑运算符,让你可以组合多个条件。
AND(且)—— 同时满足多个条件
field1:value1 AND field2:value2
示例:
log.level:error AND service.name:user-service
含义:查找 user-service 服务的 error 级别日志。
kubernetes.namespace:production AND log.level:error AND message:"timeout"
含义:查找生产环境中包含"timeout"的错误日志。
OR(或)—— 满足任意一个条件
field1:value1 OR field2:value2
示例:
log.level:error OR log.level:warn
含义:查找错误日志或警告日志。
service.name:user-service OR service.name:order-service
含义:查找 user-service 或 order-service 的日志。
NOT(非)—— 排除某个条件
NOT field:value
示例:
NOT log.level:debug
含义:排除 debug 级别的日志。
service.name:user-service AND NOT log.level:info
含义:查找 user-service 的日志,但排除 info 级别。
混合使用:
(service.name:user-service OR service.name:order-service) AND log.level:error
含义:查找 user-service 或 order-service 的错误日志。
log.level:error AND (message:"timeout" OR message:"connection failed")
含义:查找包含"timeout"或"connection failed"的错误日志。
4.1.3 通配符查询:模糊匹配
当记不全完整值时,用通配符。
* 代表任意多个字符
| 查询语句 | 匹配示例 |
|---|---|
service.name:user* |
user-service, user-api, user-db |
kubernetes.pod.name:api-* |
api-server-1, api-server-2, api-gateway |
message:*timeout* |
任何包含 timeout 的日志 |
? 代表单个字符
| 查询语句 | 匹配示例 |
|---|---|
log.level:err?r |
error |
kubernetes.pod.name:api-? |
api-1, api-2, api-a |
4.1.4 范围查询:数值和日期
用于查询数值型或日期型字段。
大于 / 小于
response_time:>1000
含义:查找响应时间大于 1000 毫秒的日志。
http.status_code:>=500
含义:查找 HTTP 状态码大于等于 500 的日志(服务器错误)。
log.level:<info
含义:查找级别低于 info 的日志(如 debug、trace)。
区间范围
response_time:[1000 TO 5000]
含义:查找响应时间在 1000 到 5000 毫秒之间的日志。
http.status_code:[400 TO 499]
含义:查找所有客户端错误(4xx)。
4.1.5 存在性查询:判断字段是否存在
存在某个字段
http.status_code:*
含义:查找包含 http.status_code 字段的日志。
不存在某个字段
NOT http.status_code:*
含义:查找不包含 http.status_code 字段的日志。
4.1.6 短语查询:精确匹配整句话
当值包含空格时,用双引号。
message:"user login failed"
含义:查找 message 字段精确包含"user login failed"这句话的日志。
不带引号 vs 带引号的区别:
| 查询 | 含义 |
|---|---|
message:user login failed |
搜索 user OR login OR failed(三个词任一出现) |
message:"user login failed" |
搜索完整短语"user login failed" |
4.2 KQL 实战:常见查询组合
下面这些都是你工作中真正会用的查询。
场景 1:查某个服务的错误日志
service.name:user-service AND log.level:error
场景 2:查某个 Pod 在特定时间的日志
kubernetes.pod.name:api-server-7d8f9
然后在时间选择器里选择对应时间范围。
场景 3:查包含某个错误关键词的所有日志
message:"OutOfMemory" OR message:"timeout" OR message:"connection refused"
场景 4:查某个请求的完整调用链(有 traceId 时)
traceId:"abc123def456"
场景 5:查生产环境的所有 5xx 错误
kubernetes.namespace:production AND http.status_code:[500 TO 599]
场景 6:排除 debug 日志,只看 warn 及以上
(log.level:error OR log.level:warn) AND kubernetes.namespace:production
场景 7:查某个容器重启前后的日志
先查该容器的日志:
kubernetes.container.name:user-api
然后根据重启时间点,前后各扩展一段时间查看。
4.3 KQL 查询性能优化建议
KQL 查询本身很快,但以下情况会明显变慢:
- 时间范围太大:查一整年 vs 查 1 小时
- 通配符开头:
*timeout比timeout*慢很多 - 全文模糊搜索:
message:*error*比log.level:error慢 - 跨太多索引:
app-logs-*匹配了 365 个索引 vs 指定日期
优化原则:
先缩时间,再缩范围,最后再模糊搜索。
五、Kibana 第二件事:会控时间
很多人查不到日志,不是因为不会搜,而是因为时间范围错了。
5.1 时间选择器的位置
在 Kibana Discover 页面的右上角,你会看到一个时间选择器。
5.2 相对时间:查"最近"的日志
相对时间是以"现在"为起点,向前推算一段时间。
常用相对时间:
| 选项 | 含义 |
|---|---|
| Last 15 minutes | 最近 15 分钟 |
| Last 30 minutes | 最近 30 分钟 |
| Last 1 hour | 最近 1 小时 |
| Last 24 hours | 最近 24 小时 |
| Last 7 days | 最近 7 天 |
使用场景:
- 线上问题正在发生:用 Last 15 minutes 或 Last 30 minutes
- 回顾今天的问题:用 Last 24 hours
- 分析一周趋势:用 Last 7 days
5.3 绝对时间:查"特定时间点"的日志
绝对时间是精确指定起止时间。
格式示例:
- 开始时间:
2026-04-03 10:00:00 - 结束时间:
2026-04-03 11:00:00
使用场景:
- 故障发生在已知时间点(如 10:03),需要回溯前后
- 需要对比两个不同时间段的日志
- 需要精确提取某段时间的日志作为证据
5.4 快速调整时间范围的技巧
- 放大:在时间轴上拖动选择更小范围,查看细节
- 缩小:点击时间选择器,切换到更大范围(如从 15 分钟切到 1 小时)
- 平移:在时间轴上左右拖动,查看相邻时间段
5.5 时间相关的常见错误
| 错误 | 正确做法 |
|---|---|
| 故障发生在 10:03,却查的是 Last 15 minutes(当前是 10:20) | 切换到绝对时间,设置 10:00-10:10 |
| 查 Last 7 days,结果太多找不到重点 | 先缩小到故障发生的 1 小时 |
| 跨时区问题 | 确认 Kibana 显示的时间是你本地时间还是服务器时间 |
六、Kibana 第三件事:会看字段(字段详解)
日志不是只看 message 文本。
真正高效的人,都是靠字段过滤和字段组合排查问题。
6.1 什么是字段?
每一条日志在 Elasticsearch 里都是一个 JSON 文档,包含多个键值对。
示例日志(原始 JSON):
{
"_index": "app-logs-2026.04.03",
"_source": {
"message": "user login failed: timeout",
"log.level": "error",
"service.name": "user-service",
"timestamp": "2026-04-03T10:03:15.123Z",
"kubernetes": {
"pod.name": "user-service-7d8f9c8b5-xk2m9",
"namespace": "production",
"container.name": "user-service",
"node.name": "node-01"
},
"host": {
"ip": "10.0.1.15",
"hostname": "worker-01"
},
"traceId": "abc123def456",
"userId": "user_789"
}
}
在这个例子里:
message、log.level、service.name等都是字段- 每个字段有一个值
- 你可以用这些字段做精确过滤
6.2 常用字段详解
6.2.1 基础日志字段
| 字段名 | 含义 | 常见值 | 用途 |
|---|---|---|---|
message |
日志正文内容 | "user login failed" |
查看具体日志内容 |
log.level |
日志级别 | debug, info, warn, error, fatal |
快速过滤错误日志 |
timestamp |
日志时间戳 | 2026-04-03T10:03:15.123Z |
确认日志发生时间 |
logger.name |
记录日志的类或模块 | com.example.UserService |
定位代码位置 |
6.2.2 服务标识字段
| 字段名 | 含义 | 常见值 | 用途 |
|---|---|---|---|
service.name |
服务名称 | user-service, order-service |
按服务过滤日志 |
service.version |
服务版本 | 1.2.3 |
排查版本相关问题 |
service.environment |
环境标识 | production, staging, development |
区分环境 |
6.2.3 Kubernetes 相关字段(kubernetes.*)
这是 Fluentd 自动补充的元数据,对容器化环境排查问题至关重要。
| 字段名 | 含义 | 示例值 | 用途 |
|---|---|---|---|
kubernetes.pod.name |
Pod 名称 | user-service-7d8f9c8b5-xk2m9 |
精确定位到某个 Pod 实例 |
kubernetes.namespace |
命名空间 | production, default, kube-system |
区分不同环境或业务域 |
kubernetes.container.name |
容器名称 | user-service |
多容器 Pod 中区分容器 |
kubernetes.node.name |
节点名称 | node-01, worker-02 |
排查节点相关问题 |
kubernetes.pod.uid |
Pod 的唯一 ID | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
Pod 重建后追溯 |
kubernetes.labels.app |
Pod 的 app 标签 | user-service |
按应用分组 |
kubernetes.labels.version |
Pod 的版本标签 | v1.2.3 |
按版本分组 |
kubernetes.labels.tier |
Pod 的层级标签 | backend, frontend |
按架构层级分组 |
kubernetes.annotations.* |
Pod 的注解信息 | 自定义 | 查看额外元数据 |
kubernetes.docker.container_id |
Docker 容器 ID | abc123... |
关联 Docker 相关日志 |
kubernetes.host |
宿主机 IP | 192.168.1.10 |
关联宿主机信息 |
kubernetes. 字段的价值:*
原始日志里可能只有"报错了",但有了这些字段,你能回答:哪个 Pod?哪个命名空间?哪个容器?哪个节点?
6.2.4 主机相关字段(host.*)
| 字段名 | 含义 | 示例值 | 用途 |
|---|---|---|---|
host.name |
主机名 | worker-01 |
定位具体机器 |
host.ip |
主机 IP | 10.0.1.15 |
网络问题排查 |
host.hostname |
主机完整主机名 | worker-01.cluster.local |
精确定位 |
6.2.5 网络相关字段(network.* / http.*)
| 字段名 | 含义 | 示例值 | 用途 |
|---|---|---|---|
http.request.method |
HTTP 请求方法 | GET, POST, PUT, DELETE |
分析请求类型分布 |
http.request.url |
请求 URL | /api/users/123 |
定位具体接口 |
http.response.status_code |
HTTP 响应状态码 | 200, 404, 500 |
快速筛选错误响应 |
http.response.body |
响应体内容 | {"error":"not found"} |
查看详细错误 |
network.client.ip |
客户端 IP | 192.168.1.100 |
追踪来源 |
network.bytes |
传输字节数 | 1024 |
分析流量大小 |
6.2.6 链路追踪字段(有链路追踪时)
| 字段名 | 含义 | 示例值 | 用途 |
|---|---|---|---|
traceId |
整条链路的全局 ID | abc123def456 |
串联一个请求的所有日志 |
spanId |
当前调用的 Span ID | span789 |
定位链路中的具体节点 |
parentId |
父调用的 Span ID | span456 |
理解调用关系 |
service.transaction.name |
事务/操作名称 | GET /api/users |
按操作类型聚合 |
6.2.7 业务相关字段(根据你们系统定义)
这些字段取决于你们日志里打了什么:
| 字段名(示例) | 含义 | 用途 |
|---|---|---|
userId |
用户 ID | 查某个用户的所有操作 |
orderId |
订单 ID | 查某个订单的完整流程 |
requestId |
请求 ID | 内部请求追踪 |
tenantId |
租户 ID | 多租户系统排查 |
6.3 如何在 Kibana 里查看字段列表
在 Kibana Discover 页面:
- 左侧边栏会显示Available fields(可用字段列表)
- 点击某个字段名,可以快速:
- 添加到显示列
- 作为过滤条件
- 查看该字段的值分布
6.4 字段查询实战
场景 1:只看 error 和 warn 级别的日志
log.level:error OR log.level:warn
场景 2:查生产环境 user-service 的所有日志
kubernetes.namespace:production AND service.name:user-service
场景 3:查某个 Pod 的所有日志
kubernetes.pod.name:user-service-7d8f9c8b5-xk2m9
场景 4:查所有 HTTP 5xx 错误
http.response.status_code:[500 TO 599]
场景 5:查某个用户的所有操作日志
userId:"user_789"
场景 6:查某个请求的完整调用链
traceId:"abc123def456"
场景 7:查特定节点上的所有错误日志
kubernetes.node.name:node-01 AND log.level:error
6.5 字段的黄金组合
记住这几个常用组合,能解决 80% 的排查场景:
| 目标 | 字段组合 |
|---|---|
| 查某个服务的错误 | service.name:X AND log.level:error |
| 查某个 Pod 的日志 | kubernetes.pod.name:X |
| 查某个请求的完整链路 | traceId:X |
| 查某个用户的所有操作 | userId:X |
| 查生产环境的 5xx 错误 | kubernetes.namespace:production AND http.status_code:[500 TO 599] |
七、Kibana 第四件事:会做可视化和看板
当你已经能搜到日志后,下一步不是"盯着一条条文本看",而是学会看趋势。
7.1 为什么要做可视化?
单条日志适合定位问题,图表和看板适合发现模式。
可视化能回答的问题:
- 错误是不是在某个时间点突然激增?
- 哪个服务的日志量异常高?
- 错误级别分布是否正常?
- 某个问题是不是持续存在还是偶发?
7.2 常用图表类型及创建方法
7.2.1 错误数量趋势图(折线图/面积图)
用途: 查看错误随时间的变化趋势。
创建步骤(Kibana Lens):
- 打开 Kibana → Visualize Library → Create new visualization → Lens
- 选择索引模式(如
app-logs-*) - 拖拽字段:
- X 轴:
@timestamp(自动按时间聚合) - Y 轴:Count(记录数)
- X 轴:
- 添加过滤条件:
log.level:error - 保存为"错误趋势图"
查询语句配合:
kubernetes.namespace:production AND log.level:error
能看出的信息:
- 错误从什么时候开始增多
- 错误是否有周期性
- 错误是否在某个操作后明显下降
7.2.2 各服务日志量柱状图
用途: 对比不同服务的日志量,找出异常。
创建步骤:
- X 轴:
service.name(按服务分组) - Y 轴:Count(记录数)
- 可选过滤:
log.level:error(只看错误)
能看出的信息:
- 哪个服务日志量最多
- 哪个服务错误最多
- 是否有服务日志量突然异常
7.2.3 日志级别分布图(饼图)
用途: 查看各级别日志的占比。
创建步骤:
- 切片字段:
log.level - 大小:Count
正常情况下的分布:
- info 占大部分
- warn 占小部分
- error 应该很少
异常情况:
- error 占比明显上升 → 有故障
- warn 激增 → 有潜在问题
- debug 太多 → 可能日志级别配置错误
7.2.4 HTTP 状态码分布图
用途: 分析接口响应健康度。
创建步骤:
- X 轴:
http.response.status_code - Y 轴:Count
能看出的信息:
- 5xx 错误占比
- 4xx 错误类型分布
- 接口整体成功率
7.2.5 Top N 错误消息柱状图
用途: 找出最常见的错误类型。
创建步骤:
- X 轴:
message(或自定义错误字段) - Y 轴:Count
- 排序:Top 10
- 过滤:
log.level:error
能看出的信息:
- 哪类错误出现最频繁
- 错误是否集中
- 优先处理哪些错误
7.2.6 Pod 日志量热力图
用途: 查看各 Pod 的日志分布。
创建步骤:
- X 轴:
kubernetes.pod.name - Y 轴:Count
- 颜色深浅:日志量
能看出的信息:
- 是否有 Pod 日志量异常(可能该实例有问题)
- 负载均衡是否正常
- 是否有 Pod 不输出日志(可能挂了)
7.3 仪表盘(Dashboard):把图表组装成看板
什么是仪表盘?
仪表盘是多个图表和搜索结果的集合,用于在一个页面查看完整信息。
创建步骤:
- 打开 Kibana → Dashboard → Create new dashboard
- 添加已保存的可视化图表
- 添加已保存的搜索
- 调整布局和大小
- 保存仪表盘
推荐的"故障排查仪表盘"配置:
| 区域 | 内容 |
|---|---|
| 顶部 | 时间选择器(全局) |
| 左上 | 错误趋势图(最近 1 小时) |
| 右上 | 日志级别分布饼图 |
| 左中 | 各服务错误量柱状图 |
| 右中 | Top 10 错误消息 |
| 底部 | 原始日志列表(过滤后) |
使用场景:
- 故障发生时快速打开
- 日常巡检
- 给领导/团队展示问题
- 作为 Bug 报告的附件
7.4 保存和分享
保存搜索
- 在 Discover 页面配置好查询条件
- 点击"Save"按钮
- 输入名称(如"user-service 错误日志")
- 下次直接在"Saved searches"里打开
分享链接
- 打开已保存的搜索或仪表盘
- 点击"Share"按钮
- 复制链接
- 粘贴到 Bug 报告或聊天中
分享链接的价值:
别人点开链接,看到的就是你配置好的查询条件和结果,无需重复操作。
八、Elasticsearch 详解:日志是如何存储和查询的
8.1 Elasticsearch 是什么?
一句话定义:
Elasticsearch(简称 ES)是一个分布式搜索和分析引擎,用来存储和检索大量数据。
在 EFK 里,它的角色是:
日志的存储数据库 + 查询引擎。
8.2 核心概念详解
8.2.1 索引(Index)
定义:
索引是 ES 存储数据的基本单位,可以理解成关系数据库里的"表"。
日志索引的命名习惯:
app-logs-2026.04.03
gateway-logs-2026.04.03
kubernetes-prod-2026.04.03
为什么按日期分索引?
- 方便按时间范围查询
- 方便删除旧日志(直接删索引)
- 查询性能更好(不用扫全量数据)
8.2.2 文档(Document)
定义:
文档是 ES 里存储的一条数据,格式是 JSON。
示例(一条日志文档):
{
"timestamp": "2026-04-03T10:03:15.123Z",
"message": "user login failed: timeout",
"log.level": "error",
"service.name": "user-service",
"kubernetes.pod.name": "user-service-7d8f9c8b5-xk2m9",
"kubernetes.namespace": "production"
}
8.2.3 字段映射(Mapping)
定义:
Mapping 定义了每个字段的类型(字符串、数字、日期等)和如何被索引。
常见字段类型:
| 类型 | 用途 | 示例 |
|---|---|---|
text |
全文搜索的文本 | message |
keyword |
精确匹配的字符串 | service.name, log.level |
long / integer |
整数 | http.status_code, response_time |
date |
日期时间 | timestamp |
object |
嵌套对象 | kubernetes, host |
为什么区分 text 和 keyword?
| 特性 | text | keyword |
|---|---|---|
| 分词 | 是(会被拆成单词) | 否(整个字符串作为一个值) |
| 用途 | 全文搜索 | 精确匹配、聚合、排序 |
| 示例 | message:"user login" 会被分成 user 和 login |
service.name:"user-service" 必须完全匹配 |
8.2.4 索引模式(Index Pattern)
定义:
索引模式是 Kibana 用来匹配一组索引的通配符表达式。
示例:
| 索引模式 | 匹配的索引 |
|---|---|
app-logs-* |
app-logs-2026.04.01, app-logs-2026.04.02, … |
kubernetes-prod-* |
kubernetes-prod-2026.04.01, … |
* |
所有索引 |
为什么需要索引模式?
Kibana 需要知道去哪些索引里查数据。配置了索引模式后:
- 可以跨多个索引查询
- 可以看到这些索引里的所有字段
8.3 Elasticsearch 是如何处理查询的?
8.3.1 查询的基本流程
用户在 Kibana 输入查询
↓
Kibana 将查询转换成 ES DSL(查询语言)
↓
ES 接收查询,分析涉及哪些索引
↓
ES 在相关索引中查找匹配的文档
↓
ES 返回结果给 Kibana
↓
Kibana 展示结果
8.3.2 为什么有些查询快,有些查询慢?
快的查询:
- 时间范围小(只查几个索引)
- 字段精确匹配(
log.level:error) - 使用了索引的字段(keyword 类型)
慢的查询:
- 时间范围大(查几百个索引)
- 全文模糊搜索(
message:*error*) - 通配符开头(
service.name:*user*) - 复杂聚合(多维度分组统计)
8.3.3 查询优化的基本原则
先缩范围,再精确过滤,最后再模糊搜索。
示例对比:
| 查询 | 性能 | 原因 |
|---|---|---|
message:*timeout*(全量搜索) |
慢 | 全文模糊,扫大量数据 |
log.level:error AND message:timeout |
快 | 先过滤级别,再搜关键词 |
kubernetes.namespace:production AND log.level:error |
很快 | 精确字段匹配 |
8.4 你需要掌握到哪里就够了?
必须理解的概念:
- 日志存在索引里
- 每条日志是一个 JSON 文档
- 字段有不同类型(text / keyword)
- 索引模式用来匹配一组索引
- 查询范围越大越慢
无需深入的内容:
- ES 集群部署
- 分片和副本配置
- 索引生命周期管理
- Java API
- 调优参数
九、Fluentd / Fluent Bit 详解:日志是怎么来到 ES 的
9.1 Fluentd / Fluent Bit 是什么?
一句话定义:
Fluentd / Fluent Bit 是一个日志收集和转发代理,负责把日志从应用收集起来,处理后发给 Elasticsearch。
两者关系:
| 特性 | Fluentd | Fluent Bit |
|---|---|---|
| 定位 | 完整的日志收集平台 | 轻量级版本 |
| 资源占用 | 较高 | 很低 |
| 常见场景 | 服务器、K8s 节点 | 容器、边缘设备 |
| 配置复杂度 | 较高 | 较简单 |
日常工作里你不需要区分太细,知道它们干的是同一类工作就行。
9.2 Fluentd 在 EFK 链路中的位置
应用输出日志
↓
Fluentd 采集日志
↓
Fluentd 补充元数据(Pod、namespace 等)
↓
Fluentd 转发到 Elasticsearch
↓
Elasticsearch 存储
↓
Kibana 查询展示
9.3 Fluentd 补充了哪些元数据?
这是 Fluentd 最重要的价值——把"裸日志"变成"带上下文的日志"。
9.3.1 Kubernetes 元数据(容器环境)
Fluentd 会读取 K8s API,自动给每条日志加上:
{
"kubernetes": {
"pod.name": "user-service-7d8f9c8b5-xk2m9",
"namespace": "production",
"container.name": "user-service",
"node.name": "node-01",
"pod.uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"labels": {
"app": "user-service",
"version": "v1.2.3",
"tier": "backend"
}
}
}
这些字段的来源:
pod.name、namespace、container.name:从容器运行时获取labels:从 K8s Pod 定义获取node.name:从 Pod 调度信息获取
9.3.2 主机元数据(服务器环境)
{
"host": {
"name": "worker-01",
"ip": "10.0.1.15",
"hostname": "worker-01.cluster.local"
}
}
9.3.3 其他补充字段
{
"@timestamp": "2026-04-03T10:03:15.123Z", // 日志时间戳
"log.level": "error", // 日志级别(从日志内容解析)
"service.name": "user-service" // 服务名(根据配置添加)
}
9.4 为什么这些元数据对排查问题至关重要?
没有元数据的日志:
2026-04-03 10:03:15 ERROR user login failed: timeout
你只能知道:
- 有个错误
- 错误内容是登录超时
有了元数据的日志:
{
"message": "user login failed: timeout",
"log.level": "error",
"service.name": "user-service",
"kubernetes.pod.name": "user-service-7d8f9c8b5-xk2m9",
"kubernetes.namespace": "production",
"kubernetes.container.name": "user-service",
"kubernetes.node.name": "node-01",
"userId": "user_789"
}
你现在能回答:
- 哪个服务?→ user-service
- 哪个环境?→ production
- 哪个 Pod?→ user-service-7d8f9c8b5-xk2m9
- 哪个容器?→ user-service
- 哪个节点?→ node-01
- 哪个用户?→ user_789
这就是为什么 Fluentd 的价值不只是"搬运日志"。
9.5 你需要掌握到哪里就够了?
必须理解的内容:
- Fluentd 负责采集和转发日志
- Fluentd 给日志补充了 Kubernetes 元数据
- 日志流向是:应用 → Fluentd → Elasticsearch → Kibana
- kubernetes.* 字段是 Fluentd 加上的
无需深入的内容:
- Fluentd 配置文件编写
- 插件开发
- 性能调优
- 路由规则设计
十、Filebeat 详解:它是什么角色?
10.1 Filebeat 是什么?
一句话定义:
Filebeat 是一个轻量级的日志文件采集器,部署在服务器上,负责把日志文件"搬运"给 Fluentd 或 Elasticsearch。
10.2 Filebeat 在什么场景下会出现?
场景 1:服务器文件日志
- 应用把日志写在服务器的
/var/log/app/目录下 - Filebeat 监控这些文件
- 有新日志就采集并转发
场景 2:容器日志(替代方案)
- 某些架构里用 Filebeat 代替 Fluentd 采集容器日志
- 但这种情况相对较少
10.3 Filebeat 和 Fluentd 的区别
| 特性 | Filebeat | Fluentd |
|---|---|---|
| 定位 | 轻量级采集器 | 完整的日志处理平台 |
| 功能 | 采集 + 转发 | 采集 + 处理 + 路由 + 丰富 |
| 配置 | 简单 | 复杂 |
| 常见搭配 | 直接发 ES 或发给 Fluentd | 发给 ES |
典型架构:
应用日志文件
↓
Filebeat(采集)
↓
Fluentd(处理 + 补充元数据)
↓
Elasticsearch
或
应用日志文件
↓
Filebeat(采集 + 转发)
↓
Elasticsearch
10.4 你需要知道什么就够了?
必须知道的内容:
- Filebeat 是轻量级日志采集器
- 常用于采集服务器上的日志文件
- 它可能出现在日志链路的最前端
- 你不是主要操作它的人
无需深入的内容:
- Filebeat 配置
- 部署方式
- 监控指标
- 性能调优
十一、实战:完整排查流程演示
场景:用户反馈"登录有时候会失败"
步骤 1:确定时间范围
先问清楚:
- 问题什么时候开始的?→ 今天上午 10 点左右
- 现在还在发生吗?→ 是的,偶发
操作:
在 Kibana 时间选择器选择:
- 绝对时间:
2026-04-03 09:30:00到2026-04-03 11:00:00
步骤 2:确定服务范围和错误类型
查询:
service.name:user-service AND log.level:error
观察:
- 错误日志数量
- 错误消息内容
- 错误发生的时间点
步骤 3:分析错误类型
假设看到以下错误:
message:"user login failed: timeout"
message:"user login failed: database connection refused"
message:"user login failed: token expired"
初步判断:
- timeout → 可能是下游服务响应慢
- database connection refused → 数据库连接问题
- token expired → 认证服务问题
步骤 4:用字段缩小范围
查询超时错误:
service.name:user-service AND message:"timeout"
查看涉及的 Pod:
添加字段 kubernetes.pod.name,发现:
- 错误集中在
user-service-7d8f9c8b5-xk2m9 - 其他 Pod 没有或很少
初步结论:
可能是单个实例问题,不是全局问题。
步骤 5:检查该 Pod 的完整日志
查询:
kubernetes.pod.name:user-service-7d8f9c8b5-xk2m9
观察:
- 该 Pod 是否频繁重启
- 是否有内存/CPU 相关警告
- 错误发生前是否有异常日志
步骤 6:查看错误趋势
创建一个简单的趋势图:
- X 轴:时间(每 5 分钟)
- Y 轴:错误数量
如果看到错误在某个时间点后激增:
可能该时间点有发布、配置变更、或下游服务异常。
步骤 7:查看链路追踪(如果有)
如果日志里有 traceId:
traceId:"abc123def456"
可以串联起:
- 用户请求进入
- 各服务处理过程
- 哪里开始出错
步骤 8:保存和分享
操作:
- 保存当前查询:“登录超时问题排查”
- 创建分享链接
- 粘贴到 Bug 报告
Bug 报告示例:
标题:用户登录偶发超时
时间:2026-04-03 10:00-10:30
影响:约 5% 的登录请求超时
范围:集中在 user-service-7d8f9c8b5-xk2m9 实例
Kibana 查询链接:[链接]
初步判断:
- 错误集中在单个 Pod 实例
- 错误类型为下游服务超时
- 建议检查该实例网络和下游服务健康状态
十二、你最终应该达到的使用结果
如果这套学习思路走通了,你最后应该达到下面这个状态:
对 Kibana
你能做到:
- 快速搜日志(熟练 KQL)
- 熟练切时间范围
- 会组合字段过滤
- 会做常见图表
- 会保存和分享结果
也就是:
达到精通使用者级别。
对 Elasticsearch
你能做到:
- 知道日志存在索引里
- 知道索引模式的作用
- 知道为什么查询有时会慢
- 知道 Kibana 背后在查 ES
也就是:
达到概念理解与查询应用级别。
对 Fluentd / Fluent Bit
你能做到:
- 知道它负责采集和转发
- 知道它会补元数据
- 知道这些字段为什么对排查重要
- 能说清日志数据流
也就是:
达到明白工作原理与数据流级别。
对 Filebeat
你能做到:
- 知道它是文件日志采集器
- 知道它可能出现在文件日志场景
- 知道它不是你当前学习重点
也就是:
达到知道其存在与角色级别。
十三、最后记住这套口诀
EFK 总口诀
先懂链路,再会搜索,再看字段,再做分析。
Kibana
主战场在 Kibana,先把日志查准,再把趋势看懂。
Elasticsearch
知道日志存在哪,知道为什么能查,知道为什么有时查得慢。
Fluentd / Fluent Bit
知道日志怎么被收上来,知道上下文字段是谁加上的。
Filebeat
知道它是前置搬运工,但不是当前重点。
十四、给你的最终建议
不要把 EFK 学成"平台搭建知识",而要把它学成:
一套基于日志的排查能力。
真正重要的不是:
- 会不会部署 ES 集群
- 会不会写 Fluentd 配置
- 会不会调 Kibana 插件
而是:
- 出问题时,你能不能快速找到日志
- 你能不能从字段里缩小范围
- 你能不能从趋势里看出异常
- 你能不能把日志证据组织成结论
当你能把"时间、查询、字段、趋势、分享"这五件事串起来,你的 EFK 使用能力就真正建立起来了。
更多推荐
所有评论(0)