使用 Prometheus 作为 OpenTelemetry 后端

Prometheus 支持通过 OTLP(即“OpenTelemetry Protocol”)以 HTTP 方式接收数据。

启用 OTLP 接收器

默认情况下,OTLP 接收器是禁用的,类似于远程写入接收器。这是因为 Prometheus 可以在没有任何认证的情况下工作,因此除非明确配置,否则接受传入流量是不安全的。

要启用接收器,您需要打开 CLI 标志 --web.enable-otlp-receiver。这将使 Prometheus 在 HTTP 路径 /api/v1/otlp/v1/metrics 上提供 OTLP 指标接收服务。

$ prometheus --web.enable-otlp-receiver

将 OpenTelemetry 指标发送到 Prometheus 服务器

通常,您需要告知 OTLP 指标流量的来源关于 Prometheus 端点的信息,以及应使用 OTLP 的 HTTP 模式(gRPC 通常是默认值)。

OpenTelemetry SDK 和仪表化库通常可以通过标准环境变量进行配置。以下是将 OpenTelemetry 指标发送到本地 Prometheus 服务器所需的 OpenTelemetry 变量。

export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://:9090/api/v1/otlp/v1/metrics

关闭跟踪和日志

export OTEL_TRACES_EXPORTER=none
export OTEL_LOGS_EXPORTER=none

OpenTelemetry 指标的默认推送间隔为 60 秒。以下设置将推送间隔设为 15 秒。

export OTEL_METRIC_EXPORT_INTERVAL=15000

如果您的仪表化库没有开箱即用地提供 service.nameservice.instance.id,强烈建议您设置它们。

export OTEL_SERVICE_NAME="my-example-service"
export OTEL_RESOURCE_ATTRIBUTES="service.instance.id=$(uuidgen)"

以上假设您的系统上可用 uuidgen 命令。请确保每个实例的 service.instance.id 都是唯一的,并且每当资源属性更改时,都会生成一个新的 service.instance.id推荐的方法是在实例每次启动时生成一个新的 UUID。

配置 Prometheus

本节解释了 Prometheus 服务器的各种推荐配置方面,以启用和调整您的 OpenTelemetry 流程。

请参阅我们将在下面部分使用的示例 Prometheus 配置文件

启用乱序接收

有多种原因可能需要启用乱序接收。

例如,OpenTelemetry 收集器鼓励批处理,您可能有多个收集器副本向 Prometheus 发送数据。由于没有机制对这些样本进行排序,它们可能会变得乱序。

要启用乱序接收,您需要使用以下内容扩展 Prometheus 配置文件:

storage:
  tsdb:
    out_of_order_time_window: 30m

30 分钟的乱序时间对于大多数情况已经足够,但请随时根据您的需求调整此值。

提升资源属性

根据经验和与我们社区的交流,我们发现在所有常见的资源属性中,有一些值得附加到您所有的 OTLP 指标上。

默认情况下,Prometheus 不会提升任何属性。如果您想提升任何属性,可以在 Prometheus 配置文件的这一部分进行操作。以下代码片段分享了要提升的最佳实践属性集:

otlp:
  # Recommended attributes to be promoted to labels.
  promote_resource_attributes:
    - service.instance.id
    - service.name
    - service.namespace
    - service.version
    - cloud.availability_zone
    - cloud.region
    - container.name
    - deployment.environment
    - deployment.environment.name
    - k8s.cluster.name
    - k8s.container.name
    - k8s.cronjob.name
    - k8s.daemonset.name
    - k8s.deployment.name
    - k8s.job.name
    - k8s.namespace.name
    - k8s.pod.name
    - k8s.replicaset.name
    - k8s.statefulset.name

在查询时包含资源属性

所有未提升的、更详细或唯一的标签都附加到一个特殊的 target_info 指标上。

您可以使用此指标在查询时连接某些标签。

此类查询的示例如下:

rate(http_server_request_duration_seconds_count[2m])
* on (job, instance) group_left (k8s_cluster_name)
target_info

在此查询中,rate(http_server_request_duration_seconds_count[2m]) 产生的时间序列会从共享相同 jobinstance 标签的 target_info 序列中增加 k8s_cluster_name 标签。换句话说,jobinstance 标签在 http_server_request_duration_seconds_counttarget_info 之间共享,类似于 SQL 的外键。而 k8s_cluster_name 标签则对应于 OTel 资源属性 k8s.cluster.name(Prometheus 将点转换为下划线)。

那么,target_info 指标与 OTel 资源属性之间有什么关系呢?当 Prometheus 处理 OTLP 写入请求时,如果包含的资源中含有 service.instance.id 和/或 service.name 属性,Prometheus 会为每个(OTel)资源生成一个 target_info 指标。它会为每个这样的 target_info 序列添加一个 instance 标签,其值为 service.instance.id 资源属性的值;以及一个 job 标签,其值为 service.name 资源属性的值。如果存在 service.namespace 资源属性,它会被前缀到 job 标签值之前(即 <service.namespace>/<service.name>)。

默认情况下,service.nameservice.namespaceservice.instance.id 本身不会被添加到 target_info 中,因为它们被转换为了 jobinstance。但是,可以启用以下配置参数,以便在转换为 jobinstance 的基础上,将它们直接添加到 target_info 中(如果 otlp.translation_strategyUnderscoreEscapingWithSuffixes,则会通过规范化将点替换为下划线)。

otlp:
  keep_identifying_resource_attributes: true

其余的资源属性也会作为标签添加到 target_info 序列中,如果 otlp.translation_strategyUnderscoreEscapingWithSuffixes,名称会转换为 Prometheus 格式(例如,点转换为下划线)。如果资源同时缺少 service.instance.idservice.name 属性,则不会生成相应的 target_info 序列。

对于每个资源的 OTel 指标,Prometheus 会将其转换为相应的 Prometheus 时间序列,并(如果生成了 target_info)添加正确的 instancejob 标签。

UTF-8

从 3.x 版本开始,Prometheus 支持指标名称和标签使用 UTF-8,因此可以省略来自 OpenTelemetry 的 Prometheus 规范化翻译器包。请注意,当 Prometheus 通过内容协商宣布它允许 UTF-8 字符时,它并不要求指标名称包含以前不支持的字符。OTLP 指标可以根据端点的配置以几种不同的方式进行转换。因此,虽然 UTF-8 在 Prometheus 存储和 UI 中默认启用,但您需要为 OTLP 指标接收器设置 translation_strategy,该策略默认设置为旧的规范化方式 UnderscoreEscapingWithSuffixes

有四种可能的翻译策略,其中两种需要 Prometheus 启用 UTF-8 支持:

  • UnderscoreEscapingWithSuffixes,默认值。这将完全转义指标名称以实现经典的Prometheus 指标名称兼容性,并包括附加类型和单位后缀。
  • UnderscoreEscapingWithoutSuffixes。这会像 UnderscoreEscapingWithSuffixes 一样完全转义指标名称,但不附加类型和单位后缀。这种模式从多个角度来看都不可取,用户应该意识到缺少后缀可能导致指标名称冲突,并且只有在经过仔细测试后才应启用此模式。一些组织更喜欢这种在 Otel 对称性和有限字符支持之间的平衡,因此会使用它。
  • NoUTF8EscapingWithSuffixes 将禁用将特殊字符更改为 _,从而允许原生使用 OpenTelemetry 指标格式,尤其是与语义约定结合使用。请注意,会附加单位和计数器的 _total 等特殊后缀,以防止具有相同名称但不同类型或单位的多个指标之间可能发生的冲突。此模式需要启用 UTF-8。
  • NoTranslation。此策略会绕过所有指标和标签名称的翻译,使其保持原样。此模式需要启用 UTF-8。请注意,没有后缀时,当多个具有相同名称但不同类型或单位的指标存在时,可能会发生冲突。
otlp:
  # Ingest OTLP data keeping UTF-8 characters in metric/label names.
  translation_strategy: NoTranslation

Delta 时序性

OpenTelemetry 规范指出,Delta 时序性和 Cumulative 时序性都受支持。虽然 Delta 时序性在 statsd 和 graphite 等系统中很常见,但在 Prometheus 中,Cumulative 时序性是默认的。

如今,Prometheus 内嵌了来自 OpenTelemetry-Collector-contribdelta 到 cumulative 处理器,它能够接收 delta 数据并将其转换为等效的 cumulative 表示形式,然后再存入 Prometheus 的 TSDB。

此功能是实验性的,因此请使用特性开关 otlp-deltatocumulative 启动 Prometheus 来使用它。

团队仍在努力寻找一种更高效处理 OTLP delta 的方法。

本页内容