將 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
注意
- OpenTelemetry 規範 指出,必須將 `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` 環境變數用作基準 URL。訊號
/v1/metrics會被自動追加 - 另請參閱:opentelemetry-python #2443
關閉跟蹤(Traces)和日誌(Logs)
export OTEL_TRACES_EXPORTER=none
export OTEL_LOGS_EXPORTER=none
OpenTelemetry 指標的預設推送間隔為 60 秒。以下設定將把推送間隔調整為 15 秒:
export OTEL_METRIC_EXPORT_INTERVAL=15000
如果您的檢測庫沒有開箱即用提供 service.name 和 service.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.id、service.namespace 和 service.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]) 生成的時間序列,會與共享相同 job 和 instance 標籤的 target_info 序列中的 k8s_cluster_name 標籤進行合併。換句話說,job 和 instance 標籤在 http_server_request_duration_seconds_count 和 target_info 之間共享,類似於 SQL 中的外部索引鍵。而 k8s_cluster_name 標籤則對應於 OTel 資源屬性 k8s.cluster.name(除非另有配置,否則 Prometheus 會將點轉換為下劃線)。
但請注意,info 函式通常比原始連線查詢具有更好的效能,因為它只選擇具有匹配 job 和 instance 標籤的 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.name、service.namespace 和 service.instance.id 本身不會被新增到 target_info 中,因為它們已被轉換為 job 和 instance。然而,除了轉換為 job 和 instance 之外,還可以啟用以下配置引數將它們直接新增到 target_info 中(如果 otlp.translation_strategy 設定為 UnderscoreEscapingWithSuffixes,則會進行規範化處理以將點替換為下劃線)。
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)向其新增正確的 instance 和 job 標籤。
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 增量的方法。