入门OpenTelemetry——Grafana全家桶方案

方案介绍

OpenTelemetry +Prometheus+ Loki + Tempo + Grafana 是一套现代化、云原生的可观测性解决方案组合,涵盖 Trace(链路追踪)Log(日志)Metrics(指标) 三大核心维度,为微服务架构中的应用提供统一的可观测性平台。

组件介绍

组件作用说明
OpenTelemetry全面采集应用侧统一采集日志、指标、追踪数据,支持多语言 SDK。
Prometheus指标采集与存储主动拉取应用和系统的监控指标,配合 Alertmanager 进行告警。
Loki日志聚合存储结构化日志存储,与 traceID 打通,轻量级类似 Prometheus 的日志系统。
Tempo分布式追踪存储收集 trace 信息,存储于对象存储(如 MinIO/S3)中,便于分析慢请求、链路瓶颈。
Grafana可视化分析平台将三种数据统一呈现,支持联动跳转(如日志 ⇄ 链路),支持告警、仪表盘、探索分析等功能。
Minio对象存储服务MinIO是一个高性能的开源对象存储服务,兼容Amazon S3接口,适合存储大规模非结构化数据,如图片、视频和日志文件。可用于存储指标、日志、链路追踪数据。

系统架构

部署示例应用

应用介绍

https://opentelemetry.io/docs/demo/kubernetes-deployment/

官方为大家写了一个 opentelemetry-demo。

这个项目模拟了一个微服务版本的电子商城,主要包含了以下一些项目:

Service开发语言服务描述
accounting serviceGo处理和计算订单数据
ad serviceJava广告服务
cart service.NET购物车服务,主要会依赖 Redis
checkout serviceGocheckout
currency serviceC++货币转换服务,提供了较高的 QPS 能力。
email serviceRuby邮件服务
frauddetection serviceKotlin风控服务
frontendJavaScript前端应用
loadgeneratorPython/Locust模拟压测服务
payment serviceJavaScript支付服务
productcatalog serviceGo商品服务
quote servicePHP成本服务
recommendation servicePython推荐服务
shipping serviceRustshipping service

部署应用

获取 charts 包

# helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
# helm pull open-telemetry/opentelemetry-demo --untar
# cd opentelemetry-demo 
# ls
Chart.lock  Chart.yaml  examples  grafana-dashboards  README.md  UPGRADING.md        values.yaml
charts      ci          flagd     products            templates  values.schema.json

自定义 charts 包,默认 charts 包集成了opentelemetry-collector、prometheus、grafana、opensearch、jaeger 组件,我们先将其禁用

# vim values.yaml
default:
  # List of environment variables applied to all components
  env:
    - name: OTEL_COLLECTOR_NAME
      value: center-collector.opentelemetry.svc
opentelemetry-collector:
  enabled: false
jaeger:
  enabled: false
prometheus:
  enabled: false
grafana:
  enabled: false
opensearch:
  enabled: false

安装示例应用

# helm install demo . -f values.yaml
- All services are available via the Frontend proxy: http://localhost:8080
  by running these commands:
     kubectl --namespace default port-forward svc/frontend-proxy 8080:8080

  The following services are available at these paths after the frontend-proxy service is exposed with port forwarding:
  Webstore             http://localhost:8080/
  Jaeger UI            http://localhost:8080/jaeger/ui/
  Grafana              http://localhost:8080/grafana/
  Load Generator UI    http://localhost:8080/loadgen/
  Feature Flags UI     http://localhost:8080/feature/
# kubectl get pod                                 
NAME                               READY   STATUS    RESTARTS      AGE
accounting-79cdcf89df-h8nnc        1/1     Running   0             2m15s
ad-dc6768b6-lvzcq                  1/1     Running   0             2m14s
cart-65c89fcdd7-8tcwp              1/1     Running   0             2m15s
checkout-7c45459f67-xvft2          1/1     Running   0             2m13s
currency-65dd8c8f6-pxxbb           1/1     Running   0             2m15s
email-5659b8d84f-9ljr9             1/1     Running   0             2m15s
flagd-57fdd95655-xrmsk             2/2     Running   0             2m14s
fraud-detection-7db9cbbd4d-znxq6   1/1     Running   0             2m15s
frontend-6bd764b6b9-gmstv          1/1     Running   0             2m15s
frontend-proxy-56977d5ddb-cl87k    1/1     Running   0             2m15s
image-provider-54b56c68b8-gdgnv    1/1     Running   0             2m15s
kafka-976bc899f-79vd7              1/1     Running   0             2m14s
load-generator-79dd9d8d58-hcw8c    1/1     Running   0             2m15s
payment-6d9748df64-46zwt           1/1     Running   0             2m15s
product-catalog-658d99b4d4-xpczv   1/1     Running   0             2m13s
quote-5dfbb544f5-6r8gr             1/1     Running   0             2m14s
recommendation-764b6c5cf8-lnkm6    1/1     Running   0             2m14s
shipping-5f65469746-zdr2g          1/1     Running   0             2m15s
valkey-cart-85ccb5db-kr74s         1/1     Running   0             2m15s
# kubectl get svc 
NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ad                ClusterIP   10.103.72.85     <none>        8080/TCP                     2m19s
cart              ClusterIP   10.106.118.178   <none>        8080/TCP                     2m19s
checkout          ClusterIP   10.109.56.238    <none>        8080/TCP                     2m19s
currency          ClusterIP   10.96.112.137    <none>        8080/TCP                     2m19s
email             ClusterIP   10.103.214.222   <none>        8080/TCP                     2m19s
flagd             ClusterIP   10.101.48.231    <none>        8013/TCP,8016/TCP,4000/TCP   2m19s
frontend          ClusterIP   10.103.70.199    <none>        8080/TCP                     2m19s
frontend-proxy    ClusterIP   10.106.13.80     <none>        8080/TCP                     2m19s
image-provider    ClusterIP   10.109.69.146    <none>        8081/TCP                     2m19s
kafka             ClusterIP   10.104.9.210     <none>        9092/TCP,9093/TCP            2m19s
kubernetes        ClusterIP   10.96.0.1        <none>        443/TCP                      176d
load-generator    ClusterIP   10.106.97.167    <none>        8089/TCP                     2m19s
payment           ClusterIP   10.102.143.196   <none>        8080/TCP                     2m19s
product-catalog   ClusterIP   10.109.219.138   <none>        8080/TCP                     2m19s
quote             ClusterIP   10.111.139.80    <none>        8080/TCP                     2m19s
recommendation    ClusterIP   10.97.118.12     <none>        8080/TCP                     2m19s
shipping          ClusterIP   10.107.102.160   <none>        8080/TCP                     2m19s
valkey-cart       ClusterIP   10.104.34.233    <none>        6379/TCP                     2m19s

接下来创建 ingress 资源,暴露frontend-proxy 服务 8080 端口

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: demo
spec:
  entryPoints:
  - web
  routes:
    - match: Host(`demo.cuiliangblog.cn`)
      kind: Rule
      services:
        - name: frontend-proxy
          port: 8080

创建完 ingress 资源后添加 hosts 解析并访问验证。

配置 Ingress 输出

以 ingress 为例,从 Traefik v2.6 开始,Traefik 原生支持使用 OpenTelemetry 协议导出追踪数据(traces),这使你可以将 Traefik 的 tracing 数据发送到兼容 OTel 的后端 。Traefik 部署可参考文档:https://www.cuiliangblog.cn/detail/section/140101250

access 配置参考文档:https://doc.traefik.io/traefik/observability/access-logs/#opentelemetry

# vim values.yaml 
experimental: # 实验性功能配置
  otlpLogs: true # 日志导出otlp格式
additionalArguments: # 自定义启动参数
  - "--experimental.otlpLogs=true"
  - "--accesslog.otlp=true"
  - "--accesslog.otlp.grpc=true"
  - "--accesslog.otlp.grpc.endpoint=center-collector.opentelemetry.svc:4317"
  - "--accesslog.otlp.grpc.insecure=true"
metrics: # 指标
  addInternals: true # 追踪内部流量
  otlp:
    enabled: true # 导出otlp格式
    grpc: # 使用grpc协议
      endpoint: "center-collector.opentelemetry.svc:4317" # OpenTelemetry地址
      insecure: true # 跳过证书
tracing: # 链路追踪
  addInternals: true # 追踪内部流量(如重定向)
  otlp:
    enabled: true # 导出otlp格式
    grpc: # 使用grpc协议
      endpoint: "center-collector.opentelemetry.svc:4317" # OpenTelemetry地址
      insecure: true # 跳过证书

部署组件

部署 MinIO

具体可参考文档:https://www.cuiliangblog.cn/detail/section/121560332,此处不再赘述。部署完成后创建 loki、tempo、thanos 三个 bucket,并创建 ak、sk 然后赋予相关权限。

部署 Prometheus

具体可参考文档:https://www.cuiliangblog.cn/detail/section/15189202,此处不再赘述。

部署 Thanos(可选)

具体可参考文档:https://www.cuiliangblog.cn/detail/section/215968508,此处不再赘述。

部署 Grafana

具体可参考文档:https://www.cuiliangblog.cn/detail/section/15189202,此处不再赘述。

部署 OpenTelemetry

具体可参考文档:https://www.cuiliangblog.cn/detail/section/215947486,此处不再赘述。OpenTelemetry 配置文件内容如下

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
# 元数据定义部分
metadata:
  name: center        # Collector 的名称为 center
  namespace: opentelemetry
# 具体的配置内容
spec:
  replicas: 1           # 设置副本数量为1
  # image: otel/opentelemetry-collector-contrib:latest  # 使用支持 elasticsearch 的镜像
  image: harbor.cuiliangblog.cn/otel/opentelemetry-collector-contrib:latest
  config:               # 定义 Collector 配置
    receivers:          # 接收器,用于接收遥测数据(如 trace、metrics、logs)
      otlp:             # 配置 OTLP(OpenTelemetry Protocol)接收器
        protocols:      # 启用哪些协议来接收数据
          grpc: 
            endpoint: 0.0.0.0:4317      # 启用 gRPC 协议
          http: 
            endpoint: 0.0.0.0:4318      # 启用 HTTP 协议
    processors:         # 处理器,用于处理收集到的数据
      batch: {}         # 批处理器,用于将数据分批发送,提高效率

    exporters:          # 导出器,用于将处理后的数据发送到后端系统
      debug: {}         # 使用 debug 导出器,将数据打印到终端(通常用于测试或调试)
      otlp:               # 数据发送到tempo的grpc端口
        endpoint: "tempo:4317"
        tls: # 跳过证书验证
          insecure: true
      prometheus:
        endpoint: "0.0.0.0:9464" # prometheus指标暴露端口
      loki:
        endpoint: http://loki.loki.svc:3100/loki/api/v1/push

    service:            # 服务配置部分
      telemetry:
        logs:
          level: "debug"              # 设置 Collector 自身日志等级为 debug(方便观察日志)
      pipelines:        # 定义处理管道
        traces:         # 定义 trace 类型的管道
          receivers: [otlp]                      # 接收器为 OTLP
          processors: [batch]                    # 使用批处理器
          exporters: [otlp]                      # 将数据导出到OTLP
        metrics:        # 定义 metrics 类型的管道
          receivers: [otlp]                      # 接收器为 OTLP
          processors: [batch]                    # 使用批处理器
          exporters: [prometheus]          # 将数据导出到prometheus
        logs:
          receivers: [otlp]
          processors: [batch]                    # 使用批处理器
          exporters: [loki]

部署 Tempo

具体可参考文档:https://www.cuiliangblog.cn/detail/section/216677625,此处不再赘述。

部署 Loki

具体可参考文档:https://www.cuiliangblog.cn/detail/section/216677852,此处不再赘述。

Grafana配置

实现步骤

  1. 配置 Loki 、Temp、Prometheus :按照上述步骤,分别部署 Prometheus、Loki 和 Tempo,并配置为 Grafana 的数据源。
  2. 日志注入 Trace ID :如果是手动注入,需要在微服务的日志中注入追踪 ID,通过统一的格式记录。
  3. 创建联合仪表板 :在 Grafana 中创建联合仪表板,通过 Tempo 展示服务调用关系,通过 Prometheus 展示服务指标,通过Loki 展示日志,使用 Trace ID 、Service Name 进行链路追踪、日志、指标数据的关联查询。
  4. 设置告警规则 :在 Grafana 中设置告警规则,例如,当特定的错误日志出现或某些追踪的延迟超出预期时,触发告警通知。

联动配置前提

在日志中注入 trace_id

  • OTel SDK 支持自动注入(如在日志格式中添加 traceid 字段)

Metrics 与 Traces 绑定

  • 通过 labels(如 service_namespan_id)让时序指标和 Trace 关联。tempo开启metricsGenerator 功能后,可以将 traces 数据写入 prometheus。

关联查询实践

Log->Trace

实现从某条日志记录中快速跳转查看相关的 trace 功能,以便更好地定位问题。

loki 数据源配置派生字段,具体可参考文档:https://grafana.com/docs/grafana/next/datasources/loki/configure-loki-data-source/#derived-fields。配置如下:

其中 TraceID 是变量名,type 选择标签匹配,标签是 trace_id。将匹配到的内容通过 ${__value.raw}提取 trace 的值,然后拼接变量到 tempo 的 dashboard 中。

此时我们查询 loki 日志,便可以通过 traceID 实现从日志到指标数据的关联与跳转查询。

新建 名为 Tempo 的 dashboard,定义 trace_id 参数,通过 url 获取。

此时重新加载 dashboard,便可以根据 url 获取 trace_id 参数并查询 tempo 数据。

Log->Metrics

Grafana 中实现 Log → Metrics(从日志跳转到指标),可以根据日志信息查询对应时间段指标数据,用于监控、告警和分析。

OpenTelemetry Metrics 可以分为两大类指标来源

  1. Service Graph 指标(分布式追踪构建的依赖图)

这些是基于 Trace 数据自动生成的 metrics,比如:

traces_service_graph_request_client_seconds_count:服务之间调用的请求次数

traces_service_graph_request_client_seconds_sum:请求总耗时(秒)

traces_service_graph_request_client_seconds_bucket:请求延迟的 histogram 分桶数据

这些指标由 **servicegraph**** processor** 生成。

  1. OpenTelemetry SDK Runtime 指标(运行时指标)

这些指标来自于 SDK 直接采集的应用运行状态,例如:

  • 对于 JVM
    • jvm_memory_used_bytes
    • jvm_threads_count
    • jvm_gc_collection_seconds_sum
  • 对于 Go
    • go_memstats_alloc_bytes
    • process_cpu_seconds_total
  • 对于 Python
    • python_gc_objects_collected_total
    • process_resident_memory_bytes

创建名为 metrics 的 dashboard,内容如下:

配置一个名为server 的变量,用于关联日志与指标数据

修改 loki 数据源配置,新增派生关联字段

查看 loki 日志,既可跳转至对应服务的 metrics 信息

Trace->Metrics

在 Grafana 中实现 Trace → Metrics 查询,也就是从 链路追踪(Tracing)界面跳转到对应的 Metrics(指标)数据面板,可以用于从一个具体的 Trace 看到相关服务的性能指标,比如延迟、错误率、请求量等。这对于 SRE/DevOps 来说是非常有价值的。

接下来我们配置 tempo 数据源关联 prometheus 配置,具体可参考文档https://grafana.com/docs/grafana/next/datasources/tempo/configure-tempo-data-source/#trace-to-metrics

查询 traces 标签信息

查询 metrics 标签信息

添加 tags 转换,将 traces 的 server.name 转换为 metrics 的 server。

添加两个指标,一个是总请求率,PromQL是 sum by (client,server)(rate(traces_service_graph_request_total{$__tags}[$__rate_interval])) ,另一个错误率的 PromQL 是 sum by (client,server)(rate(traces_service_graph_request_failed_total{$__tags}[$__rate_interval]))

接下来通过 traces 查询 metrics 数据。

查询结果如下:

Trace->Log

Grafana 中实现 Tracing → Logging 查询(即从 Trace 页面跳转查看相关日志)是构建完整 Observability 的关键一环。实现从某个具体的 Trace span 跳转到相关时间段和服务的日志,进一步排查问题。

接下来我们配置 tempo 数据源关联 loki 配置,具体可参考文档https://grafana.com/docs/grafana/next/datasources/tempo/configure-tempo-data-source/#trace-to-logs

添加 tags 转换,将 traces 的 server.name 转换为 logging 的 server_name。

添加自定义查询语句,将 tracing 与 logging 关联 {${__tags}} | trace_id="${__span.traceId}"

接下来通过 tracing 查询 logging 数据。

查询结果如下:

告警配置

在现代微服务架构中,服务数量众多、故障路径复杂、故障影响广泛,依靠人工排查日志和指标已无法满足快速定位问题的需求。借助 Grafana 配置 Prometheus 指标告警 和 Loki 日志关键字告警,能够实现问题的实时监测、自动预警、快速定位与响应,是构建高可用 Observability 系统的关键步骤。

  • Metrics 告警 可以基于服务延迟、错误率、CPU/内存等指标,及时发现性能瓶颈或异常行为,如 P95 延迟升高、请求失败率激增、内存飙升等。
  • Loki 日志告警 则弥补了指标粒度不足的问题,能够基于关键字或异常堆栈的出现频率,第一时间检测到程序错误、异常崩溃、权限问题等复杂事件,尤其在问题根因分析中不可或缺。

将两者结合配置告警,能实现从“宏观指标趋势”到“微观日志细节”的闭环监控体系,大幅提升系统稳定性与运维效率,是企业实现高可靠性、高可观测性体系的基础能力。Grafana 告警规则配置具体可参考文档:

https://www.cuiliangblog.cn/detail/article/69

指标告警

推荐配置的告警主要有以下两类

Service Graph 类

用于发现:服务响应慢、依赖超时、调用失败、服务“消失”等。

这些指标通过 OpenTelemetry 的 Trace 数据生成,适用于探测服务之间的延迟和调用失败:

指标告警建议示例 PromQL
traces_service_graph_request_client_seconds_count调用次数异常下降(服务可能宕机)increase(traces_service_graph_request_client_seconds_count[5m]) < 1
traces_service_graph_request_client_seconds_sum
count
平均延迟过高rate(traces_service_graph_request_client_seconds_sum[5m]) / rate(traces_service_graph_request_client_seconds_count[5m]) > 1
(单位:秒)
traces_service_graph_request_client_seconds_bucketp95 响应时间异常histogram_quantile(0.95, rate(traces_service_graph_request_client_seconds_bucket[5m])) > 1

OpenTelemetry SDK 类

这些指标是 SDK 直接采集的,适用于监控服务进程状态和资源消耗:

JVM 示例

指标告警建议示例 PromQL
jvm_memory_used_bytes
/ jvm_memory_max_bytes
JVM 内存使用率 > 80%jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"} > 0.8
jvm_threads_count线程数飙升(可能死循环)jvm_threads_count > 300
jvm_gc_collection_seconds_sumGC 时间异常增加increase(jvm_gc_collection_seconds_sum[5m]) > 5

通用(跨语言)

指标告警建议示例 PromQL
process_cpu_seconds_totalCPU 使用率高rate(process_cpu_seconds_total[1m]) > 0.9
process_resident_memory_bytes内存泄漏趋势increase(process_resident_memory_bytes[10m]) > 100000000

日志告警

配置 日志关键字告警 是发现异常最直接、最及时的方式,尤其适合监控应用抛出的错误、异常堆栈、拒绝请求等。以下是一些常见的关键字和告警配置建议

推荐日志关键字

错误类关键词(系统级/程序级异常)

关键词说明
error通用错误关键字
ExceptionJava/Python 等抛出的异常
NullPointerExceptionJVM 常见致命错误
TracebackPython 错误堆栈
panic:Go 程序崩溃时抛出的 panic
level=errorstructured log 关键字段
status=500HTTP 请求失败(服务端)

性能类关键词(瓶颈、超时、拒绝)

关键词说明
timeout调用超时,可能是依赖或 DB 问题
slow接口响应慢(配合上游埋点)
TooManyRequests
/ 429
接入限流或被限流
OutOfMemoryErrorJVM OOM
rejected线程池拒绝执行任务等场景

业务/安全关键词(敏感场景)

关键词说明
unauthorized
/ 401
非法访问请求
forbidden
/ 403
权限不足
invalid tokenToken 验证失败
login failed登陆失败次数过多可能是攻击
sql error
/ db error
数据库操作失败

Loki Alerting 示例(基于 LogQL)

5 分钟内 error 日志超过 10 条:

count_over_time({app="my-app"} |= "error"[5m]) > 10

多关键词联合

count_over_time({job="checkout"} |= "error" or |= "Exception"[5m]) > 5

使用正则匹配关键词结尾

count_over_time({job="api"} |=~ "(?i)(panic|timeout|oom|Exception)$"[5m]) > 0

查看更多

崔亮的博客-专注devops自动化运维,传播优秀it运维技术文章。更多原创运维开发相关文章,欢迎访问https://www.cuiliangblog.cn
或关注公众号《崔亮的博客》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值