可观测性从零到上手指南:搭建日志、指标与追踪Demo环境

可观测性 从零到上手指南

1. 引言:为什么你需要可观测性?

传统监控的思维模式是“已知故障的发现与告警”。服务器宕机、CPU 过载、磁盘写满——这些场景可以被预设阈值捕捉。但当服务从单体演变为数十个微服务,故障模式从“服务不可用”转变为“请求响应慢 2 秒”、“支付成功率下降 0.5%”、“用户登录偶尔失败”,传统监控立刻失效。它无法回答一个关键问题:系统内部到底发生了什么?

这就是可观测性的价值所在。日志(Logs)告诉你发生了什么,指标(Metrics)告诉你发生频率和趋势,追踪(Traces)告诉你发生在哪个环节、耗时多少。三者并非独立工具,而是协同工作的数据管道。日志提供事件详情,指标提供聚合视图,追踪提供请求级因果关系。缺少任何一个,排查故障就像在黑暗里摸象。

本文的目标是:从零开始,搭建一个完整的可观测性 Demo 环境,理解三大支柱如何协同工作,并掌握将观测数据转化为可操作洞察的方法。读完本文,你将拥有一个可运行的本地可观测性栈,以及为应用注入观测数据的实战经验。

2. 第一步:理解三大支柱与核心工具选型

日志(Logs):结构化日志与 ELK/Loki 的定位

日志是最传统的观测数据,但传统日志有两个致命缺陷:非结构化(难以搜索和聚合)和存储成本高。可观测性要求日志必须是结构化的,例如 JSON 格式,包含时间戳、级别、服务名、请求 ID 等关键字段。

工具选型上,ELK(Elasticsearch, Logstash, Kibana)是成熟的全文搜索方案,适合复杂查询和长期存储。但 ELK 的资源消耗较高,且 Logstash 的管道处理存在性能瓶颈。Grafana Loki 则采用轻量级设计,只索引元数据(标签),不索引日志内容,存储成本大幅降低。Loki 与 Grafana 原生集成,适合已经采用 Prometheus + Grafana 的团队。

指标(Metrics):Prometheus 与 Grafana 的黄金指标(USE/RED 方法)

指标是聚合后的数值序列,用于监控系统健康度。Prometheus 是当前事实上的标准,采用拉模型(Pull)采集指标,通过 PromQL 查询语言进行灵活聚合。

指标设计需要方法论指导。USE 方法(Utilization, Saturation, Errors)适用于基础设施资源:CPU 利用率、内存饱和度、磁盘 I/O 错误率。RED 方法(Rate, Errors, Duration)适用于服务级别:每秒请求数、错误率、请求延迟分布(p50/p90/p99)。Grafana 作为可视化层,将 Prometheus 指标转化为实时仪表盘。

追踪(Traces):OpenTelemetry 与 Jaeger 的链路追踪原理

追踪解决的是“一个请求在多个服务间如何流转”的问题。每个请求被赋予一个 Trace ID,在每个服务节点生成一个 Span(跨度),记录该节点的操作名称、开始时间、结束时间、状态以及父子关系。

OpenTelemetry 是 CNCF 的标准化项目,提供统一的 API、SDK 和 Collector,支持自动或手动注入追踪数据。Jaeger 是成熟的追踪后端,负责存储、查询和展示追踪链路。OpenTelemetry Collector 作为数据采集网关,接收应用发出的追踪数据,处理后转发给 Jaeger 或其他后端。

3. 第二步:搭建最小可观测性环境(Docker Compose)

以下 docker-compose.yml 文件一键部署 Prometheus + Grafana + Loki + Tempo(Grafana 的追踪后端,兼容 Jaeger 协议)以及 OpenTelemetry Collector。

version: '3.8'

说实话,services:
  # 指标存储与查询
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  # 可视化面板
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - ./grafana-datasources.yml:/etc/grafana/provisioning/datasources/datasources.yaml

  # 日志存储(轻量级)
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml

  # 追踪存储
  tempo:
    image: grafana/tempo:latest
    ports:
      - "3200:3200"   # 接收 OTLP 数据
      - "9095:9095"   # Jaeger gRPC
    command: -config.file=/etc/tempo.yaml

  # 统一数据采集网关
  otel-collector:
    image: otel/opentelemetry-collector-contrib:latest
    ports:
      - "4317:4317"   # OTLP gRPC
      - "4318:4318"   # OTLP HTTP
    volumes:
      - ./otel-collector-config.yml:/etc/otel-collector-config.yml
    command: --config=/etc/otel-collector-config.yml

配套的 otel-collector-config.yml 配置如下:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

exporters:
  prometheus:
    endpoint: "0.0.0.0:8889"
  loki:
    endpoint: http://loki:3100/loki/api/v1/push
  otlp:
    endpoint: tempo:4317
    tls:
      insecure: true

service:
  pipelines:
    metrics:
      receivers: [otlp]
      exporters: [prometheus]
    logs:
      receivers: [otlp]
      exporters: [loki]
    traces:
      receivers: [otlp]
      exporters: [otlp]

启动命令:

docker-compose up -d

验证数据流是否正常工作:访问 Grafana(http://localhost:3000,账号 admin/admin),在数据源配置中分别添加 Prometheus(http://prometheus:9090)、Loki(http://loki:3100)和 Tempo(http://tempo:3200)。如果数据源状态显示绿色,说明采集网关与存储后端已联通。 (突然有点感慨,不管了)

4. 第三步:为应用注入观测数据(代码实战)

以 Python 应用为例,使用 OpenTelemetry SDK 自动采集 HTTP 请求的指标、日志和追踪。

一上来安装依赖:

pip install opentelemetry-distro opentelemetry-exporter-otlp

创建应用 app.py

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
import flask
import requests

# 配置追踪导出到 OpenTelemetry Collector
trace.set_tracer_provider(TracerProvider())
span_exporter = OTLPSpanExporter(endpoint="http://localhost:4317", insecure=True)
trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(span_exporter))

# 自动注入 Flask 和 requests 库的追踪
app = flask.Flask(__name__)
FlaskInstrumentor().instrument_app(app)
RequestsInstrumentor().instrument()

@app.route("/")
def hello():
    # 手动创建一个 Span 记录业务逻辑
    with trace.get_tracer(__name__).start_as_current_span("process_request"):
        response = requests.get("https://httpbin.org/delay/1")
        return {"message": "Hello, Observability!", "status": response.status_code}

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

运行应用:

python app.py

访问 http://localhost:5000/,应用会自动生成追踪数据,通过 OpenTelemetry Collector 发送到 Tempo。同时,Flask 的请求日志会被 Collector 采集并推送到 Loki,请求的延迟指标(如 http.server.duration)会暴露给 Prometheus。

在 Grafana 中创建第一个仪表盘:添加一个“延迟分布”面板,查询 Prometheus 指标 http.server.duration_bucket;添加一个“错误率”面板,使用 rate(http.server.duration_count{http.status_code=~"5.."}[5m]) / rate(http.server.duration_count[5m])。实时观察请求延迟和错误率变化。

5. 第四步:从 Demo 到生产——关键落地建议

数据存储与采样策略:避免成本失控

可观测性数据量增长极快。一个中等规模的微服务集群,每天可能产生 TB 级的日志和指标。必须实施采样策略:对追踪数据采用头部采样(基于 Trace ID 哈希)或尾部采样(基于延迟或错误条件),保留 1%-10% 的完整链路。日志采用结构化压缩,指标采用降采样(如 1 分钟聚合为 1 小时聚合)。设置数据保留周期,热数据 7 天,温数据 30 天,冷数据归档到对象存储。

告警规则设计:基于 SLO 的告警而非阈值告警

传统阈值告警(如 CPU > 80%)容易产生告警风暴。推荐基于服务等级目标(SLO)设计告警:定义错误预算,当错误率接近消耗完错误预算时触发告警。例如,SLO 为 99.9% 可用性(每月允许 43 分钟不可用),当过去 1 小时错误率消耗了 10% 的错误预算时告警。这种告警具有业务意义,且能提前预警趋势问题。

团队协作:建立可观测性文化,避免数据孤岛

可观测性不是运维团队的单向输出。开发团队需要参与定义关键指标(如 RED 指标),并为代码注入追踪和结构化日志。建立“可观测性设计评审”环节,每个新服务上线前必须通过观测数据质量检查。共享 Grafana 仪表盘和告警规则,让所有团队成员能基于同一份数据做决策,而非各自维护 Excel 报表。

6. 总结:下一步行动清单

日志、指标、追踪三大支柱的协同价值在于:日志提供事件详情,指标提供聚合趋势,追踪提供请求级因果关系。三者结合,才能从“系统是否运行”升级为“系统为何如此运行”。

推荐学习资源:OpenTelemetry 官方文档(opentelemetry.io)是核心参考;Grafana Playground(play.grafana.org)提供在线体验环境,无需本地安装即可探索仪表盘。

行动号召:从今天起,为你的服务添加第一个追踪 Span。选择你熟悉的语言,引入 OpenTelemetry SDK,在关键业务逻辑处创建一个 Span,观察它在 Tempo 中的完整链路。这一步做完,你就跨入了可观测性的门槛。

---

版权声明: 本文为博主原创文章 (AI 辅助生成),遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

posted @ 2026-05-12 21:12  见山大叔  阅读(58)  评论(0)    收藏  举报