16.8.3 分布式追踪与链路分析

本节聚焦 Kubernetes 环境下的分布式追踪与链路分析,目标是实现从入口到下游依赖的全链路可观测,快速定位性能瓶颈与故障根因。主流方案以 OpenTelemetry 作为采集标准,后端可对接 Jaeger、Zipkin、SkyWalking 等系统。下面给出原理、安装、配置、示例、排错与练习。

分布式追踪原理草图(采集-传输-存储-展示):

文章图片

核心概念与命令解释:
- Trace:一次请求全链路标识;Span:链路中单次调用单元。
- trace_id:跨服务关联标识,必须在入口生成并传递。
- OTLP:OpenTelemetry 传输协议,常用 gRPC/HTTP。


安装示例:Kubernetes 部署 OpenTelemetry Collector + Jaeger#

以下示例在 observability 命名空间安装 Collector 与 Jaeger(演示用本地存储,生产需接入 ES/ClickHouse):

# 1) 创建命名空间
kubectl create ns observability

# 2) 部署 Jaeger (all-in-one 演示版)
cat > /tmp/jaeger.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jaeger
  namespace: observability
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jaeger
  template:
    metadata:
      labels:
        app: jaeger
    spec:
      containers:
        - name: jaeger
          image: jaegertracing/all-in-one:1.52
          ports:
            - containerPort: 16686  # UI
            - containerPort: 14250  # gRPC
            - containerPort: 14268  # HTTP
---
apiVersion: v1
kind: Service
metadata:
  name: jaeger
  namespace: observability
spec:
  selector:
    app: jaeger
  ports:
    - name: ui
      port: 16686
      targetPort: 16686
    - name: grpc
      port: 14250
      targetPort: 14250
    - name: http
      port: 14268
      targetPort: 14268
EOF
kubectl apply -f /tmp/jaeger.yaml
# 3) 部署 OpenTelemetry Collector
cat > /tmp/otel-collector.yaml <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: otel-collector-config
  namespace: observability
data:
  otel-collector-config.yaml: |
    receivers:
      otlp:
        protocols:
          grpc:
          http:
    processors:
      batch: {}
      memory_limiter:
        limit_mib: 256
        check_interval: 1s
    exporters:
      jaeger:
        endpoint: jaeger.observability.svc.cluster.local:14250
        tls:
          insecure: true
      logging:
        loglevel: info
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [memory_limiter, batch]
          exporters: [jaeger, logging]
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: otel-collector
  namespace: observability
spec:
  replicas: 1
  selector:
    matchLabels:
      app: otel-collector
  template:
    metadata:
      labels:
        app: otel-collector
    spec:
      containers:
        - name: otel-collector
          image: otel/opentelemetry-collector:0.96.0
          args: ["--config=/conf/otel-collector-config.yaml"]
          ports:
            - containerPort: 4317  # OTLP gRPC
            - containerPort: 4318  # OTLP HTTP
          volumeMounts:
            - name: config
              mountPath: /conf
      volumes:
        - name: config
          configMap:
            name: otel-collector-config
---
apiVersion: v1
kind: Service
metadata:
  name: otel-collector
  namespace: observability
spec:
  selector:
    app: otel-collector
  ports:
    - name: otlp-grpc
      port: 4317
      targetPort: 4317
    - name: otlp-http
      port: 4318
      targetPort: 4318
EOF
kubectl apply -f /tmp/otel-collector.yaml

预期效果:
- Jaeger UI 通过 kubectl port-forward svc/jaeger -n observability 16686:16686 访问。
- Collector 日志中出现 Exporting spans,表示接收并导出追踪数据。


应用接入示例(Java / Spring Boot,OTLP gRPC)#

示例以环境变量方式开启自动采集与上报(可用于容器启动参数):

# 运行时环境变量(Deployment 中的 env)
OTEL_SERVICE_NAME=order-service
OTEL_TRACES_EXPORTER=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector.observability.svc.cluster.local:4317
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
OTEL_RESOURCE_ATTRIBUTES=deployment.environment=prod,team=platform

命令解释:
- OTEL_SERVICE_NAME:服务名,将展示在追踪 UI。
- OTEL_EXPORTER_OTLP_ENDPOINT:Collector 地址。
- OTEL_RESOURCE_ATTRIBUTES:标签,方便过滤与多环境区分。


链路分析操作示例#

1) 查看某服务 p99 延迟链路
- 在 Jaeger UI 选择 order-service,排序 Duration 观察长耗时 Trace。
2) 逐层分析 Span
- 进入 Trace 后查看最长 Span,如 db.queryhttp.client
3) 结合日志定位
- 通过 Span 的 trace_id 查询日志系统(需日志埋点输出 trace_id)。


排错清单(含命令)#

1) Collector 无法接收数据

# 检查服务与端口
kubectl get svc -n observability
kubectl get pod -n observability -l app=otel-collector -o wide

# 观察 Collector 日志
kubectl logs -n observability deploy/otel-collector

常见原因:端口被拦截、OTLP 协议不匹配、Collector 配置错误。

2) Jaeger 无数据

# 确认 Collector 导出端点正确
kubectl get cm -n observability otel-collector-config -o yaml | grep jaeger -n
# 测试可达性(进入 Collector Pod)
kubectl exec -n observability deploy/otel-collector -- \
  sh -c "nc -zv jaeger.observability.svc.cluster.local 14250"

常见原因:Jaeger 未就绪、端口错误、TLS 设置不一致。

3) Trace 断链
- 排查入口是否生成 trace_id
- 确认服务间 HTTP Header 传递 traceparent
- 检查 SDK 自动注入与中间件版本。


练习#

1) 在测试命名空间部署一个简单服务(如 whoami),开启 OTEL 自动采集并上报到 Collector,观察链路。
2) 修改 Collector 采样率(尾部采样/概率采样),验证 UI 中 Trace 数量变化。
3) 触发一次接口超时(延迟 3s),在 Jaeger 中定位最长 Span,并说明原因。

通过以上安装、示例与排错步骤,可在 Kubernetes 中建立可用的分布式追踪能力,实现多服务调用的快速定位与根因分析。