☁️ 云原生可观测
由浅入深学习指南
7 个工具 · 5 个阶段 · 从零到动手
阶段 1: 概念 · 阶段 2: Prometheus · 阶段 3: ELK · 阶段 4: 采集+追踪 · 阶段 5: 集成
🤔 第 1 步:一台服务器出问题了,你怎么排查?
❌ 没有可观测性
- SSH 上服务器,敲
top 看 CPU - 再敲
tail -f /var/log/app.log 翻日志 - 发现日志太多,用
grep 搜"error" - 看了 30 分钟,没找到线索
- 重启服务,问题消失 → 下次再说
✅ 有可观测性
- 打开一个 Grafana 页面,发现 CPU 在 10:23 突然飙升
- 切到日志面板,10:23 附近全是 DB 连接超时
- 点其中一个 Trace,看到是某条 SQL 查询特别慢
- 定位到具体代码,5 分钟修完
- 整个过程没碰过服务器
💡 三句话理解可观测性
指标告诉你"出问题了"(CPU 飙升到 90%)。日志告诉你"为什么出"(DB 连接超时)。追踪告诉你"在哪里出的"(service_a 调用 service_b 的 /query 花了 5 秒)。缺一个,排查就得靠猜。
🎯 第 2 步:7 个工具各管什么?
📦 Elasticsearch
日志存储 + 搜索引擎。把日志当 JSON 存进去,像 Google 一样搜。
类比:专门为搜索优化的数据库。
📊 Kibana
ES 的可视化门户。搜日志、画图表、管索引。
类比:ES 的配套 UI。
📡 Prometheus
指标采集 + 告警系统。每 15s 拉一次应用的数值,存成时间序列。
类比:一个专门存"数字"的系统。
📈 Grafana
统一画图板。对接 Prometheus/ES/各种数据源,画 Dashboard。
类比:万能仪表盘。
🔗 OpenTelemetry
统一采集标准。一套 API 发出三种信号,通过 Collector 转到后端。
类比:可观测性的 USB-C 接口。
💨 Fluent Bit
轻量日志采集器。~650KB 内存,把日志从文件送到 ES/Kafka。
类比:日志管道工。
🔬 Jaeger
分布式追踪。展示一次请求经过哪些服务、每步花了多久。
类比:请求的全链路 GPS 记录仪。
💡 学习顺序建议:先 Prometheus+Grafana(最简单,5 分钟出结果)→ ES+Kibana → Fluent Bit → OTel+Jaeger。本指南完全按这个顺序走。
🏗️ 第 3 步:它们怎么拼在一起?
flowchart LR
APP["应用"] -->|"日志"| FB["Fluent Bit"]
APP -->|"traces+metrics"| SDK["OTel SDK"]
FB --> ES["ES 存储日志"]
ES --> KB["Kibana 搜日志"]
SDK --> COLL["OTel Collector"]
COLL --> PRO["Prometheus 存指标"]
COLL --> J["Jaeger 存追踪"]
PRO --> G["Grafana 画图"]
J --> G
ES --> G
🔵 日志链路
Fluent Bit 采日志 → ES 存 → Kibana 搜 / Grafana 看
🟠 指标链路
OTel SDK → Collector → Prometheus → Grafana
🟣 追踪链路
OTel SDK → Collector → Jaeger → Grafana
🟠 阶段 2 · 为什么先从 Prometheus 开始?
✅ 最简单的学习起点
- 启动 Prometheus 只要一行
docker run - 启动后自带 Web UI,输
up 就能看到结果 - Grafana 连上 Prometheus 后立刻出图
- 所有操作都有即时反馈,非常适合入门
📝 这阶段你会学到
- Metrics 是什么、怎么查
- PromQL 最常用的 5 个函数
- 配告警规则
- Grafana 建 Dashboard
- 预期用时:30 分钟
# 先跑起来再说,配什么后面讲
docker run -d --name prom -p 9090:9090 prom/prometheus
docker run -d --name grafana -p 3000:3000 grafana/grafana
📡 第 4 步:启动 Prometheus + 看第一个图
启动
# docker-compose.yml
services:
prometheus:
image: prom/prometheus
ports: ["9090:9090"]
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports: ["3000:3000"]
---
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
启动后访问 http://localhost:9090
第一步:输 up 回车
# 在 /graph 输入框里输入 up,点 Execute
up
# 看到结果了吗?
# prometheus → 1(表示在线)
# prometheus (2) → 1
# 1 = 在线,0 = 离线
# 就这么简单
第二步:切到 Graph 标签
# 输入
prometheus_http_requests_total
# 切到 Graph 标签
# 看到一条不断增长的曲线了吗?
# 这就是 Counter 指标——只增不减
第三步:用 rate() 看速率
# 输入
rate(prometheus_http_requests_total[5m])
# 切到 Graph
# 看到平稳的折线图了吗?
# rate() 把"累计值"变成了"每秒速率"
# 这才是监控需要的——看趋势,不是看累计
📝 第 5 步:PromQL 核心 5 个函数(够了)
PromQL 有几十个函数,但 90% 的场景只需要这 5 个。
| # | 函数 | 干什么 | 实例 | 效果 |
| 1 | 直接写指标名 | 查当前值 | prometheus_http_requests_total | 当前累计请求数 |
| 2 | rate(x[5m]) | Counter→每秒速率 | rate(promhttp_requests_total[5m]) | 每秒请求数 |
| 3 | sum by(job)(x) | 按 job 分组求和 | sum by(job)(rate(http_requests_total[5m])) | 每个服务的 QPS |
| 4 | {label="val"} | 标签过滤 | up{job="node"} | 只看 node 的状态 |
| 5 | topk(N, x) | 取 Top N | topk(3, rate(http_requests_total[5m])) | QPS 最高的 3 个 |
💡 PromQL 心法(记住这一句就够了)
Counter 用 rate(),Gauge 直接看,分组用 by(),TopK 用 topk。
Counter(累计值)→ 必须 rate() 再画图。
Gauge(可增可减)→ 直接画。
❌ 新手常犯的错
# 直接看 Counter——没意义!
prometheus_http_requests_total
# 数字一直涨,看不出趋势
# 应该用 rate()
rate(prometheus_http_requests_total[5m])
# 每秒变化量,趋势一目了然
✅ 实战三道题
# 1. CPU 使用率
100 - avg by(instance)(
rate(node_cpu_seconds_total{mode="idle"}[5m])
) * 100
# 2. 内存使用率
(1 - node_memory_MemFree_bytes
/ node_memory_MemTotal_bytes) * 100
# 3. P99 延迟
histogram_quantile(0.99,
rate(duration_seconds_bucket[5m])
)
📈 第 6 步:Grafana 连 Prometheus + 建第一个 Dashboard
连数据源(3 分钟)
# 方式一:手动
# 浏览器打开 http://localhost:3000
# 默认账号 admin/admin
# 左侧齿轮 → Data Sources → Add data source
# 搜索 Prometheus → URL 填 http://prometheus:9090
# → Save & Test(绿色=成功)
# 方式二:自动配(推荐)
# /etc/grafana/provisioning/datasources/prom.yaml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
isDefault: true
建 Dashboard(3 分钟)
# 1. 左侧 + 号 → New Dashboard
# 2. Add visualization → 选 Prometheus
# 3. 查询框输入:
rate(prometheus_http_requests_total[5m])
# 4. 右侧面板设置:
# Title: 请求速率
# Unit: req/s
# 5. 右上角 Apply → Save,取名
# 已经能看到一条曲线了
# 这就是你的第一个 Dashboard!
加下拉过滤(3 分钟)
# 1. Dashboard 设置 → Variables → Add
# 2. Name: job, Type: Query
# 3. Query: label_values(up, job)
# 4. Panels 中用 $job 变量:
rate(http_requests_total{job="$job"}[5m])
# 5. 顶部出现下拉菜单,选了自动变
🔔 第 7 步:配第一个告警规则
告警规则文件
# alerts.yml
groups:
- name: example
rules:
- alert: InstanceDown
expr: up == 0
for: 1m
labels: { severity: critical }
annotations:
summary: "实例 {{ $labels.instance }} 挂了"
- alert: HighCPU
expr: (100 - avg by(instance)(
rate(node_cpu_seconds_total{mode="idle"}[5m])
) * 100) > 80
for: 5m
labels: { severity: warning }
annotations:
summary: "CPU > 80% ({{ $value | humanize }}%)"
在 prometheus.yml 中引用
# prometheus.yml
rule_files:
- "alerts.yml"
# 验证语法
promtool check rules alerts.yml
# 热加载(不重启 Prometheus)
curl -X POST http://localhost:9090/-/reload
# 查看告警状态
# http://localhost:9090/rules
# 或 /api/v1/rules
常用操作速查
| 操作 | 命令 |
| 查配置 | curl /api/v1/status/config |
| 查目标 | /targets 页面看 UP/DOWN |
| 查规则 | /rules 页面看告警状态 |
| 热加载 | POST /-/reload |
| 查指标 | /metrics 看自身指标 |
✅ 阶段 2 小结 + 阶段 3 预告
✅ 你现在已经会了
- 启动 Prometheus + Grafana
- PromQL 5 个核心函数
- 建 Dashboard + 配告警
- 看 CPU/内存/请求数指标
🔜 下一步:ELK Stack
Prometheus 只能管"数字"(指标)。但排查问题还需要搜日志。ES 就是干这个的——把日志存进去,像 Google 一样搜。
💡 学习节奏:如果 Prometheus 部分还没完全理解,回头再练练。接下来 ES 部分完全独立,不影响。
🔎 第 8 步:启动 ES + Kibana + 写入第一条日志
启动
docker run -d --name es \
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
-e "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
docker.elastic.co/elasticsearch/elasticsearch:8.15.0
docker run -d --name kibana \
-p 5601:5601 \
-e "ELASTICSEARCH_HOSTS=http://host.docker.internal:9200" \
docker.elastic.co/kibana/kibana:8.15.0
# 验证
curl http://localhost:9200
# 看到 JSON = ES 跑起来了
# 打开 http://localhost:5601 = Kibana 跑起来了
写入第一条数据
# 打开 http://localhost:5601
# 左侧菜单 → Dev Tools → Console
# 建索引(不指定 mapping,ES 自动推断)
PUT /nginx-logs
# 写入一条日志
POST /nginx-logs/_doc
{
"@timestamp": "2026-05-08T10:00:00",
"client_ip": "192.168.1.100",
"method": "GET",
"uri": "/api/users",
"status_code": 200,
"response_time": 120,
"user_agent": "Mozilla/5.0"
}
验证数据进来了
# 搜全部
GET /nginx-logs/_search
{ "query": { "match_all": {} } }
# 应该看到刚才写入的那条记录
1 分钟完成写入→搜索。接下来可以批量写数据练习。
📦 第 9 步:理解 ES 的 3 个核心概念
Index(索引)
≈ 数据库的表。存同一类文档。
PUT /shop
# 创建一个索引
POST /shop/_bulk
{"index":{}}
{"name":"笔记本","price":6999,"stock":100}
{"index":{}}
{"name":"手机","price":4999,"stock":200}
Document(文档)
≈ 一行记录。JSON 格式,每个文档有唯一 ID。
# 搜索全部
GET /shop/_search
{ "query": { "match_all": {} } }
# 按 ID 查
GET /shop/_doc/ID
# 更新
POST /shop/_update/ID
{ "doc": { "stock": 80 } }
# 删除
DELETE /shop/_doc/ID
Mapping(映射)
≈ 表结构。字段类型定义。
# 查看映射
GET /shop/_mapping
# 手动定义(推荐)
PUT /products
{
"mappings": {
"properties": {
"name": { "type": "text" },
"price": { "type": "integer" },
"tags": { "type": "keyword" },
"created_at": { "type": "date" }
}
}
}
# text=分词 keyword=精确 integer=整数 date=时间
💡 CRUD 练习建议:在 Dev Tools 里依次做:建索引 → 写入 → 查 → 改 → 删。10 分钟就能记住所有操作。删错了?没事,再写入就行。
🔍 第 10 步:从 match 到 bool——搜索三步走
第 1 步:match_phrase(短语精确搜索)
# 最常用的搜索——搜关键词
GET /nginx-logs/_search
{ "query": {
"match": { "message": "error timeout" }
}}
# 分词搜索,含任意词就命中
# "error timeout" 分为 [error, timeout]
# 匹配含 error 或 timeout 的文档
第 2 步:term + range(精确 + 范围)
# 精确匹配——搜状态码
GET /nginx-logs/_search
{ "query": {
"term": { "status_code": 500 }
}}
# 范围——搜响应时间
GET /nginx-logs/_search
{ "query": {
"range": { "response_time": { "gt": 1000 } }
}}
# gt=大于 gte=大于等于 lt=小于 lte=小于等于
第 3 步:bool——组合查询利器
# 把上面所有条件组合在一起
GET /nginx-logs/_search
{ "query": {
"bool": {
"must": [
{ "match": { "message": "error" } }
],
"filter": [
{ "term": { "status_code": 500 } },
{ "range": { "response_time": { "gt": 1000 } } },
{ "range": { "@timestamp": { "gte": "now-6h" } } }
],
"must_not": [
{ "term": { "service": "healthcheck" } }
],
"should": [
{ "match": { "message": "urgent" } }
]
}
}}
# must=必须匹配(评分)
# filter=必须匹配(不评分,可缓存)
# must_not=排除
# should=提升评分
💡 搜索心法:match 搜文本 / term 精确值 / range 范围 / bool 搭积木。按这个顺序学,从简单到复杂。
📊 第 11 步:ES 聚合——分 3 个级别学
级别 1:terms + date_histogram(分组+时间)
# 按状态码分组计数
GET /nginx-logs/_search
{ "size":0, "aggs": {
"by_status": {
"terms": { "field":"status_code", "size":5 }
}
}}
# → 200: 1234次, 404: 56次, 500: 12次
# 按小时分组
GET /nginx-logs/_search
{ "size":0, "aggs": {
"hourly": {
"date_histogram": {
"field":"@timestamp",
"calendar_interval": "hour"
}
}
}}
级别 2:avg/stats/cardinality(统计量)
# 响应时间统计
GET /nginx-logs/_search
{ "size":0, "aggs": {
"stats": {
"stats": { "field":"response_time" }
}
}}
# count/min/max/avg/sum 一次性返回
# 去重计数
GET /nginx-logs/_search
{ "size":0, "aggs": {
"unique_ips": {
"cardinality": { "field":"client_ip" }
}
}}
级别 3:嵌套聚合(分组再统计)
GET /nginx-logs/_search
{ "size":0, "aggs": {
"by_service": {
"terms": { "field":"service.keyword" },
"aggs": {
"avg_resp": { "avg": {"field":"response_time"} },
"p99": {
"percentiles":{
"field":"response_time","percents":[99]
}
},
"hourly": {
"date_histogram":{
"field":"@timestamp","fixed_interval":"1h"
}
}
}
}
}}
# 外部分组→内部分组统计
# 一个查询回答:每个服务的平均延迟/P99/每小时趋势
🖥️ 第 12 步:Kibana 三步上手
① Data View(必做,配错=搜不到)
- 左侧菜单 → Stack Management → Data Views
- 点 Create data view
- Name:
nginx-logs - Index pattern:
nginx-logs-*(匹配你的索引) - Timestamp:
@timestamp - 点 Save
② Discover
- 左侧 → Discover → 选 data view
- 时间范围
Last 7 days - 搜索栏输
status_code: >= 400 - 点 Update → 看到日志列表
- 点任一行展开看所有字段
③ Dashboard + Lens
- 左侧 → Dashboard → Create
- 点 Create visualization
- 拖
@timestamp 到 X 轴 - 拖
status_code 到 Y 轴(选 Count) - 拖
status_code 到 Breakdown 分组 - Save → 加第二个图
📋 常用操作
| 操作 | 命令 |
| 查所有索引 | GET /_cat/indices?v |
| 查 mapping | GET /索引/_mapping |
| 删索引 | DELETE /索引 |
| 批量写 | POST /_bulk |
| 调查询 | Dev Tools 写好→贴到 Dashboard |
⚠️ 搜不到数据的三步排查:① Data View 索引模式匹配吗?② 时间范围对吗?③ ES 真的有数据吗(Dev Tools 先查 GET /_cat/indices)
✅ 阶段 3 小结
✅ 你现在已经会了
- ES 增删改查 + 搜索
- match/term/range/bool 四种查询
- terms/date_histogram/stats 聚合
- Kibana Discover + Dashboard
🤔 但还缺什么?
- 日志怎么自动进 ES 的?—— 下一节学 Fluent Bit
- 怎么把监控指标和日志串起来?—— 下下节学 OTel
- 怎么追踪一次请求经过多个服务?—— 下下下节学 Jaeger
💡 目前你已经搭建了两个独立的系统:Prometheus 管"数字",ES 管"文字"。下阶段把它们串起来。
💨 第 13 步:Fluent Bit——让日志自动流入 ES
启动 + 配一个最简单的管道
# 启动 Fluent Bit
docker run -d --name fb \
-v $(pwd)/fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf \
cr.fluentbit.io/fluent/fluent-bit:latest
# fluent-bit.conf(最简单的配置)
[INPUT]
name tail
path /var/log/nginx/access.log
tag nginx.access
parser nginx
mem_buf_limit 5MB
[OUTPUT]
name stdout # 先打印到控制台
match *
# 验证日志
docker logs fb
# 看到 Nginx 日志一行行打印出来了
调试技巧:先配 stdout 确认日志能收到,再改成 ES。不然不知道是采集的问题还是写入的问题。
然后把 stdout 改成 ES
# 把 OUTPUT 改成 ES
[OUTPUT]
name es
match *
host 192.168.1.100
port 9200
index nginx-logs-${DATE}
generate_id on
# 日志就自动进 ES 了!
# 去 Kibana Discover 刷新一下就能看到
再加个过滤:只留错误日志
[FILTER]
name grep
match nginx.*
regex status 5[0-9]{2}
# 加个标签
[FILTER]
name modify
match *
add env production
常改文件
| 文件 | 改了会怎样 |
| fluent-bit.conf | 整个管道——重启生效 |
| parsers.conf | 格式解析规则——自动加载 |
💨 第 13 步续:Fluent Bit 常见 3 个场景
场景 1:采集 JSON 格式日志
# parsers.conf
[PARSER]
Name json_log
Format json
Time_Key @timestamp
# 采集
[INPUT]
name tail
path /app/logs/*.json
parser json_log
场景 2:K8s 容器日志(DaemonSet 标配)
[INPUT]
name tail
path /var/log/containers/*.log
parser cri
tag kube.*
mem_buf_limit 50MB
[FILTER]
name kubernetes
match kube.*
merge_log On
labels On
场景 3:输出到 Kafka(大型部署)
[OUTPUT]
name kafka
match *
brokers kafka:9092
topics nginx-logs
Grok 常用模式
| 模式 | 匹配 |
| IP | 192.168.1.1 |
| NUMBER | 200, 3.14 |
| HTTPDATE | 07/May/2025:12:00:00 |
| GREEDYDATA | 任一内容 |
FB vs Logstash:FB ~650KB 内存 vs LS ~1GB。FB 的 200+ Grok 模式够覆盖 90% 日志解析场景。新项目统一用 FB。
🔗 第 14 步:OpenTelemetry——把指标、日志、追踪统一起来
❌ 没有 OTel 之前
# 三个库三种配置
from jaeger_client import Config # 追踪
from prometheus_client import Counter # 指标
import logging # 日志
# TraceID 无法自动串到日志
# 换后端(Jaeger→Zipkin)要改代码
✅ 有 OTel 以后
# 只用 OTel SDK
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("handle"):
handle()
# 一套 API 三信号
# 换后端只改 Collector 配置
# TraceID 自动注入日志
架构:应用 → Collector → 后端
flowchart LR
APP["应用
装 OTel SDK"] -->|"OTLP 协议"| COLL["OTel Collector
receiver→processor→exporter"]
COLL --> J["Jaeger"]
COLL --> P["Prometheus"]
COLL --> ES["Elasticsearch"]
💡 应用只需要对接 Collector,后端怎么换都行。这就是 OTel 的核心价值——解耦。
🔧 第 15 步:动手搭 OTel——从 SDK 到 Jaeger
启动 Jaeger + Collector
# Jaeger(all-in-one,含 Collector+UI)
docker run -d --name jaeger \
-p 16686:16686 -p 4317:4317 \
jaegertracing/all-in-one:latest
# OTel Collector(配置文件)
# collector.yml
receivers:
otlp:
protocols:
grpc: { endpoint: "0.0.0.0:4317" }
processors:
batch: { timeout: 1s }
exporters:
otlp:
endpoint: "jaeger:4317"
tls: { insecure: true }
debug: { verbosity: detailed }
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp, debug]
# 启动 Collector
docker run -d --name otel \
-p 4317:4317 \
-v $(pwd)/collector.yml:/etc/otelcol/config.yaml \
otel/opentelemetry-collector-contrib:latest
在应用里装 SDK
# Python 应用,自动埋点(一行启动)
pip install opentelemetry-instrumentation \
opentelemetry-instrumentation-flask
opentelemetry-instrument \
--traces_exporter otlp \
--service_name my-app \
python app.py
# 访问你的应用几次
# 然后打开 http://localhost:16686
# Service 下拉选 my-app
# 点 Find Traces
# → 看到第一条 Trace 的瀑布图!
环境变量速查
| 变量 | 作用 |
| OTEL_SERVICE_NAME | 服务名 |
| OTEL_EXPORTER_OTLP_ENDPOINT | Collector 地址 |
| OTEL_TRACES_SAMPLER_ARG=0.1 | 10% 采样率 |
🔬 第 16 步:怎么看 Trace 找到慢请求
Jaeger UI 界面
- 打开
http://localhost:16686
- 选 Service → 点 Find Traces
- 看到所有 Trace 列表,按耗时排序
- 找一个最长的点进去
flowchart LR
G["Gateway
10ms"] --> A["Auth
5ms"]
G --> U["User
3420ms ⚠️"]
U --> D["DB Query
3400ms ⚠️"]
D --> R["Redis
20ms"]
怎么找问题:最长的 span = 问题所在。上图中 User 服务花了 3420ms,里面 DB Query 花了 3400ms → 数据库查询慢是根因。
生产配置:使用 ES 做存储
# all-in-one 用内存,重启丢数据
# 生产用 ES
docker run -d --name jaeger \
-e SPAN_STORAGE_TYPE=elasticsearch \
-e ES_SERVER_URLS=http://es:9200 \
-p 16686:16686 -p 4317:4317 \
jaegertracing/all-in-one:latest
在 Grafana 中看 Trace
# 配 Jaeger 数据源
# Data Sources → Add → Jaeger
# URL: http://jaeger:16686
# 然后左侧 Explore → 选 Jaeger
# 搜 Trace,直接在 Grafana 里看瀑布图
🏗️ 第 17 步:把它们全部拼起来
flowchart TB
APP["你的应用"] -->|"日志"| FB["Fluent Bit
DaemonSet"]
APP -->|"traces+metrics"| SDK["OTel SDK
自动埋点"]
FB -->|"Bulk API"| ES["Elasticsearch
日志存储+搜索"]
SDK -->|"OTLP :4317"| COLL["OTel Collector
管道转发"]
COLL -->|"OTLP"| J["Jaeger
追踪存储"]
COLL -->|"Prometheus"| PRO["Prometheus
指标 TSDB"]
ES --> KB["Kibana
搜日志"]
ES & PRO & J --> G["Grafana
统一看板"]
PRO -->|"告警"| AM["Alertmanager"]
AM -->|"通知"| SL["Slack/钉钉/邮件"]
🟠 日志路径
应用日志 → FB → ES → Kibana/Grafana
🔵 指标路径
OTel SDK → Collector → Prometheus → Grafana
🟣 追踪路径
OTel SDK → Collector → Jaeger → Grafana
💡 三信号都走通后,你就可以:在 Grafana 看到一个指标异常 → 点一下跳转到对应时间的 Trace → 再点跳转到日志。一次排查操作,三份数据。
📋 配置文件速查——日常改什么
| 工具 | 文件 | 改了会怎么样 |
| Prometheus | prometheus.yml | 增减采集目标、改频率。POST /-/reload 热加载,不用重启 |
| Prometheus | alerts.yml | 改告警条件。promtool check rules 验证语法 |
| Grafana | datasources.yaml | 声明式配数据源。重启生效,放在 provisioning 目录 |
| Grafana | dashboards.yaml | 声明式导 Dashboard。导入后不改原 JSON |
| ES | elasticsearch.yml | 集群名/数据路径/网络/内存。生产改了要滚动重启 |
| ES | jvm.options | 堆大小 -Xms/-Xmx(不超过内存 50%,最多 32G) |
| Kibana | kibana.yml | ES 地址/语言/安全配置 |
| OTel Collector | collector.yml | 管道配置:receivers/processors/exporters。改了重启 |
| Fluent Bit | fluent-bit.conf | 输入→过滤→输出全链路。改了重启 |
| Fluent Bit | parsers.conf | 日志格式解析器。不改 FB 也能自动加载 |
| Jaeger | 环境变量 | 存储后端、采样策略。docker run -e 传入 |
❓ 常见问题速查
| 症状 | 可能原因 | 怎么查 | 怎么修 |
| Prometheus Target DOWN | 服务没暴露 /metrics | curl 目标/metrics | 确认服务在运行、端口正确 |
| Grafana 图空了 | PromQL 写错 / 时间不对 | Explore 里测同一条 PromQL | 修正 PromQL,改时间范围 |
| ES 搜不到数据 | Data View 不对 / 时间范围错 | GET /_cat/indices | 修正索引模式和时间范围 |
| Fluent Bit 没进 ES | ES 地址不对 / ES 不可写 | 加 stdout output 先调试 | 修 ES 地址,确认 ES 可用 |
| OTel Trace 看不到 | Collector 连不上 / 采样 0 | Collector 日志看 debug | 检查 OTLP endpoint 和采样率 |
| Jaeger 没数据 | Collector 没配 Jaeger | 看 Collector 日志 | 加 exporters: otlp: {endpoint: "jaeger:4317"} |
| 告警没触发 | for 时间未到 / 语法错 | GET /api/v1/rules | 查告警页面状态,promtool 验语法 |
🎯 总结
🟠 Prometheus + Grafana
最易上手。先配指标监控,建第一个 Dashboard。5 个 PromQL 函数覆盖 95% 场景。
🔎 ES + Kibana
日志存搜索。match/term/bool/aggs 四个查询类型走天下。Dev Tools 里练到顺手。
💨 Fluent Bit
日志自动采集入 ES。input→filter→output 三段配置,先 stdout 再改 ES。
🔗 OTel + Jaeger
统一采集标准。OTel SDK 埋一次,Collector 转发到 Jaeger/Prometheus/ES。
一句话记住每个工具:
ES 搜日志 / Prometheus 管数字 / Grafana 画图 / Fluent Bit 采日志 / OTel 统一 / Jaeger 追踪 / Kibana 搜 ES。
📋 端口速查 + 学习路线
所有工具端口
| 工具 | 端口 | 干什么 |
| Prometheus | :9090 | Web UI + API |
| Grafana | :3000 | Web UI (admin/admin) |
| ES | :9200 | REST API |
| Kibana | :5601 | Web UI |
| Fluent Bit | — | 无端口,配置文件 |
| OTel Collector | :4317 | OTLP gRPC 接收 |
| Jaeger | :16686 | Web UI |
学习路线(4 周)
第 1 天:Prometheus + Grafana
docker 启动 → 输 up → 建 Dashboard → 配告警
第 2 天:ES + Kibana
写入数据 → match→term→bool→aggs → 建 Dashboard
第 3 天:Fluent Bit
采集日志入 ES → 加过滤 → Grok 解析
第 4 天:OTel + Jaeger
SDK 自动埋点 → Collector 转发 → Jaeger 看 Trace