使用 Prometheus 作为您的 OpenTelemetry 后端

Prometheus 支持通过 HTTP  来进行 OTLP (又名“OpenTelemetry 协议”)的摄取。

启用 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

在查询时包含资源属性

默认情况下,除 service.instance.idservice.namespaceservice.name 外,所有 OTel 资源属性都会被转换为特殊 target_info 指标的标签。这意味着,对于您未推广的 OTel 资源属性,您仍然可以通过与 target_info 进行连接来在查询中包含相应的标签。为了实现这一点,我们建议启用实验性的 PromQL 函数 info,以便通过以下标志轻松进行连接:

--enable-feature=promql-experimental-functions

上述查询的示例可以是这样的:

info(rate(http_server_request_duration_seconds_count[2m]), {k8s_cluster_name=~".+"})

或者,可以通过原始连接查询实现相同的功能:

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 将点转换为下划线,除非另有配置)。

但请注意,info 函数通常比原始连接查询更高效,因为它只选择具有匹配 jobinstance 标签的 target_info 系列。更重要的是,info 函数解决了连接查询方法中一个旧的、相当晦涩的问题。当除连接标签之外的其他标签的值(即所谓的标识标签)发生变化(即动荡)时,除非旧的 target_info 版本被标记为过时,否则在 PromQL 回溯时间(默认为 5 分钟)期间,旧版本和新版本 target_info 之间会存在重叠。在此期间,由于存在两个匹配的不同 target_info 时间序列,针对 target_info 的连接查询将失败。幸运的是,info 函数没有这个问题,因为它总是选择最新的样本!

那么,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。但是,可以启用以下配置参数,将它们直接添加到 target_info(如果 otlp.translation_strategy 设置为 UnderscoreEscapingWithSuffixes,则会进行规范化以将点替换为下划线),除此之外还会转换为 jobinstance

otlp:
  keep_identifying_resource_attributes: true

资源的其他资源属性也会作为标签添加到 target_info 系列中,如果 otlp.translation_strategy 设置为 UnderscoreEscapingWithSuffixes,则会根据 Prometheus 的格式进行名称转换(例如,点转换为下划线)。如果资源既没有 service.instance.id 也没有 service.name 属性,则不会生成相应的 target_info 系列。

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

UTF-8

从 3.x 版本开始,Prometheus 支持指标名称和标签的 UTF-8,因此可以省略 OpenTelemetry 的 Prometheus 规范化翻译器包 。请注意,当 Prometheus 通过内容协商声明它允许 UTF-8 字符时,它并不要求指标名称包含先前不支持的字符。OTLP 指标的转换方式可能不同,具体取决于端点的配置。因此,虽然 Prometheus 存储和 UI 中默认启用了 UTF-8,但您需要为 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

增量时间性

OpenTelemetry 规范指出 ,支持增量时间性和累积时间性。虽然增量时间性在 statsd 和 graphite 等系统中很常见,但累积时间性是 Prometheus 的默认设置。

今天,Prometheus 嵌入了 来自 OpenTelemetry-Collector-contrib  的增量到累积处理器 ,它能够摄入增量并将它们转换为等效的累积表示,然后再存储到 Prometheus 的 TSDB 中。

此功能是实验性的,因此请通过启用功能标志 otlp-deltatocumulative 来启动 Prometheus 以使用它。

该团队仍在努力寻找更有效的方式来处理 OTLP 增量。

本页内容