基于Jaeger的分布式追踪系统搭建与配置详解

本文从实际需求出发,详解基于Jaeger的分布式追踪系统搭建与配置,涵盖核心组件、部署步骤、采样策略、存储选型及与Prometheus、OpenTelemetry的集成,帮助你快速构建可观测性基础设施。

基于Jaeger的分布式追踪系统搭建与配置详解
封面图:ZuCDN · ZuCDN 原创

当你的服务从单体拆分为微服务,一次用户请求可能横跨十几个服务,问题定位变得异常困难。分布式追踪系统正是为此而生,而Jaeger作为CNCF毕业项目,是目前应用最广泛的链路追踪平台之一。本文将从实际搭建者的视角,带你逐步完成基于Jaeger的分布式追踪系统搭建与配置,并解答过程中常见的问题。

为什么选择Jaeger?先明确你的需求

在动手之前,先问自己三个问题:你的服务规模有多大?需要追踪哪些指标?团队对可观测性的投入有多少?Jaeger的优势在于:它提供了完整的追踪数据收集、存储、查询和UI展示能力,且支持多种存储后端,包括Elasticsearch、Cassandra和Badger。如果你已经有Prometheus监控体系,Jaeger可以很好地与之互补——Prometheus负责指标监控,Jaeger负责链路追踪。根据Prometheus官方文档,Prometheus收集并存储指标作为时间序列数据,而链路追踪则关注请求在服务间的传播路径。两者结合,才能构建完整的可观测性。

核心组件:理解Jaeger的架构

Jaeger的架构包含几个关键组件:agent、collector、query和storage。agent作为sidecar运行在每个节点上,负责接收应用发送的追踪数据并转发给collector;collector负责校验、索引和存储数据;query服务提供API和UI查询;storage则负责持久化。在搭建之前,理解这些组件的职责至关重要,否则配置时容易混淆。

搭建步骤:从单体部署到容器化

最简单的起步方式是使用Jaeger提供的all-in-one镜像,它包含了所有组件,适合开发和测试环境。但生产环境建议分离部署。以下是一个基于Docker Compose的示例配置:

version: '3'
services:
  jaeger-collector:
    image: jaegertracing/jaeger-collector:1.53
    command: ["--collector.zipkin.host-port=9411"]
    ports:
      - "14269"
      - "14268"
      - "14250"
      - "9411"
    environment:
      - SPAN_STORAGE_TYPE=elasticsearch
      - ES_SERVER_URLS=http://elasticsearch:9200
    depends_on:
      - elasticsearch
  jaeger-query:
    image: jaegertracing/jaeger-query:1.53
    ports:
      - "16686:16686"
      - "16687"
    environment:
      - SPAN_STORAGE_TYPE=elasticsearch
      - ES_SERVER_URLS=http://elasticsearch:9200
    depends_on:
      - elasticsearch
  jaeger-agent:
    image: jaegertracing/jaeger-agent:1.53
    command: ["--reporter.grpc.host-port=jaeger-collector:14250"]
    ports:
      - "5775:5775/udp"
      - "6831:6831/udp"
      - "6832:6832/udp"
      - "5778:5778"
    depends_on:
      - jaeger-collector
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.10
    environment:
      - discovery.type=single-node
    ports:
      - "9200:9200"

启动后,访问query服务的16686端口即可打开Jaeger UI。但你可能需要根据实际环境调整端口和存储配置。

配置详解:采样策略与存储选择

生产环境必须配置采样策略,否则高流量下存储成本会失控。Jaeger支持三种采样策略:const(全部采样)、probabilistic(概率采样)和rateLimiting(限速采样)。通常使用probabilistic,例如设置0.1表示采样10%的请求。你可以在collector启动参数中指定:

--sampling.strategies-file=/etc/jaeger/sampling.json

采样配置文件示例:

{
  "default_strategy": {
    "type": "probabilistic",
    "param": 0.1
  }
}

存储选型方面,Elasticsearch适合大规模生产,但运维复杂;Badger是嵌入式存储,适合单机小规模;Cassandra适合超大规模。如果团队已有Elasticsearch集群,直接复用是常见做法。注意,Jaeger的存储层需要创建索引模板,首次启动时会自动初始化。

数据采集:如何接入你的应用

Jaeger支持多种语言客户端,以及通过OpenTelemetry进行标准化采集。OpenTelemetry官方文档强调,它是一个厂商中立、开源的观测框架,用于生成、收集和导出遥测数据。如果你的服务已经接入OpenTelemetry,可以将数据导出到Jaeger。例如,使用OTLP协议导出:

otel:
  traces:
    exporter: otlp
    endpoint: jaeger-collector:4317

如果使用Jaeger原生客户端,需要配置agent地址和端口。例如Java应用使用Jaeger tracer:

JaegerTracer tracer = new JaegerTracer.Builder("service-name")
    .withReporter(new RemoteReporter.Builder()
        .withSender(new UdpSender("jaeger-agent", 6831, 0))
        .build())
    .build();

注意,agent使用UDP端口6831接收数据,如果网络环境对UDP有限制,可以改用HTTP或gRPC直接发送到collector。

与Prometheus集成:构建完整可观测性

链路追踪和指标监控是互补的。Jaeger本身不提供指标监控,但可以借助Prometheus监控Jaeger自身的运行状态。根据Prometheus官方文档,Prometheus是一个开源系统监控和警报工具包,收集并存储指标作为时间序列数据。你可以在Jaeger组件中暴露/metrics端点,然后配置Prometheus抓取。例如,collector的监控指标包括接收的span数、存储延迟等。集成后,你可以在Grafana中同时展示指标和追踪数据。

常见误区与失败条件

在搭建过程中,有几个常见的坑:

  • 端口配置错误:agent默认端口6831是UDP,如果防火墙只开放了TCP,数据会丢失。
  • 采样策略未生效:修改采样配置文件后,需要重启collector或通过API动态更新,否则仍使用默认策略。
  • 存储后端版本不兼容:Jaeger对Elasticsearch版本有要求,使用过旧或过新的版本可能导致索引失败。
  • 忽略上下文传播:跨服务传播trace context时,需要确保HTTP头或消息队列的header正确传递,否则链路断裂。

CI/CD中的自动化部署

如果你使用GitHub Actions进行CI/CD,可以自动化Jaeger的部署。GitHub Actions官方文档指出,你可以在仓库中自动化、自定义和执行软件工作流。例如,在每次代码推送时,通过工作流构建镜像并更新Jaeger配置。但要注意,Jaeger本身不是CI/CD工具,它只是可观测性组件。

结语:从搭建到落地

搭建Jaeger只是第一步,更重要的是让团队真正使用它来定位问题。建议从小规模开始,逐步完善采样策略和存储规划,并与其他可观测性工具集成。本文基于官方文档和常见实践,但具体版本行为可能有所变化,请以实际环境为准。

参考资料

延伸阅读