Skip to content
Jaeger v2 架构与组件

Jaeger v2 架构与组件

基线:Jaeger v2.22.0(2026-10-06 发布,官方 docs 当前 latest = 2.22)。本章所有配置均逐字取自 GitHub tag v2.22.0 与 docs.jaegertracing.io/docs/2.22/ 页面,来源在每节标注。

如果只用一句话概括 Jaeger v2 的架构革命:Jaeger 不再自研 collector,而是把自己重写成 OpenTelemetry Collector 的一个定制发行版——OTel 官方组件打底,contrib 组件补齐,再加上 Jaeger 自己的存储、查询、采样五个专有 extension/exporter/processor。

打个比方:v1 时代的 Jaeger 像一套自装软件——collector、query、agent 各装各的,配置靠各自的启动参数;v2 则像预装全家桶的定制操作系统:开机就是一个标准 OTel Collector 内核,管道(receivers/processors/exporters)的玩法完全一致,你要做的只是往配置里填 Jaeger 自家的应用。学会 v2 的配置,等于同时学会了 OTel Collector——这份知识在你接 metrics、logs 时可以直接复用。相关心智模型见 01-核心概念.md,本章专注"组件怎么组装、进程怎么切分"。

从 1.x 三件套到单二进制多角色

v1 的部署单位是"组件即进程":agent、collector、query(加上 Kafka 场景的 ingester)各自是独立二进制、独立镜像、独立 flag 集。v2 把这些全部折叠进一个 jaeger 二进制,进程扮演什么角色完全由 --config 指向的 YAML 决定:

v1 组件(独立二进制) v2 中的对应物 现状
jaeger-agent(UDP 转发) 内置 jaeger receiver 直接收 Thrift/UDP;agent 角色可配置但不推荐 官方立场:需要 per-host/per-pod agent 层时改用标准 OTel Collector(docs/2.22/architecture)
jaeger-collector jaeger 二进制 + collector 角色的配置 独立 v1 镜像已退役,最后版本 1.76(download 页标 Deprecated)
jaeger-query jaeger 二进制 + jaeger_query extension 同上
jaeger-ingester jaeger 二进制 + Kafka receiver 的配置 同上
all-in-one 调试镜像 同一个 jaeger 二进制,不带 --config 时的默认行为 内存存储,重启即失

官方对角色划分原文(docs/2.22/architecture,“Roles"一节):

  • collector:接收应用上报的 trace 数据并写入存储后端;
  • query:对外提供查询 API 和 UI;
  • ingester:从 Kafka 消费 span 写入存储,用于 collector-Kafka-ingester 的切分架构;
  • all-in-one:collector 与 query 合一的单进程;
  • agent:主机代理或应用 sidecar——“While Jaeger can be configured for this role, we recommend using the standard OpenTelemetry Collector instead”,因为 agent 层往往还要顺手处理 metrics 与 logs,那是标准 Collector 的主场。

选 all-in-one 还是 collector/query 分离,官方明说"a matter of preference”:用外部存储时两者都能水平扩展,差别在于分离部署可以把读流量和写流量拆开源伸缩,并施加不同的访问与安全策略。展开见 03-部署与Kubernetes.md。

还有一个时间线问题要摆在桌面上:v1 已经走到头了。官方 issue #6321 明确 1.x 的 end-of-life 定在 2025-12-31,最后一个 v1 release 是 1.76.0(2025-12-03);docs 站的版本切换器如今也只剩 2.22(latest)与 1.76(archive) 两档。所以本手册的结论不是"v2 是新选项",而是"留在 v1 才是需要申报例外状态的遗留项"——v1→v2 的官方迁移指南存在(Google Doc),但正文在本手册基线环境不可达,本章与 03-部署与Kubernetes.md 的对照全部以 2.22 文档与源码实测为准。

v2 发行版解剖

三层组件构成

docs/2.22/architecture(“Jaeger Binary"一节)列出 v2 二进制内的组件来自三层:

  1. OTel 官方 upstream 组件:OTLP receiver、batch processor、attributes processor 等核心件;
  2. opentelemetry-collector-contrib 组件:Kafka exporter/receiver、tail sampling processor 等——这是 v1 里要靠独立进程或阉割版实现的能力,v2 直接白嫖 contrib;
  3. Jaeger 自有组件:下面五个,是 Jaeger 区别于"裸 Collector"的全部家当。

五个 Jaeger 自有组件

按 docs/2.22/architecture(“Jaeger Components"一节)逐个说职责,注意它们在配置里的段位不同:

组件 配置段位 职责
jaeger_storage extensions 存储后端注册中心。官方定义:“Extensible hub for storage backends supported in Jaeger. It provides all other Jaeger components access to Jaeger storage implementations”。Collector 写、Query 读,都按名字引用这里注册的 backend
jaeger_storage_exporter exporters(也可放 connectors) 写入器:把管道里流过的 span 写进 jaeger_storage 中配置的后端
jaeger_query extensions 读取 + UI:起 HTTP/gRPC 服务器,暴露查询 API(16685/16686)和 Jaeger UI
remote_sampling extensions 采样策略服务:起 HTTP(5778)/gRPC(5779)端点,按静态策略文件或自适应结果给客户端下发采样率
adaptive_sampling processors 反馈式采样计算器:“observes all the traces collected by Jaeger and dynamically calculates sampling probabilities”(configuration 页原文),按服务/端点统计流量反推概率,写回供 remote_sampling 下发

为什么需要 jaeger_storage 这个中间层,而不像标准 OTel 那样"每种目的地一个 exporter”?官方在 configuration 页解释得很直白:OTel Collector 只管写,而 Jaeger 还要通过 UI 和查询 API 读,必须有一个机制让 exporter 和 query extension 共享同一份后端配置——jaeger_storage extension 就是干这个的。理解这一点,v2 的配置就全通了:后端在 extension 里注册一次,写侧用名字引用,读侧也用名字引用。

外加一个借来的 connector

架构图上还有一个非 Jaeger 自有但生产必备的角色:spanmetrics connector(OTel contrib 组件,architecture 页列在 Connectors 下:“Generates metrics from span data”)。它把 span 流实时折算成 RED 指标(请求数/错误数/时延分布),是 Jaeger UI 里 SPM(服务性能监控)菜单的数据源,详见 08-可观测性联动.md;部署骨架在仓库的 cmd/jaeger/config-spm.yaml。

文字版数据流

把上面拼起来,一个典型 collector 进程内部是这样流动的:

应用 SDK(OTLP / Jaeger Thrift / Zipkin)
        │
        ▼
receivers ── otlp(4317 gRPC / 4318 HTTP)
        │     jaeger(14250 / 14268 / 6831 / 6832,内置未删)
        │     zipkin(9411)/ kafka(ingester 角色用)
        ▼
processors ─ batch(攒批)
        │     adaptive_sampling(反馈计算,配合 remote_sampling)
        ▼
exporters ── jaeger_storage_exporter ──▶ jaeger_storage extension
              (按 trace_storage 名字选后端)     │  memory / badger /
                                                │  elasticsearch / cassandra /
connectors ─ spanmetrics ─▶ Prometheus 拉取     │  clickhouse / grpc(远端)
                                                ▼
                                        存储后端(ES/Cassandra/...)
                                                
读侧:jaeger_query extension ──按 storage.traces 名字──▶ 同一个 jaeger_storage
        │  16686:Jaeger UI + /api/v3/* JSON
        └  16685:jaeger.api_v3.QueryService gRPC
采样侧:remote_sampling extension ◀── adaptive_sampling 写回的概率
        │  5778 HTTP /sampling、5779 gRPC
        └  客户端 SDK 定时拉取策略(见 06-采样.md)

读侧和写侧共享 extension 里的同一份后端注册表,这是 v2 与"collector 写 ES、query 也连 ES 但各配各的"v1 模式的本质区别。

发行版里还有哪些牌可打

除 Jaeger 自有组件外,默认发行版开箱还带着 contrib 的一批常用件(docs/2.22/architecture 组件清单,写配置时段位对应):

段位 组件 在 Jaeger 部署里的典型用途
receivers kafka ingester 角色消费(模式四,见 03-部署与Kubernetes.md)
receivers nop query-only 部署的占位管道,不占任何入口端口
processors tail_sampling 尾采样:基于完整 trace 决策,见 06-采样.md;仓库有两份范例 config-tail-sampling-*.yaml
processors memory_limiter collector 过载时的背压保护,见 09-性能与运维.md
processors attributes 过滤/改写/富化 span:补 k8s 环境信息、脱敏敏感属性、裁剪体积
processors filter 丢弃指定 span/事件,官方在组件清单里直接警示"may cause broken traces”——会切碎调用链
exporters kafka / otlp / otlp_http 写队列或转发给其他 collector;otlp 还能把采样后的数据转发进别的后端
exporters prometheus spanmetrics 指标落地(见 08-可观测性联动.md)
exporters debug / nop 排障打印 / query-only 占位
extensions zpages / expvar / pprof 进程内部状态与剖析,all-in-one 与示例配置分别挂在 27778/27777/1777

这份清单决定了 v2 的扩展上限:任何 OTel 生态的 receiver/processor/exporter,理论上都能装进 Jaeger 的管道——要么发行版已有,要么用下文的 OCB 自己编译进去。

单一二进制与角色

v1 之所以有 jaeger-agent/collector/query/ingester 四个镜像,是因为每套角色都是独立代码路径,编译时就得选边站。v2 反过来:角色之间共享同一个管道引擎和同一批 extension,唯一差别是"这个进程挂载了哪几个组件"——而这恰好是配置文件天然能表达的事。所以官方干脆取消角色子命令,把"你是谁"完全交给 --config,一个二进制覆盖全部形态。

角色由 –config 决定,没有子命令

先破除一个惯性预期:v2 的 jaeger 二进制没有 collector/query/agent 这些角色子命令。源码 cmd/jaeger/internal/command.go(tag v2.22.0)显示,根命令由 otelcol.NewCommand 包装而来,和 OTel Collector 的 otelcol CLI 一模一样,--config、--set、--feature-gates 等全是它的原生 flag。

没有 --config 时发生了什么?command.go 拦截了 otelcol 的 RunE:检测到零个 --config 就注入二进制内嵌的 all-in-one 配置(内存存储),并打印两行日志——原文逐字如下:

No '--config' flags detected, using default All-in-One configuration with memory storage.
To customize All-in-One behavior, pass a proper configuration.

docker run 不带任何参数就能出 UI,机制就在这。内嵌的 cmd/jaeger/internal/all-in-one.yaml 本身就是最好的官方教材,值得逐行读一遍(本章末尾给出仓库 config.yaml 全文,内嵌版与其高度相似,差异见下文端口一节)。

子命令只有三个(源码 NewCommand 里 AddCommand):

  • jaeger version — 版本信息;
  • jaeger docs — 把配置结构导出成文档;
  • jaeger mappings — 生成 Elasticsearch/Cassandra 的索引 mapping。

--set 可以打补丁式覆盖配置项,官方 configuration 页的例子:--set "receivers.otlp.protocols.grpc.endpoint=0.0.0.0:4317"——all-in-one 模式不改文件临时换监听地址很好用。

工具是独立二进制

Jaeger 生态里仍然有几个独立小工具,源码在仓库 cmd/ 目录(v2.22.0 实测清单):anonymizer(trace 脱敏)、es-index-cleaner(ES 索引清理)、es-rollover(ES 滚动别名)、esmapping-generator(mapping 生成)、remote-storage(独立远端存储服务,见 03-部署与Kubernetes.md)、tracegen(压测造数)。发布 release 资产里它们打包成 jaeger-tools-2.22.0-<os>-<arch>.tar.gz,与主二进制分开下载;Docker 侧则对应 jaeger-es-index-cleaner、jaeger-remote-storage 等独立镜像(download 页均有 v2 条目)。

主二进制的发布资产(v2.22.0 release 实测,tag 发布 2026-10-06):jaeger-2.22.0-{linux,darwin,windows}-{amd64,arm64}.tar.gz(linux 另有 ppc64le/s390x,windows 附带 .zip),每个包都配 .sha256sum.txt 校验与 .asc GPG 签名,并有整包 jaeger-SBOM.spdx.json 供应链清单——生产准入要验签/留 SBOM 时直接取用。

用 OCB 裁剪出你自己的发行版

既然 v2 是 Collector 发行版,就能用 OpenTelemetry Collector Builder(ocb)重切组件。custom-distribution 页给出的最小 manifest 骨架(节选,gomod: github.com/jaegertracing/jaeger v2.19.0,官方示例版本如此,基线 2.22 时替换为对应 tag 即可):

dist:
  module: github.com/example/my-jaeger
  name: jaeger
  description: My custom Jaeger distribution
  output_path: ./build
telemetry:
  gomod: github.com/jaegertracing/jaeger v2.19.0
  import: github.com/jaegertracing/jaeger/components/telemetry
extensions:
  - gomod: github.com/jaegertracing/jaeger v2.19.0
    import: github.com/jaegertracing/jaeger/components/extension/jaegerstorage
  - gomod: github.com/jaegertracing/jaeger v2.19.0
    import: github.com/jaegertracing/jaeger/components/extension/jaegerquery
receivers:
  - gomod: github.com/jaegertracing/jaeger v2.19.0
    import: github.com/jaegertracing/jaeger/components/ext/receiver/otlpreceiver
exporters:
  - gomod: github.com/jaegertracing/jaeger v2.19.0
    import: github.com/jaegertracing/jaeger/components/exporter/storageexporter
processors:
  - gomod: github.com/jaegertracing/jaeger v2.19.0
    import: github.com/jaegertracing/jaeger/components/ext/processor/batchprocessor

两个实操要点(均出自官方页):Jaeger 自有组件在 components/extension|exporter|processor/,借来的 OTel 组件在 components/ext/(re-export,保证与主模块版本一致);构建时建议 ocb --config builder.yaml --skip-strict-versioning,否则 ocb 会因 Jaeger 组件与被转述的上游版本号不一致而拒绝构建。收益场景:只要 OTLP 入口的极简 collector 可以剔掉 Kafka/Zipkin/Thrift 接收器,缩小二进制体积和攻击面。

配置系统:与 otelcol 同构,但没有热加载

五段式

v2 配置文件的骨架与 OTel Collector 完全同构,六个段位各司其职:

receivers: {}      # 数据入口:otlp / jaeger / zipkin / kafka / nop
processors: {}     # 管道内加工:batch / adaptive_sampling / tail_sampling
connectors: {}     # 跨管道转换:spanmetrics / forward
exporters: {}      # 数据出口:jaeger_storage_exporter / kafka / prometheus
extensions: {}     # 管道外服务:jaeger_storage / jaeger_query / remote_sampling / healthcheckv2 / pprof ...
service:           # 装配:哪些组件进哪条 pipeline、extensions 列表、自监控 telemetry
  extensions: []
  pipelines:
    traces:
      receivers: []
      processors: []
      exporters: []
  telemetry: {}

service.telemetry:Jaeger 自己的可观测性

六段式里的 service 段还藏着一个子段 telemetry,管 Jaeger 进程自身的指标与日志(v2.22.0 各示例配置逐字可见其结构):

service:
  telemetry:
    resource:
      service.name: jaeger          # 自监控数据归属的资源标签
    metrics:
      level: detailed               # basic 只有核心指标,detailed 含每组件收发/队列
      readers:
        - pull:
            exporter:
              prometheus:
                host: 0.0.0.0
                port: 8888          # /metrics 抓取端点
    logs:
      level: debug                  # 生产建议 info

三个实操含义:其一,8888 的 Prometheus 端点是容量规划与告警的主数据源(积压、丢弃计数都从这里来,指标清单见 09-性能与运维.md);其二,resource.service.name 让 Jaeger 的自监控数据在链路侧可被识别——理论上你甚至能让 collector 消费自己的遥测,官方在示例配置里留了注释"TODO Initialize telemetry tracer once OTEL released new feature",说明自监控 tracing 在这个版本仍未默认接通,别在 UI 里苦等 Jaeger 自己的 span;其三,level: detailed 开销不小,高吞吐写入口可降回 basic。

顺带一提一个管道形状的坑:jaeger_storage_exporter 默认在 span 入队即 ACK(存储还没落盘就告诉上游"成功");官方 configuration 页明确"当管道不能丢 span 时,queue 需要 wait_for_result: true,且此时管道不能再叠 batch processor"。不丢数据的完整投递语义(Delivery Guarantees)见 04-存储后端.md 与 09-性能与运维.md。

cmd/jaeger/ 下随仓库附了 25 个 config-*.yaml 现成范本(v2.22.0 tag 实测计数):badger、cassandra、clickhouse,elasticsearch 与 opensearch 各四变体(base/auto-rollover/data-stream/manual-rollover),kafka-collector、kafka-ingester(含 dead-letter、sync 变体)、query-only、remote-storage 前后端、spm 四连、尾采样两份、ocb-smoketest——基本覆盖了官方支持的所有部署形态,改两行就能用。存储后端逐个的参数细节见 04-存储后端.md。

环境变量只能"插值",不能"驱动"

configuration 页原文:“Jaeger v2 can only be configured via a config file, it does not recognize environment variables in the same way as Jaeger v1 used to do."。v1 那套 COLLECTOR_*、QUERY_*、BADGER_* 环境变量到 v2 全部失效,进程只认 --config。YAML 内部倒是支持 OTel confmap 的插值语法,官方示例:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "${env:JAEGER_LISTEN_HOST:-localhost}:4317"

${env:VAR:-default} 让容器里设 JAEGER_LISTEN_HOST=0.0.0.0、本地裸跑默认 localhost 共用同一份配置——官方镜像正是这么做的(Dockerfile ENV JAEGER_LISTEN_HOST=0.0.0.0)。例外提醒:控制 OpenTelemetry Go SDK 自身行为的环境变量(如 OTEL_EXPORTER_OTLP_ENDPOINT)Jaeger v2 仍然自动识别,那是 SDK 的事,不是 collector 配置。

注意:没有 SIGHUP,也没有整体热加载——这是 v1 迁移最容易踩空的一条。 OTel Collector 的 confmap 在进程启动时一次性解析配置,Jaeger v2 照单全收:改 YAML 必须重启进程生效,SIGHUP 不会重载任何东西(官方无此承诺)。唯一的例外是 remote_sampling 的 file 策略:sampling 页原文 “The file will be automatically reloaded if its contents change”,all-in-one 内嵌配置里还默认写了 reload_interval: 1s。也就是说:入口协议、管道、存储参数改完都要滚动重启;只有采样策略 JSON 是热更的。给 v1 老用户做迁移预期管理时,把这一条写在操作手册第一页。

端口与 API 总表

来源:docs/2.22/architecture/apis(“Default Ports"三张表)+ cmd/jaeger/Dockerfile EXPOSE。所有默认端口都可在配置里覆盖(“They can be overwritten by user via configuration”)。

写入口(collector 角色):

端口 协议 端点/格式 官方稳定性
4317 gRPC OTLP ExportTraceServiceRequest Stable
4318 HTTP /v1/traces,OTLP Protobuf 或 JSON Stable
9411 HTTP /api/v1/spans、/api/v2/spans,Zipkin v1/v2 Stable
6831 UDP Legacy Thrift compact 编码 Stable, Deprecated
6832 UDP Legacy Thrift binary 编码 Stable, Deprecated
14250 gRPC jaeger.api_v2.CollectorService,Legacy Protobuf Stable, Deprecated
14268 HTTP POST /api/traces,Thrift binary,Content-Type: application/vnd.apache.thrift.binary Stable, Deprecated

读出口(query 角色/extension):

端口 协议 端点/格式 官方稳定性
16685 gRPC jaeger.api_v3.QueryService(推荐;兼容 api_v2) Stable
16686 HTTP Jaeger UI;/api/v3/* 官方 JSON;/api/* internal v3 Stable / internal 仅内部

采样服务(remote_sampling extension):

端口 协议 端点/格式
5778 HTTP /sampling,sampling.proto 的 Protobuf-to-JSON 映射
5779 gRPC jaeger.api_v2.SamplingManager

管理与观测面(来自内嵌 all-in-one.yaml、config.yaml 示例与 Dockerfile):

端口 来源 用途
8888 telemetry.prometheus Collector 自监控指标 /metrics
13133 / 13132 healthcheckv2 /status HTTP 健康检查 / gRPC 健康检查
27777 / 27778 expvar / zpages(all-in-one 内嵌默认开) 运行时调试
1777 pprof(config.yaml 示例开启) Go 性能剖析
8889 spanmetrics/ingester 示例配置 SPM 指标出口示例(Helm Service 也按此暴露)
17271 / 17270 remote storage gRPC 存储服务端口 / admin 端口(独立 jaeger-remote-storage 工具,见 03-部署与Kubernetes.md)
12345 -debug 镜像 Delve headless 调试

Dockerfile 的 EXPOSE 清单可当快速核对表:5778 5779 4317 4318 14268 14250 9411 16686 13132 13133。注意没有 5775——那是 v1 agent 的 UDP 端口,v2 默认配置里没有它(Helm chart Service 模板里的 5775/14267 属残留,后面章节讲)。

注意:legacy 端口没有被移除。 常有人把"Legacy Thrift 全部 Deprecated"读成"v2 删了这些端口”——错。v2 内建 jaeger receiver(config.yaml 中 protocols: grpc / thrift_binary / thrift_compact / thrift_http 默认启用),6831/6832/14250/14268 照常工作,Deprecated 只是官方"将来会逐步淘汰、不要在新项目里选"的信号。存量 Jaeger 客户端 Thrift 上报可以先继续跑,但迁移到 OTLP 的排期建议放在升级之前,见 05-Go客户端埋点.md 与 06-采样.md。 另一点官方口径:新写入口只推荐 OTLP;Zipkin 格式 Stable 可继续用;程序化查询走 16685 的 api_v3 gRPC,UI 用的 /api/* internal JSON 明确"undocumented and subject to change”,不要拿它当对外集成面,见 07-查询UI与API.md。

2026 视角的三个新配置项(jaeger_query)

cmd/jaeger/config.yaml(v2.22.0)里 jaeger_query extension 多了几处值得一说的键:

  • otlp_proxy:让 UI 同源接收 OTLP——target: http://127.0.0.1:4318 配置后,浏览器侧埋点把 span 发到 16686 上的 /api/otlp/v1/*,由 query extension 转发给本进程的 OTLP HTTP receiver。省掉前端单独记 collector 地址的跨域麻烦。
  • ai.mcp:2026 年新增,在 query 端口挂出 /api/ai/mcp/ 的 MCP 工具端点,让 AI Agent 直接查 Jaeger 数据;配置注释原文写明它"replaces the retired standalone jaeger_mcp extension"——独立的 jaeger_mcp extension 已退役,别再找它。
  • max_clock_skew_adjust:跨主机时钟漂移的自动纠偏上限,默认 0s 即关闭。v1 时代默认开启的 skew 调整在 v2 里成了显式 opt-in(常见值 30s),设为 0 就不会出现"server span 被强行挪到 parent 中间"的困惑。

最小完整 config.yaml 生产骨架

以下逐字摘自 GitHub jaegertracing/jaeger@v2.22.0:cmd/jaeger/config.yaml(仅删去了版权头与两处 TODO 注释),它同时是"all-in-one + 采样 + pprof"形态的官方推荐底稿:

service:
  extensions: [jaeger_storage, jaeger_query, remote_sampling, healthcheckv2, pprof]
  pipelines:
    traces:
      receivers: [otlp, jaeger, zipkin]
      processors: [batch, adaptive_sampling]
      exporters: [jaeger_storage_exporter]
  telemetry:
    resource:
      service.name: jaeger
    metrics:
      level: detailed
      readers:
        - pull:
            exporter:
              prometheus:
                host: 0.0.0.0
                port: 8888
    logs:
      level: debug

extensions:
  healthcheckv2:
    use_v2: true
    http:

  pprof:
    endpoint: 0.0.0.0:1777

  jaeger_query:
    storage:
      traces: some_store
      traces_archive: another_store
    ui:
      config_file: ./cmd/jaeger/config-ui.json
    ai:
      agent_url: ws://localhost:16688
      mcp: {}
    otlp_proxy:
      target: http://127.0.0.1:4318
    max_clock_skew_adjust: 0s

  jaeger_storage:
    backends:
      some_store:
        memory:
          max_traces: 100000
      another_store:
        memory:
          max_traces: 100000

  remote_sampling:
    # You can either use file or adaptive sampling strategy in remote_sampling
    # file:
    #   path: ./cmd/jaeger/sampling-strategies.json
    adaptive:
      sampling_store: some_store
      initial_sampling_probability: 0.1
    http:
    grpc:

receivers:
  otlp:
    protocols:
      grpc:
      http:

  jaeger:
    protocols:
      grpc:
      thrift_binary:
      thrift_compact:
      thrift_http:

  zipkin:

processors:
  batch:
  # Adaptive Sampling Processor is required to support adaptive sampling.
  # It expects remote_sampling extension with `adaptive:` config to be enabled.
  adaptive_sampling:

exporters:
  jaeger_storage_exporter:
    trace_storage: some_store

逐段解读:

  • service.extensions:一行点齐五个进程外服务——存储注册表、查询 UI、采样端点、健康检查、pprof。管道之外的东西全在这里挂;pipelines.traces 则定义了数据面的"进—加工—出"三件套。生产上把 exporters 换成 ES/ClickHouse 时,只需改 jaeger_storage.backends.some_store 的类型,管道结构一字不动,这就是注册中心模式的好处。
  • telemetry:Collector 自监控(level: detailed 含每组件的收发/队列指标,Prometheus 抓取端点 8888)。告警与容量规划盯这组指标,见 09-性能与运维.md;logs.level: debug 生产环境建议调回 info。
  • jaeger_query:traces: some_store 与 traces_archive: another_store 按名字引用注册表,主查询与归档查询各指一个后端;ui.config_file 是 UI 行为配置(菜单、lookback 上限等,见 07-查询UI与API.md)。ai/otlp_proxy/max_clock_skew_adjust 三键即上一节的新特性。
  • jaeger_storage:示例里两个 backend 都是 memory(max_traces: 100000)——官方注释口径"非生产,重启即失";生产替换为 elasticsearch/clickhouse/cassandra 等,细节与 TTL 见 04-存储后端.md。
  • remote_sampling:file 与 adaptive 二选一。示例启用了 adaptive:(依赖 adaptive_sampling processor 写回统计),initial_sampling_probability: 0.1 是冷启动先按 10% 采的兜底;http:/grpc: 空对象即启用默认 5778/5779。采样策略文件与 JSON 结构见 06-采样.md。
  • receivers:otlp/jaeger/zipkin 三入口默认全开(端口未写即默认值);内嵌 all-in-one 的差异正在于此——它给每个端口显式写了 ${env:JAEGER_LISTEN_HOST:-localhost}:PORT,并额外挂了 expvar(27777)/zpages(27778),但管道 processors 里没有 adaptive_sampling(与 config.yaml 的注释一致:那是可选件)。
  • exporters:trace_storage: some_store 把管道出口绑定到注册表里的名字。注意 jaeger_storage_exporter 还有 queue:(默认写完 ACK)与 connectors 形态(可接死信)两个进阶开关,何时必须配 wait_for_result: true、以及为什么那时不能再叠 batch processor,涉及投递语义,见 04-存储后端.md 与 09-性能与运维.md。

内嵌 all-in-one.yaml 与仓库 config.yaml 的差异

两份配置高度同源但有意不同(均逐字对读 v2.22.0 tag),抄作业时别混用:

差异点 内嵌 all-in-one.yaml(无参启动) 仓库 config.yaml(示例底稿)
extensions 多挂 expvar(27777)、zpages(27778),无 pprof 挂 pprof(1777),无 expvar/zpages
processors 仅 batch batch + adaptive_sampling
remote_sampling 启用 file: 策略(reload_interval: 1s,默认概率 1) 启用 adaptive:(依赖采样存储)
端口写法 全部显式 ${env:JAEGER_LISTEN_HOST:-localhost}:PORT 留空用默认端口表(仅 telemetry 写 0.0.0.0)
jaeger_query 只配 traces,无归档库 traces + traces_archive 双库,含 ai/otlp_proxy 注释块

理解这张表,就理解了 all-in-one 的定位:一切为了"开箱即用、单机可调试"——采样用最直白的文件策略、调试端点全开、监听地址交给环境变量;而 config.yaml 面向"生产起步",留了归档和自适应采样的钩子。

实战建议

先把 v2 心智收拢成五条,再对号入座:

  1. 一个二进制,角色在配置里——--config 决定你今天是 collector 还是 query;
  2. 存储是注册中心:jaeger_storage 命名注册,写侧 exporter 和读侧 jaeger_query 都按名字引用;
  3. 采样是服务不是库:remote_sampling 负责下发,file 静态策略或 adaptive_sampling processor 动态计算二选一(后者才与它成对出现);
  4. 配置即全部:没有 v1 环境变量,没有 SIGHUP,改 YAML 就重启(采样 JSON 除外);
  5. 不会用 OTel Collector 不等于不能学 v2,但学会 v2 你一定顺学会了 OTel Collector。
  • 单进程 all-in-one 适合谁:开发、演示、CI 冒烟,以及日 span 量很小的内部系统(memory 后端重启即失,官方原文只推荐 dev/test)。要持久但量级不大,选 all-in-one + badger——官方 storage/badger 页的边界写得非常清楚:“only suitable for a single-node deployment”;badger 开了 collector 就不能被同配置的 query 访问(“and vice versa”),所以要么 all-in-one 一个进程全包,要么配 remote-storage 共享——后者见 03-部署与Kubernetes.md。
  • 什么时候拆 collector / query:日 span 千万级起步、或需要对读面单独做安全隔离(UI 暴露给内部用户,写入口暴露给全集群 SDK)时拆;两者都用外部存储时各自都是无状态水平扩展,HPA 友好(09-性能与运维.md)。流量尖峰频繁、存储追不上时再在中间垫 Kafka——那是 ingester 角色的主场,拓扑细节在 03-部署与Kubernetes.md。
  • 要不要自己搭 agent 层:官方立场很明确——别拿 Jaeger 二进制当 agent 用。SDK 直连 collector(配合 k8s Service/负载均衡)是默认答案;确需 per-host/per-pod 代理层(本地网络缓冲、K8s pod 元数据富化、统一出口)时,部署标准 OpenTelemetry Collector 做前置,它同样支持 Jaeger 的 Remote Sampling 协议,可以代理到 Jaeger 后端的 adaptive sampling,见 08-可观测性联动.md。
  • 迁移自检三件事:删光旧 COLLECTOR_*/QUERY_* env 换 YAML;给"SIGHUP 不重载、改配置=滚动重启"写进变更流程;把 legacy Thrift 端口的下线排进升级后的第一个技术债清单。更多坑见 10-常见陷阱与最佳实践.md。