Jaeger 部署与配置:单机模式、生产部署、存储后端选型
说起 Jaeger 的部署,我一开始也觉得很简单——不就是 docker-compose up 一下嘛?后来踩过几次坑,才发现从「跑起来」到「能扛住线上流量」,中间隔着一个大西洋。今天这篇我把踩过的坑、生产环境的心得、以及存储后端怎么选,一次性讲清楚。
一、单机模式:10 分钟快速上手
说白了,单机模式就是让你看看 Jaeger 长什么样。对于本地开发、功能验证,完全够用。我的习惯是用 Docker Compose 搞定所有组件。
docker-compose.yml 里显式指定版本号,避免无意中拉新版本导致配置不兼容。我曾经因为用了 latest 标签,结果存储后端索引结构变了,第二天查数据查不到,排查了半天才发现是版本跳跃的问题。
最简单的配置如下:
version: '3.7'
services:
jaeger-collector:
image: jaegertracing/jaeger-collector:1.60
ports:
- "14269:14269" # admin
- "14268:14268" # thrift
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
environment:
- SPAN_STORAGE_TYPE=badger # 无外依赖,本地文件存储
jaeger-query:
image: jaegertracing/jaeger-query:1.60
ports:
- "16686:16686" # UI
- "16687:16687" # admin
environment:
- SPAN_STORAGE_TYPE=badger
depends_on:
- jaeger-collector
jaeger-agent:
image: jaegertracing/jaeger-agent:1.60
ports:
- "6831:6831/udp"
- "14271:14271" # admin
command: ["--reporter.grpc.host-port=jaeger-collector:14250"]
depends_on:
- jaeger-collector
启动后访问 http://localhost:16686,就能看到干净的 Jaeger UI。嗯,这里要注意:Badger 是内嵌的本地 KV 存储,重启后数据可能丢失,只适合临时测试。
二、生产部署:架构升级与高可用
生产环境的目标很明确:高可用、可扩展、数据不丢。这时需要把 Collector、Query 分开部署,再加上存储后端和消息队列。以下是我推荐的最小生产架构。
三、存储后端选型:核心决策
选哪个存储后端,直接决定了你的运维成本和查询体验。我对比过三种主流方案,整理了一张表。
| 特性 | Elasticsearch | Cassandra | Badger |
|---|---|---|---|
| 写入性能 | 中等,有写放大 | 优秀,线性可扩展 | 极快(单机) |
| 查询灵活性 | 丰富聚合、全文检索 | 有限(按 traceID / 时间) | 很有限 |
| 运维复杂度 | 中等,需调优堆内存 | 较高,集群管理 | 零运维 |
| 持久化 | 支持,可配置 ILM | 支持,需备份策略 | 重启数据丢失 |
| 建议场景 | 中小规模,需要快速集成 | 大规模,写入量 > 10W span/s | 开发测试,不可用 |
我的生产选型经验:如果你的团队已经有 Elasticsearch 运维经验,选 ES 最省事。如果 span 量极大(例如百万级/秒),建议上 Cassandra,写入性能更稳定。我不建议在大规模场景用 ES,因为写入抖动会导致索引性能问题——我曾经遇到 ES 写入队列打满导致 Jaeger Collector OOM,后来换成 Cassandra + Kafka 缓冲才解决。
四、关键配置参数(生产必备)
配置 Jaeger 不复杂,但有几个参数容易忽略。
Collector 的 gRPC 与 HTTP 端口
- 14250 – 内部 gRPC(Agent 到 Collector)
- 4317 – OTLP gRPC(新 SDK 首选)
- 14268 – Thrift HTTP(兼容旧 SDK)
Query 缓存与超时
--query.max-clock-skew-adjustment=5s # 时钟偏差校准
--query.additional-headers=access-control-allow-origin:* # CORS 跨域
--es.index-prefix=jaeger- # ES 索引前缀
--es.use-ilm=true,结果 ES 索引数量暴涨到几千个,查询时 ES 直接挂了。如果你用 ES,强烈建议开启 ILM 策略。
五、存储后端选型的补充决策树
当你拿不准选哪个时,可以用这个简化的决策逻辑:
- 单机/测试 → Badger(零依赖)
- 规模 < 10K span/s → Elasticsearch(如果有 ES 人力)
- 规模 10K–100K span/s → Elasticsearch + ILM,或 Cassandra(选你熟悉的)
- 规模 > 100K span/s → Cassandra + Kafka(强烈推荐)
另外提一句:如果你用了 Kafka,Collector 的 --kafka.producer.batch-size 可以调到 16384,减少网络 IO。
# 生产 Collector 启动命令示例(使用 ES + Kafka)
docker run -d --name=jaeger-collector \
-e SPAN_STORAGE_TYPE=elasticsearch \
-e ES_SERVER_URLS=http://es-cluster:9200 \
-e ES_INDEX_PREFIX=jaeger- \
-e ES_USE_ILM=true \
-e ES_ILM_POLICY_NAME=jaeger-ilm-policy \
-e KAFKA_PRODUCER_BROKERS=kafka-broker:9092 \
-e KAFKA_PRODUCER_BATCH_SIZE=16384 \
jaegertracing/jaeger-collector:1.60
我个人习惯把环境变量统一放在一个 .env 文件里,方便多环境切换。你想想看,如果你每次部署都要改十几个参数,迟早会漏掉一个导致线上故障。
六、小结
这一章我们把 Jaeger 从单机玩具到生产可用说了一遍。核心就是三点:
- 单机用 Docker Compose + Badger 快速验证;
- 生产务必引入 Kafka 做缓冲,Collector 无状态水平扩展;
- 存储后端的选择决定了你的运维成本和查询上限,不要只看初期性能。