jaeger学习

Jaeger All-in-One 部署

Step 1:创建命名空间
复制代码
kubectl create namespace observability
Step 2:部署 Jaeger All-in-One

创建文件 jaeger-all-in-one.yaml:

复制代码
[root@k3s-server jaeger]# cat jaeger-all-in-one.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jaeger
  namespace: observability
  labels:
    app: jaeger
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jaeger
  template:
    metadata:
      labels:
        app: jaeger
    spec:
      containers:
        - name: jaeger
          image: jaegertracing/all-in-one:1.62.0
          ports:
            # Jaeger UI 网页
            - containerPort: 16686
              name: ui
            # Collector gRPC 老jaeger‑sdk
            - containerPort: 14250
              name: grpc
            # Collector HTTP thrift 老http上报
            - containerPort: 14268
              name: http
            # Agent compact thrift UDP
            - containerPort: 6831
              protocol: UDP
              name: agent-compact
            # --------新增OTLP端口声明(备注)--------
            - containerPort: 4317
              name: otlp-grpc
            - containerPort: 4318
              name: otlp-http
          env:
            - name: COLLECTOR_OTLP_ENABLED
              value: "true"
          resources:
            limits:
              memory: "512Mi"
              cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: jaeger
  namespace: observability
spec:
  selector:
    app: jaeger
  ports:
    - name: ui
      port: 16686
      targetPort: ui
    - name: grpc
      port: 14250
      targetPort: grpc
    - name: http
      port: 14268
      targetPort: http
    - name: agent-compact
      port: 6831
      protocol: UDP
      targetPort: agent-compact
    # --------新增OTLP Service转发端口--------
    - name: otlp-grpc
      port: 4317
      targetPort: otlp-grpc
    - name: otlp-http
      port: 4318
      targetPort: otlp-http
  type: ClusterIP
Step 3:应用部署
复制代码
kubectl apply -f jaeger-all-in-one.yaml
Step 4:验证 Pod 运行状态
复制代码
kubectl get pods -n observability
Step 5:访问 Jaeger UI
复制代码
# 端口转发到本地
kubectl port-forward svc/jaeger 16686:16686 -n observability --address 0.0.0.0

然后浏览器打开:http://localhost:16686

你应该能看到 Jaeger 的 Web 界面 🎉

Step6:部署一个示例应用
复制代码
[root@k3s-server jaeger]# cat otel-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: otel-demo
  namespace: observability
  labels:
    app: otel-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: otel-demo
  template:
    metadata:
      labels:
        app: otel-demo
    spec:
      containers:
        - name: otel-demo
          image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest
          args:
            - "traces"
            - "--otlp-endpoint=jaeger:4317"
            - "--otlp-insecure"
            - "--service=otel-demo-service"
            - "--duration=60s"
            - "--rate=1"
          resources:
            limits:
              memory: "128Mi"
              cpu: "200m"

kubectl apply -f otel-demo.yaml

Pod 是否运行

复制代码
kubectl get pods -n observability
Step7:查看日志,确认数据真的发出去了
复制代码
kubectl logs -n observability deployment/otel-demo
Step8:去 Jaeger UI 查看

打开 Jaeger UI:

复制代码
kubectl port-forward svc/jaeger 16686:16686 -n observability --address 0.0.0.0

浏览器打开:

复制代码
http://ip:16686

然后:

  1. 左侧 Service 下拉框里找:otel-demo-service

  2. 点击 Find Traces

  3. 点任意一条 Trace

    Trace
    └── otel-demo-service
    └── 一个 Span

这就说明:

应用已经成功把追踪数据发给 Jaeger 了。


Step9:这节课最重要的理解

不要急着写代码,先记住这句话:

应用要产生追踪数据,必须集成 OpenTelemetry SDK。

SDK 会帮应用做三件事:

SDK 做的事 通俗理解
生成 TraceID 给整条请求一个编号
生成 Span 记录"这一步做了什么、花了多久"
发送数据 把记录发给 Jaeger

配置采样率yaml

复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: otel-demo
  namespace: observability
spec:
  replicas: 1
  selector:
    matchLabels:
      app: otel-demo
  template:
    metadata:
      labels:
        app: otel-demo
    spec:
      containers:
        - name: otel-demo
          image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest
          args:
            - "traces"
            - "--otlp-endpoint=jaeger:4317"
            - "--otlp-insecure"
            - "--service=otel-demo-sampling"
            - "--duration=120s"
            - "--rate=10"
          env:
            - name: OTEL_TRACES_SAMPLER
              value: "parentbased_traceidratio"
            - name: OTEL_TRACES_SAMPLER_ARG
              value: "0.1"
          resources:
            limits:
              memory: "128Mi"
              cpu: "200m"

======================================

Jaeger 生产架构部署

小步骤 1:先理解生产架构长什么样

之前 All-in-One 是这样的:

复制代码
应用 → Jaeger All-in-One → 内存存储 → UI

生产级架构会变成这样:

复制代码
应用
  ↓
Jaeger Collector
  ↓
Elasticsearch
  ↓
Jaeger Query / UI
组件 作用
Collector 接收应用上报的追踪数据
Elasticsearch 持久化存储追踪数据
Query / UI 提供查询接口和可视化界面

小步骤 2:部署 Elasticsearch

复制代码
kubectl create namespace observability

创建文件:

复制代码
[root@k3s-server jaeger]# cat elasticsearch.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
  namespace: observability
spec:
  replicas: 1
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
        - name: elasticsearch
          image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
          ports:
            - containerPort: 9200
          env:
            - name: discovery.type
              value: "single-node"
            - name: xpack.security.enabled
              value: "false"
            - name: ES_JAVA_OPTS
              value: "-Xms512m -Xmx512m"
          resources:
            limits:
              memory: "1Gi"
              cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
  namespace: observability
spec:
  selector:
    app: elasticsearch
  ports:
    - port: 9200
      targetPort: 9200

部署

复制代码
kubectl apply -f elasticsearch.yaml

小步骤 3:确认 Elasticsearch 能访问

复制代码
kubectl logs -n observability deployment/elasticsearch --tail=30

小步骤 4:部署 Jaeger Collector

复制代码
[root@k3s-server jaeger]# cat jaeger-collector.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jaeger-collector
  namespace: observability
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jaeger-collector
  template:
    metadata:
      labels:
        app: jaeger-collector
    spec:
      containers:
      - name: jaeger-collector
        image: jaegertracing/jaeger-collector:1.62.0
        env:
        # ✅新版环境变量,去掉SPANS_前缀!
        - name: SPAN_STORAGE_TYPE
          value: "elasticsearch"
        - name: ES_SERVER_URLS
          value: "http://elasticsearch:9200"
        ports:
        - containerPort: 14250
        - containerPort: 14268
        - containerPort: 4317
        - containerPort: 4318
        resources:
          limits:
            memory: "512Mi"
            cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: jaeger-collector
  namespace: observability
spec:
  selector:
    app: jaeger-collector
  ports:
    - name: grpc
      port: 14250
      targetPort: 14250
    - name: http
      port: 14268
      targetPort: 14268
    - name: otlp-grpc
      port: 4317
      targetPort: 4317
    - name: otlp-http
      port: 4318
      targetPort: 4318

部署:

复制代码
kubectl apply -f jaeger-collector.yaml

检查:

复制代码
kubectl get pods -n observability

小步骤 5:部署 Jaeger Query / UI

复制代码
[root@k3s-server jaeger]# cat jaeger-query.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jaeger-query
  namespace: observability
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jaeger-query
  template:
    metadata:
      labels:
        app: jaeger-query
    spec:
      containers:
        - name: jaeger-query
          image: jaegertracing/jaeger-query:1.62.0
          env:
            - name: SPAN_STORAGE_TYPE
              value: "elasticsearch"
            - name: ES_SERVER_URLS
              value: "http://elasticsearch:9200"
          ports:
            - containerPort: 16686
          resources:
            limits:
              memory: "512Mi"
              cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: jaeger-query
  namespace: observability
spec:
  selector:
    app: jaeger-query
  ports:
    - port: 16686
      targetPort: 16686
  type: NodePort

部署:

复制代码
kubectl apply -f jaeger-query.yaml

检查:

复制代码
kubectl get pods -n observability

你应该看到三个核心 Pod:

复制代码
elasticsearch
jaeger-collector
jaeger-query

小步骤 6:打开 Jaeger UI

执行:

复制代码
kubectl port-forward svc/jaeger-query 16686:16686 -n observability --address 0.0.0.0

然后浏览器打开:

复制代码
http://IP:16686

这时候界面应该能打开。

但现在还没有数据,因为还没有应用往 jaeger-collector 发追踪数据。

小步骤 7:部署一个测试应用,把数据发给 Collector

复制代码
[root@k3s-server jaeger]# cat otel-demo-prod.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: otel-demo
  namespace: observability
spec:
  replicas: 1
  selector:
    matchLabels:
      app: otel-demo
  template:
    metadata:
      labels:
        app: otel-demo
    spec:
      containers:
        - name: otel-demo
          image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest
          args:
            - "traces"
            - "--otlp-endpoint=jaeger-collector:4317"
            - "--otlp-insecure"
            - "--service=prod-demo-service"
            - "--duration=120s"
            - "--rate=2"
          resources:
            limits:
              memory: "128Mi"
              cpu: "200m"

部署:

复制代码
kubectl apply -f otel-demo-prod.yaml

查看日志:

复制代码
kubectl logs -n observability deployment/otel-demo --tail=20

如果看到它在生成或导出 traces,说明数据正在发往 Collector。

小步骤 8:去 Jaeger UI 验证

回到 Jaeger UI:

复制代码
http://ip:16686

操作步骤:

  1. 左侧 Service 选择 prod-demo-service
  2. 点击 Find Traces
  3. 点开一条 Trace

你应该能看到追踪数据已经存到 Elasticsearch,并通过 Query/UI 查出来了。

=============================================

Jaeger 知识点总结

一、基础概念

1. 是什么

Jaeger 是 Uber 开源的分布式追踪系统(Distributed Tracing) ,基于 OpenTracing 规范;现在社区主推 OpenTelemetry(OTel),Jaeger 可以直接接收 OTel 的追踪数据。

作用:微服务架构下,追踪一次请求跨多个服务的完整调用链路,定位慢请求、调用报错、性能瓶颈。

2. 核心术语(OpenTracing)

  • Trace(追踪) :一次完整请求的全部链路,全局唯一 traceID,一条 Trace 由多个 Span 组成。
  • Span(跨度) :链路里的一次操作 / 调用;有自己唯一spanID;包含开始时间、结束时间、耗时;存在父子关系。
  • Parent‑Span:父 Span,上游调用;子 Span 由父 Span 产生。
  • Tag(标签):Span 的键值对结构化元数据,用于过滤(http.status_code、error=true)
  • Log(日志事件):Span 内时间点事件,记录异常堆栈等
  • Baggage(行李) :跨进程透传的自定义上下文,会随 trace 全链路传递,慎用,不要放大量数据。

上下文传播:TraceId、SpanId 需要跨服务传递,通过 HTTP Header /gRPC metadata 传递(trace propagation 传播)。

二、Jaeger 架构组件

整体架构分:采集 → 存储 → 查询 UI

  1. Jaeger‑Agent(代理)

    • 部署在每台主机 / Pod 上,Sidecar 方式;业务应用上报 span 数据发给本地 agent(UDP/HTTP)
    • Agent 做聚合、转发,减轻业务应用压力;应用不需要直连 Collector。

    也可以绕过 agent,业务直接上报给 Collector(开发环境常用)

  2. Collector(收集器)

    • 接收 Agent / 应用发来的 trace 数据;做校验、处理;写入后端存储。
    • 支持接收:Jaeger 协议、OpenTelemetry (OTLP) 协议 ✅(新版本重点)
  3. Query(查询服务)

    • 查询后端存储里面的 trace 数据;提供 API;前端 UI 后端。
  4. UI(Web 前端)

    • Web 可视化页面;查询 TraceID;查看调用链路时序图、DAG 依赖图。
  5. Storage(存储后端)

    存储 适用场景
    Memory 仅测试,重启丢失数据
    Cassandra 官方原生,生产旧方案,运维重
    Elasticsearch 最常用生产存储
    Badger 本地磁盘存储,单节点小规模部署

💡新版本 Jaeger all‑in‑one:开发环境一键集成 agent+collector+query+ui+memory 存储,本地测试首选。

三、数据传播的两种模式

1. 注入 & 提取 Inject / Extract

  • Inject:把 trace 上下文 写入传输载体(http header、grpc metadata),上游服务
  • Extract:下游从载体读出 trace 上下文,继续创建子 span

2. 传播格式(Propagator)

  • jaeger:旧 Jaeger 原生头 uber‑trace‑id
  • w3c tracecontext:W3C 标准 traceparent/tracestate,OpenTelemetry 默认,优先用这个!

重点:全链路所有服务必须使用同一种传播器,否则链路断链!看不到完整 trace

四、部署模式

  1. All‑in‑One(开发测试) 所有组件打包一个进程;内存存储;本地快速调试。

    docker 快速启动

    docker run -d --name jaeger
    -p 16686:16686 \ # UI端口
    -p 4317:4317 \ # OTLP grpc
    -p 4318:4318 \ # OTLP http
    jaegertracing/all-in-one:latest

端口记忆:

  • 16686:Web UI
  • 4317:OTLP‑gRPC(otel 推荐)
  • 4318:OTLP‑HTTP
  • 6831 UDP:旧 jaeger agent thrift
  1. 分布式生产部署 Agent (Sidecar DaemonSet) + Collector 集群 + Elasticsearch 存储 + Query + UI;K8s 环境 DaemonSet 部署 Jaeger‑Agent 每个节点一个。

五、Jaeger vs OpenTelemetry(高频面试)

历史演进: 旧方案:业务埋码使用 OpenTracing SDK →上报 Jaeger Agent →Jaeger Collector 存储 现状:OpenTracing 已经归档废弃,不再维护! ✅ 现在标准方案:业务使用 OpenTelemetry SDK 埋点生成 Trace,输出 OTLP 协议,直接发给 Jaeger Collector;Jaeger 作为后端存储 + 可视化,不再负责 SDK 埋点。

简单一句话:

  • OpenTelemetry (OTel):负责埋点生成链路数据(SDK)
  • Jaeger:负责接收、存储、查询可视化链路数据(后端服务)

六、核心使用场景 & 排查问题思路

排查步骤

  1. 在 UI 搜索 TraceID,拿到整条请求链路
  2. 看每个 span 耗时,定位慢的服务 / 接口(找出瓶颈)
  3. 查看 tag error=true 的 span 定位异常服务;查看 log 里异常堆栈
  4. 查看服务依赖 DAG 图,看服务之间调用拓扑

常见问题

  1. 链路断了,前后服务 Span 不在同一个 TraceID? 👉 传播器不一致;http header 被反向代理 (Nginx/Istio) 丢弃 traceparent 头。
  2. 没有上报数据,UI 查不到 trace 👉 确认 OTLP 地址;检查网络;确认采样策略。
  3. 数据量太大存储压力高 → 采样 (Sampling)

七、采样 Sampling(非常重要面试点)

微服务流量很大,不能 100% 全部采集所有请求 trace,会压垮存储;需要采样策略。

4 种采样策略

  1. Constant 常量采样 0全部丢弃;1全部采集;测试环境用 1,生产禁止 1。
  2. Probabilistic 概率采样 按 traceID 概率采集,比如 0.1 采集 10% 的链路;整条 Trace 要么全部保留,要么全部丢弃(基于 traceID,同一个 trace 所有 span 统一决策,不会出现半截链路)
  3. Rate‑Limiting 限速采样 限制每秒最多采集 N 条 trace;适合流量突增场景,控制采集 QPS 上限。
  4. Remote 远程采样(生产推荐) 采样策略配置放在 Jaeger Collector;SDK 远程拉取采样策略;改策略不用重启业务服务。

✅采样是基于 TraceID 决策,不是 Span!保证一条 trace 完整或者丢弃,不会出现残缺链路。

八、K8s + Istio + Jaeger

Istio 本身可以生成访问链路;Istio 可以把 trace 数据输出 OTLP 到 Jaeger;此时业务代码不需要手动埋点 SDK,Sidecar 代理层面自动采集链路。 缺点:只能采集网络层面;业务内部方法调用看不到 span;想要方法级链路,业务还是要 OTel SDK 埋点。

九、面试高频简答题整理

  1. Jaeger 作用?

分布式追踪,可视化微服务跨服务调用链路,定位慢查询、调用异常性能瓶颈。

  1. Trace、Span 关系?

Trace 是一次完整请求;Trace 由若干 Span 组成;Span 存在父子调用关系;每个 trace 拥有全局 traceId。

  1. Agent 的作用?

部署主机 / 节点本地;业务本地上报,转发给 Collector;解耦业务和 collector;缓冲数据。

  1. 什么是采样,为什么需要采样?

高流量微服务,全部上报 trace 存储压力大;采样选择性采集部分链路;采样决策基于 TraceID 保证链路完整性。

  1. OpenTelemetry 和 Jaeger 关系?

OTel 是新一代埋点 SDK 标准,生成 OTLP 追踪数据;Jaeger 作为后端接收存储展示 trace;OpenTracing 已经废弃。

  1. 链路断链一般排查什么?

W3C 传播器是否统一;网关是否丢弃 traceparent 请求头;网络是否连通;采样策略是否全部丢弃。

十、补充区分三件套

  • Metrics (指标):Prometheus:统计计数器、耗时百分位,聚合指标
  • Logs (日志):ELK/Loki:离散事件日志
  • Tracing (链路追踪):Jaeger/Zipkin:单次完整调用链路

可观测性三大支柱:指标、日志、追踪。

相关推荐
别动我齐刘海1 小时前
简历技术栈全面复习总结
c++·人工智能·深度学习·学习·tcp/ip·算法·rpc
UIU1141 小时前
-7 / 2 在 C 里是 -3,在 Python 里是 -4,谁算错了?
c++·学习·c#
其实防守也摸鱼1 小时前
渗透测试学习计划(全栈综合 · 零基础进阶)
android·数据库·学习·安全·oracle·自动化·学习方法
一隅论数智2 小时前
给AI Agent一颗“私域大脑“:本体增强的工程化之路
大数据·运维·数据仓库·人工智能·笔记·学习·政务
我是你的开心果7782 小时前
ai全栈软件开发学习day27
人工智能·学习·状态模式
zhangrelay2 小时前
ubuntu图形化和命令行查看硬件参数方式汇总-Surface Go
linux·笔记·学习·ubuntu
DevNo3 小时前
我的医学考研学习品牌接触记录
学习·考研
传奇开心果编程3 小时前
【ArkUI进阶练中学】第9课:分布式能力与多设备协同
学习·ui·华为·harmonyos
shangan_33 小时前
C语言学习
c语言·开发语言·学习