將 Prometheus 用作您的 OpenTelemetry 後端

Prometheus 支援透過 HTTP  攝取 OTLP (又稱 “OpenTelemetry 協議”)資料。

啟用 OTLP 接收器

預設情況下,OTLP 接收器是停用的,這與遠端寫入(Remote Write)接收器類似。這是因為 Prometheus 可以在沒有任何身份驗證的情況下執行,因此除非顯式配置,否則接受傳入流量是不安全的。

要啟用該接收器,您需要開啟命令列(CLI)標誌 --web.enable-otlp-receiver。這將使 Prometheus 在 HTTP 路徑 /api/v1/otlp/v1/metrics 上提供 OTLP 指標接收服務。

$ prometheus --web.enable-otlp-receiver

向 Prometheus 伺服器傳送 OpenTelemetry 指標

通常情況下,您需要告訴 OTLP 指標流量的來源 Prometheus 端點,以及應該使用 OTLP 的 HTTP  模式(通常預設使用 gRPC)。

OpenTelemetry SDK 和檢測庫通常可以透過 標準環境變數  進行配置。以下是將 OpenTelemetry 指標傳送到本地主機(localhost)上的 Prometheus 伺服器所需的 OpenTelemetry 變數:

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

注意

關閉跟蹤(Traces)和日誌(Logs)

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

本節介紹了啟用和調優 OpenTelemetry 流程的各種推薦 Prometheus 伺服器配置。

請參閱我們將在以下部分中使用的 Prometheus 配置示例檔案 

啟用亂序攝取

您可能想要啟用亂序(out-of-order)攝取的原因有很多。

例如,OpenTelemetry 收集器(collector)鼓勵批次處理,並且您可能會有多個收集器副本向 Prometheus 傳送資料。由於沒有對這些樣本進行排序的機制,它們可能會發生亂序。

要啟用亂序攝取,您需要在使用以下內容擴充套件 Prometheus 配置檔案:

storage:
  tsdb:
    out_of_order_time_window: 30m

在大多數情況下,允許 30 分鐘的亂序時間已經足夠,但請根據您的需求隨時調整此值。

提升資源屬性

根據經驗以及與社群的交流,我們發現在所有常見的資源屬性中,有一些特別值得附加到您所有的 OTLP 指標上。

預設情況下,Prometheus 不會提升(promote)任何屬性。如果您想提升其中任何屬性,可以在 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 進行連線(join)在查詢中引入相應的標籤。為此,我們建議透過以下標誌啟用實驗性的 PromQL 函式 info 以實現輕鬆連線:

--enable-feature=promql-experimental-functions

此類查詢的一個示例如下:

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

或者,也可以透過原始的連線(join)查詢來實現相同效果:

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 版本被標記為陳舊(stale),否則在 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。然而,除了轉換為 jobinstance 之外,還可以啟用以下配置引數將它們直接新增到 target_info 中(如果 otlp.translation_strategy 設定為 UnderscoreEscapingWithSuffixes,則會進行規範化處理以將點替換為下劃線)。

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 指標可以根據端點的配置以幾種不同的方式進行轉換。因此,雖然 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

增量時效性(Delta Temporality)

OpenTelemetry 規範指出 ,增量時效性(Delta temporality)和累積時效性(Cumulative temporality)都支援。雖然增量時效性在 statsd 和 graphite 等系統中很常見,但在 Prometheus 中預設是累積時效性。

如今,Prometheus 嵌入了來自 OpenTelemetry-Collector-contrib 增量到累積轉換處理器(delta to cumulative processor) ,它能夠在將資料儲存到 Prometheus 的 TSDB 之前,攝取增量並將其轉換為等效的累積表示。

此功能是實驗性的,因此請在啟動 Prometheus 時啟用功能標誌 otlp-deltatocumulative 以使用它。

團隊仍在努力開發一種更高效的處理 OTLP 增量的方法。

本頁內容