在前面的文章中,我们已经完成了 Kubernetes 可观测体系中的两个部分:
Metrics 指标 Prometheus Logs 日志 LokiPrometheus 可以帮助我们发现:
Node CPU 是否过高
Memory 是否不足
Pod 是否频繁重启
服务错误率是否突然升高
Loki 则可以帮助我们进一步查看:
数据库连接是否失败
配置文件是否缺失
应用是否出现异常
某个 Pod 在故障前输出了什么日志
但是,当系统由多个服务组成时,仅仅查看 Metrics 和 Logs 仍然不够。
假设一次用户请求需要经过下面几个服务:
用户请求 │ ▼ Frontend │ ▼ Backend │ ▼ Database现在请求耗时突然从:
200 ms上升到:
2 sPrometheus 可以发现:
接口延迟上升Loki 也可能找到一些相关日志。
但是我们仍然需要回答:
这 2 秒究竟消耗在哪个服务上?
是 Frontend 处理缓慢?
还是 Backend 调用了一个很慢的接口?
或者 Database 查询耗费了大量时间?
这正是分布式链路追踪需要解决的问题。
这一篇,我们继续搭建可观测体系的第三部分:
Tracing 链路追踪 Tempo本篇将在单节点 Kubernetes 实验环境中部署:
Tempo:存储和查询 Trace
OpenTelemetry Collector:接收、处理和转发 Trace
Python Demo:生成最简单的测试 Trace
Grafana:查询和展示完整调用链
最终形成下面这条链路:
Demo Application │ │ OTLP/gRPC 4317 ▼ OpenTelemetry Collector │ │ OTLP/gRPC 4317 ▼ Tempo │ │ HTTP 3200 ▼ Grafana Explore一、什么是 Trace?
一次请求进入系统后,可能会经过多个处理步骤。
例如:
HTTP Request │ ├── Validate Request │ ├── Query Database │ └── Build Response在链路追踪系统中,一次完整请求通常称为:
TraceTrace 内部的每个处理步骤称为:
Span例如:
Trace: 用户请求 │ ├── Span: HTTP Request 320 ms │ ├── Span: Validate Request 10 ms │ ├── Span: Query Database 250 ms │ └── Span: Build Response 60 ms通过这些 Span,我们可以直观看出:
Query Database占用了大部分时间。
因此,Tracing 主要回答:
一次请求经过了哪些步骤?
以及:
时间究竟消耗在哪里?
二、OpenTelemetry 和 Tempo 分别负责什么?
在本实验中,OpenTelemetry 和 Tempo 承担不同的角色。
OpenTelemetry
OpenTelemetry 是一套开放的可观测标准和工具体系。
它可以处理:
Metrics Logs Traces本篇主要使用其中两个部分:
OpenTelemetry SDK OpenTelemetry Collector应用通过 OpenTelemetry SDK 创建 Trace 和 Span,然后将数据发送给 OpenTelemetry Collector。
Collector 主要负责:
接收应用发送的遥测数据
批量处理 Trace
添加或修改属性
将 Trace 转发给后端存储系统
将应用和具体存储后端解耦
Tempo
Tempo 是 Grafana 生态中的分布式链路追踪后端。
它主要负责:
接收 Trace
存储 Trace
根据 Trace ID 查询
根据服务名、Span 名称和属性搜索 Trace
将查询结果提供给 Grafana
Tempo 支持单体和微服务两种部署模式。
对于入门、开发和小规模环境,Grafana 官方建议使用单体模式;微服务模式更加复杂,适合需要独立扩展各组件的场景。
本实验室的目标仍然是:
单节点 + 低资源占用 + 便于学习因此采用:
Tempo Monolithic也就是单体部署模式。
三、整体架构
本篇完整架构如下:
Kubernetes Cluster Demo Trace Application │ │ OpenTelemetry SDK │ OTLP/gRPC :4317 ▼ OpenTelemetry Collector │ │ Batch Processor │ OTLP/gRPC :4317 ▼ Tempo │ │ Query API :3200 ▼ Grafana这里为什么不让应用直接连接 Tempo?
理论上可以:
Application │ ▼ Tempo但是在真实系统中,更常见的结构是:
Application │ ▼ OpenTelemetry Collector │ ▼ Tracing BackendCollector 相当于应用和后端之间的统一中转站。
以后即使将 Tempo 替换成其他 Trace 后端,应用端也不一定需要修改。
Collector 还可以统一完成:
数据批处理
数据过滤
属性补充
采样
多后端转发
重试和队列缓冲
因此,本实验采用更加标准的结构:
Application ↓ Collector ↓ Tempo ↓ Grafana四、安装 Tempo
前面的 Prometheus 和 Grafana 已经安装在:
monitoringNamespace 中。
为了方便 Grafana 访问,这一篇也将 Tempo 安装在:
monitoringNamespace 中。
1. 添加 Grafana Helm Repository
如果前面安装 Loki 时已经添加过,可以直接执行更新:
helm repo add grafana https://grafana.github.io/helm-charts helm repo update查看 Tempo Chart:
helm search repo grafana/tempoGrafana 提供了单体和分布式 Tempo Helm 部署方式;对于本实验,使用单体grafana/tempoChart 即可。
2. 准备 tempo-values.yaml
创建配置文件:
vim tempo-values.yaml内容如下:
tempo: # 关闭匿名使用情况上报 reportingEnabled: false # 开启 OTLP 接收端口 receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 # 单节点实验环境不使用持久化存储 persistence: enabled: false service: type: ClusterIP这里开启了两个 OTLP 接收协议:
4317 OTLP/gRPC 4318 OTLP/HTTP本篇主要使用:
4317 OTLP/gRPCTempo 的 OTLP Receiver 默认可能只监听本地地址,因此在 Kubernetes 中需要明确配置为:
0.0.0.0:4317 0.0.0.0:4318这样其他 Pod 才能通过 Kubernetes Service 访问。Tempo 官方配置文档也说明,Receiver 默认可能监听 localhost,若需要接收外部容器发送的数据,应配置监听地址。
3. 关于临时存储
这里设置了:
persistence: enabled: false这意味着 Tempo 数据只用于实验。
如果 Tempo Pod 被删除或重新创建,已经存储的 Trace 可能丢失。
因此,这套配置适用于:
学习 Tempo
验证 OTLP 链路
测试 Grafana Trace 查询
单节点可观测实验室
不适合生产环境。
生产环境通常应该使用:
PVC
Amazon S3
Google Cloud Storage
Azure Blob Storage
其他对象存储
Tempo 官方也建议生产环境优先使用对象存储;本地文件系统更加适合单体测试和开发场景。
4. 安装 Tempo
执行:
helm install tempo grafana/tempo \ -n monitoring \ -f tempo-values.yaml查看 Helm Release:
helm list -n monitoring查看 Pod:
kubectl get pods -n monitoring正常情况下应该看到类似结果:
tempo-0 1/1 Running不同版本的 Helm Chart,Pod 名称和容器数量可能略有差异。
5. 查看 Tempo Service
执行:
kubectl get svc -n monitoring应该可以看到:
tempo进一步查看端口:
kubectl get svc tempo -n monitoring结果中通常可以看到:
3200/TCP 4317/TCP 4318/TCP它们分别对应:
3200 Tempo HTTP 查询接口 4317 OTLP/gRPC 4318 OTLP/HTTPTempo 的完整 Kubernetes Service DNS 为:
tempo.monitoring.svc.cluster.local后续 OpenTelemetry Collector 将数据发送到:
tempo.monitoring.svc.cluster.local:43176. 查看 Tempo 日志
执行:
kubectl logs -n monitoring statefulset/tempo --tail=100如果当前 Chart 创建的不是 StatefulSet,也可以先查看资源:
kubectl get deployment,statefulset -n monitoring然后根据实际资源名称查看日志。
如果 Tempo 正常启动,日志中不应该持续出现:
address already in use或者:
connection refused等错误。
五、安装 OpenTelemetry Collector
Tempo 已经能够接收 Trace,接下来部署 OpenTelemetry Collector。
Collector 官方 Helm Chart 要求显式设置运行模式,可选值包括:
daemonset deployment statefulset本篇只需要一个集中接收 Trace 的 Collector,因此使用:
deployment官方当前安装示例推荐使用:
otel/opentelemetry-collector-k8s镜像。
1. 添加 OpenTelemetry Helm Repository
执行:
helm repo add open-telemetry \ https://open-telemetry.github.io/opentelemetry-helm-charts helm repo update查看 Chart:
helm search repo open-telemetry/opentelemetry-collector2. 创建 observability Namespace
创建专门用于 Collector 和测试应用的 Namespace:
kubectl create namespace observability如果 Namespace 已经存在,会提示:
AlreadyExists也可以使用更加幂等的写法:
kubectl create namespace observability \ --dry-run=client -o yaml | kubectl apply -f -检查:
kubectl get namespace应该可以看到:
observability六、准备 Collector 配置
创建配置文件:
vim otel-collector-values.yaml内容如下:
mode: deployment image: repository: otel/opentelemetry-collector-k8s alternateConfig: extensions: health_check: endpoint: ${env:MY_POD_IP}:13133 receivers: otlp: protocols: grpc: endpoint: ${env:MY_POD_IP}:4317 http: endpoint: ${env:MY_POD_IP}:4318 processors: memory_limiter: check_interval: 5s limit_percentage: 80 spike_limit_percentage: 25 batch: {} exporters: otlp/tempo: endpoint: tempo.monitoring.svc.cluster.local:4317 tls: insecure: true service: extensions: - health_check pipelines: traces: receivers: - otlp processors: - memory_limiter - batch exporters: - otlp/tempo ports: otlp: enabled: true otlp-http: enabled: true jaeger-compact: enabled: false jaeger-thrift: enabled: false jaeger-grpc: enabled: false zipkin: enabled: false service: type: ClusterIP resources: limits: memory: 256Mi requests: cpu: 50m memory: 128Mi这里使用了:
alternateConfig:而不是直接使用:
config:原因是 OpenTelemetry Collector Chart 自带默认配置,其中包括:
Logs Pipeline
Metrics Pipeline
Debug Exporter
Jaeger Receiver
Zipkin Receiver
如果直接覆盖部分config,Helm 会将自定义内容与默认内容合并。
对于本篇只处理 Trace 的最小环境来说,可能会引入不必要的配置。
alternateConfig不与默认配置合并,可以提供一份完全独立的 Collector 配置。但使用这种方式时,必须保留健康检查扩展,否则 Chart 的 Readiness 和 Liveness Probe 可能失败。
1. Receiver
下面的配置表示 Collector 接收 OTLP 数据:
receivers: otlp: protocols: grpc: endpoint: ${env:MY_POD_IP}:4317 http: endpoint: ${env:MY_POD_IP}:4318支持两种协议:
OTLP/gRPC 4317 OTLP/HTTP 43182. Processor
这里配置了两个 Processor:
memory_limiter: batch:memory_limiter用于限制 Collector 内存占用。
batch会将多个 Span 组成批次后再发送,从而减少网络请求次数。
因此,处理过程大致是:
接收 Span │ ▼ 检查内存限制 │ ▼ 批量处理 │ ▼ 发送给 Tempo3. Exporter
下面的配置表示将 Trace 发送到 Tempo:
exporters: otlp/tempo: endpoint: tempo.monitoring.svc.cluster.local:4317 tls: insecure: true由于 Collector 和 Tempo 都运行在同一个 Kubernetes Cluster 内部,因此可以使用 Kubernetes Service DNS:
tempo.monitoring.svc.cluster.local本实验没有配置 TLS,所以设置:
insecure: true4. Pipeline
Trace Pipeline 如下:
pipelines: traces: receivers: - otlp processors: - memory_limiter - batch exporters: - otlp/tempo完整的数据流为:
OTLP Receiver │ ▼ Memory Limiter │ ▼ Batch Processor │ ▼ OTLP Tempo Exporter七、安装 OpenTelemetry Collector
执行:
helm install otel-collector \ open-telemetry/opentelemetry-collector \ -n observability \ -f otel-collector-values.yaml查看 Helm Release:
helm list -n observability1. 查看 Pod
执行:
kubectl get pods -n observability正常情况下可以看到类似结果:
otel-collector-opentelemetry-collector-xxxxxxxxxx-xxxxx 1/1 Running2. 查看 Deployment
执行:
kubectl get deployment -n observability应该可以看到:
otel-collector-opentelemetry-collector3. 查看 Service
执行:
kubectl get svc -n observability应该可以看到:
otel-collector-opentelemetry-collector查看具体端口:
kubectl get svc \ otel-collector-opentelemetry-collector \ -n observability应该包含:
4317/TCP 4318/TCP完整 Service DNS 为:
otel-collector-opentelemetry-collector.observability.svc.cluster.local4. 查看 Collector 日志
执行:
kubectl logs \ -n observability \ deployment/otel-collector-opentelemetry-collector \ --tail=100不同版本的 Collector 日志格式可能略有差异。
正常情况下应该能够看到 OTLP Receiver 和健康检查扩展启动,并且不应该持续出现:
connection refused或者:
failed to export等错误。
此时链路的基础设施部分已经完成:
OpenTelemetry Collector │ ▼ Tempo │ ▼ Grafana但是目前还没有应用产生 Trace。
接下来部署一个最小 Python 应用。
八、创建最小 Trace Demo
为了避免一次部署复杂的 OpenTelemetry Demo 系统,本篇只创建一个最简单的 HTTP 应用。
每次访问:
/应用会生成一个 Trace,其中包含三个 Span:
http-request │ ├── step-1 └── step-2两个子步骤分别模拟:
step-1 100 ms step-2 200 ms通过这个简单例子,可以直观看到:
Trace
Root Span
Child Span
Span Duration
Span Attribute
Service Name
1. 创建 demo-config.yaml
创建文件:
vim demo-config.yaml内容如下:
apiVersion: v1 kind: ConfigMap metadata: name: demo-trace-app namespace: observability data: app.py: | import os import time from flask import Flask from opentelemetry import trace from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( OTLPSpanExporter, ) app = Flask(__name__) service_name = os.getenv( "OTEL_SERVICE_NAME", "demo-trace" ) otlp_endpoint = os.getenv( "OTEL_EXPORTER_OTLP_ENDPOINT", "otel-collector-opentelemetry-collector." "observability.svc.cluster.local:4317" ) resource = Resource.create({ "service.name": service_name, "deployment.environment": "k8s-lab", "service.version": "1.0.0" }) provider = TracerProvider( resource=resource ) exporter = OTLPSpanExporter( endpoint=otlp_endpoint, insecure=True ) processor = BatchSpanProcessor( exporter ) provider.add_span_processor( processor ) trace.set_tracer_provider( provider ) tracer = trace.get_tracer( "demo-trace" ) @app.route("/") def hello(): with tracer.start_as_current_span( "http-request" ) as span: span.set_attribute( "demo.tag", "v1" ) span.set_attribute( "http.route", "/" ) with tracer.start_as_current_span( "step-1" ): time.sleep(0.1) with tracer.start_as_current_span( "step-2" ): time.sleep(0.2) return "hello otel trace\n" @app.route("/slow") def slow(): with tracer.start_as_current_span( "slow-request" ) as span: span.set_attribute( "demo.slow", True ) with tracer.start_as_current_span( "slow-operation" ): time.sleep(1) return "slow trace generated\n" if __name__ == "__main__": app.run( host="0.0.0.0", port=8080 )这个程序显式设置了几个 Resource Attribute:
service.name deployment.environment service.version其中最重要的是:
service.name = demo-trace后续 Grafana 将根据这个属性查询服务。
应用 ConfigMap:
kubectl apply -f demo-config.yaml检查:
kubectl get configmap -n observability应该可以看到:
demo-trace-app九、部署 Demo Application
创建:
vim demo-app.yaml内容如下:
apiVersion: apps/v1 kind: Deployment metadata: name: demo-trace namespace: observability spec: replicas: 1 selector: matchLabels: app: demo-trace template: metadata: labels: app: demo-trace spec: containers: - name: demo-trace image: python:3.11-slim command: - sh - -c args: - | pip install --no-cache-dir \ flask \ opentelemetry-api \ opentelemetry-sdk \ opentelemetry-exporter-otlp && echo "Starting demo trace application" && python /app/app.py env: - name: OTEL_SERVICE_NAME value: demo-trace - name: OTEL_EXPORTER_OTLP_ENDPOINT value: >- otel-collector-opentelemetry-collector.observability.svc.cluster.local:4317 ports: - name: http containerPort: 8080 readinessProbe: httpGet: path: / port: 8080 initialDelaySeconds: 3 periodSeconds: 5 resources: requests: cpu: 50m memory: 64Mi limits: memory: 256Mi volumeMounts: - name: app mountPath: /app volumes: - name: app configMap: name: demo-trace-app应用:
kubectl apply -f demo-app.yaml查看 Deployment:
kubectl get deployment -n observability查看 Pod:
kubectl get pods -n observability刚开始可能会看到:
ContainerCreating随后进入:
Running由于容器启动时需要执行:
pip install第一次启动可能需要等待一段时间。
查看应用日志:
kubectl logs \ -n observability \ deployment/demo-trace \ -f正常情况下应该可以看到:
Starting demo trace application Running on http://0.0.0.0:8080十、访问 Demo 并生成 Trace
为了从 Kubernetes Node 访问 Demo,先安装socat,执行:
sudo apt update sudo apt install -y socat验证:
command -v socat应该输出:
/usr/bin/socat然后使用:
kubectl port-forward \ -n observability \ deployment/demo-trace \ 8080:8080这里直接使用:
deployment/demo-trace而不是填写具体 Pod 名称。
因为 Pod 名称包含随机字符串,例如:
demo-trace-5ffd95c654-hs448Pod 重新创建后名称会发生变化,而 Deployment 名称保持稳定。
端口转发成功后,会看到类似输出:
Forwarding from 127.0.0.1:8080 -> 8080 Forwarding from [::1]:8080 -> 8080保持这个终端不关闭。
重新打开另一个终端,多访问几次:
curl http://localhost:8080 curl http://localhost:8080 curl http://localhost:8080输出:
hello otel trace再访问慢请求:
curl http://localhost:8080/slow输出:
slow trace generated每执行一次请求,应用都会生成一条新的 Trace。
此时完整链路为:
curl │ ▼ Demo Application │ │ OpenTelemetry SDK ▼ OpenTelemetry Collector │ │ OTLP/gRPC ▼ Tempo正常使用kubectl port-forward时,一般不需要额外安装socat。
只有在特定旧环境或特殊转发工具明确报告缺少socat时,才需要单独处理。
十一、在 Grafana 中配置 Tempo
进入 Grafana。
依次打开:
Connections ↓ Add new connection ↓ Tempo ↓ Add new data source填写 URL:
http://tempo.monitoring.svc.cluster.local:3200这里使用的是:
Tempo HTTP Query API而不是 OTLP 数据接收端口。
两者的作用不同:
4317 Collector 向 Tempo 写入 Trace 3200 Grafana 从 Tempo 查询 Trace本实验中的 Grafana 和 Tempo 都运行在 Kubernetes Cluster 内部,因此 Grafana 可以通过 Kubernetes Service DNS 访问 Tempo。
点击:
Save & Test如果看到类似提示:
Data source is working说明 Grafana 已经能够查询 Tempo。
十二、在 Grafana 中查询 Trace
进入:
Explore选择数据源:
Tempo1. 使用 Search 页面查询
可以在查询界面中选择:
Service Name然后选择:
demo-trace点击:
Run query应该可以看到刚才生成的 Trace。
注意:这里的Limit默认是20,查询的Trace可能较少,可以自行改大。
2. 使用 TraceQL 查询
也可以切换到 TraceQL 模式,输入:
{ resource.service.name = "demo-trace" }这里需要注意,TraceQL 的完整查询需要使用花括号。
不是:
service.name = "demo-trace"而是:
{ resource.service.name = "demo-trace" }3. 查询普通请求
查询 Root Span:
{ name = "http-request" }4. 查询慢请求
查询:
{ name = "slow-request" }或者根据自定义属性查询:
{ span.demo.slow = true }5. 根据环境查询
查询:
{ resource.deployment.environment = "k8s-lab" }6. 根据版本查询
查询:
{ resource.service.version = "1.0.0" }十三、查看完整 Trace
点击其中一条 Trace,可以看到类似结构:
demo-trace: http-request │ ├── http-request 300 ms │ ├── step-1 100 ms │ └── step-2 200 ms其中:
http-request是 Root Span。
下面两个是 Child Span:
step-1 step-2可以看到:
step-1 大约 100 ms step-2 大约 200 ms对于慢请求,则可以看到:
slow-request └── slow-operation 大约 1 s这就是链路追踪最核心的能力:
将一次请求拆分成多个步骤,并显示每个步骤的耗时。
如果真实系统中出现延迟,就可以判断时间主要消耗在:
HTTP 请求处理
数据库查询
外部接口调用
消息队列
缓存访问
业务计算
十四、Trace、Span 和上下文传播
在本篇 Demo 中,我们创建了一个父 Span:
with tracer.start_as_current_span( "http-request" ):然后在父 Span 内创建两个子 Span:
with tracer.start_as_current_span( "step-1" ):以及:
with tracer.start_as_current_span( "step-2" ):OpenTelemetry 会自动识别当前上下文,因此形成:
http-request │ ├── step-1 └── step-2这就是 Span 上下文传播。
如果没有正确传播上下文,可能会变成三条互不相关的 Trace:
Trace A http-request Trace B step-1 Trace C step-2而不是一条完整调用链。
在真正的分布式系统中,上下文还需要通过 HTTP Header 在服务之间传播。
常见 Header 为:
traceparent例如:
Frontend │ │ traceparent ▼ Backend │ │ traceparent ▼ Database Service这样不同服务产生的 Span 才能被组合成同一条 Trace。
本篇 Demo 只在一个进程内部创建父子 Span,因此 OpenTelemetry SDK 可以自动处理上下文。
十五、为什么使用 Collector,而不是直接写入 Tempo?
现在的链路是:
Application │ ▼ Collector │ ▼ Tempo看起来比直接连接 Tempo 多了一层。
但是 Collector 带来了几个重要好处。
1. 应用与存储后端解耦
应用只需要知道:
OTLP Endpoint不需要了解 Tempo 的具体实现。
以后后端变更时,可以只修改 Collector。
2. 批量发送
Collector 使用:
batch processor将多个 Span 合并后发送,减少网络请求次数。
3. 数据处理
Collector 可以在发送前:
删除敏感字段
添加 Kubernetes Metadata
修改属性
丢弃无用数据
对 Trace 进行采样
4. 多后端输出
同一份 Trace 可以同时发送到多个系统:
Application │ ▼ Collector │ │ ▼ ▼ Tempo Another Backend5. 统一入口
多个应用可以统一发送到 Collector:
Frontend ──┐ Backend ──┼──► Collector ──► Tempo Worker ──┘应用不需要分别维护后端连接。
十六、清理测试资源
本篇创建的:
demo-trace ConfigMap demo-trace Deployment主要用于生成测试 Trace。
确认已经能够在 Grafana 中查询 Trace 后,可以删除:
kubectl delete -f demo-app.yaml kubectl delete -f demo-config.yaml检查:
kubectl get pods -n observability此时应该只保留 OpenTelemetry Collector。
Collector 和 Tempo 可以继续保留,因为后续还可以用于:
接入真实应用
演示跨服务 Trace
将 Trace 与 Logs 关联
将 Trace 与 Metrics 关联
进行故障注入实验
如果希望删除整个 Collector 和 Demo 环境,可以执行:
helm uninstall otel-collector \ -n observability kubectl delete namespace observability如果还需要删除 Tempo:
helm uninstall tempo \ -n monitoring不过本系列后续还会继续使用 Tempo,因此暂时建议保留:
Tempo OpenTelemetry Collector Grafana本系列采用的资源管理原则仍然是:
基础设施组件:继续保留 临时测试业务:验证完成后删除这样既能保持实验连续性,也可以避免无用 Pod 不断堆积。
十七、小结:Metrics、Logs 和 Tracing
到这里,单节点 Kubernetes 可观测实验室已经完成了三项核心能力。
Metrics
Kubernetes Metrics │ ▼ Prometheus │ ▼ GrafanaMetrics 主要回答:
系统发生了什么?例如:
CPU 是否过高
Memory 是否不足
Pod 是否频繁重启
请求延迟是否上升
Logs
Pod stdout / stderr │ ▼ Fluent Bit │ ▼ Loki │ ▼ GrafanaLogs 主要回答:
为什么会出现问题?例如:
数据库连接失败
配置文件缺失
权限错误
应用异常退出
Tracing
Application │ ▼ OpenTelemetry Collector │ ▼ Tempo │ ▼ GrafanaTracing 主要回答:
问题发生在哪个调用步骤?例如:
哪个服务最慢
哪次数据库查询耗时过长
请求经过了哪些服务
某个步骤花费了多长时间
将三者放在一起:
Metrics + Logs + Tracing就形成了一个相对完整的可观测体系。
可以简单理解为:
Metrics 发现问题 Logs 解释问题 Tracing 定位问题现在,我们的单节点 Kubernetes 实验室已经具备:
Prometheus Grafana Loki Fluent Bit Tempo OpenTelemetry Collector完整链路为:
Metrics ──► Prometheus ──┐ │ Logs ─────► Loki ────────┼──► Grafana │ Traces ───► Tempo ───────┘当然,目前三种数据仍然相对独立。
真正更有价值的可观测体验,是将它们关联起来:
从 Metrics 发现延迟升高 │ ▼ 进入对应 Trace │ ▼ 定位最慢 Span │ ▼ 查看相关 Pod 日志这也是后续可以继续完善的方向。