Prometheus 遠端寫入規格

  • 版本:1.0
  • 狀態:已發佈
  • 日期:2023 年 4 月

本文件旨在定義和標準化現有、廣泛且有機採用的協定的 API、線路格式、協定和語意,而不是提出任何新的內容。

遠端寫入規格旨在記錄 Prometheus 和 Prometheus 遠端寫入相容代理程式如何將資料傳送至 Prometheus 或 Prometheus 遠端寫入相容接收器的標準。

本文件中,關鍵字「必須 (MUST)」、「不得 (MUST NOT)」、「必要 (REQUIRED)」、「應 (SHALL)」、「不應 (SHALL NOT)」、「應該 (SHOULD)」、「不應該 (SHOULD NOT)」、「建議 (RECOMMENDED)」、「可能 (MAY)」和「選擇性 (OPTIONAL)」應按照 RFC 2119 中的說明進行解釋。

注意: 此規格有 2.0 版本可用,請參閱此處

簡介

背景

遠端寫入協定旨在實現從發送器到接收器即時可靠地傳播樣本,而不會遺失。

遠端寫入協定設計為無狀態;嚴格來說沒有訊息間的通訊。因此,該協定不被視為「串流」。為了實現串流效果,應使用例如 HTTP/1.1 或 HTTP/2 在同一連線上傳送多個訊息。考慮過「花俏」的技術 (例如 gRPC),但當時尚未被廣泛採用,而且將 gRPC 服務公開到 AWS EC2 ELB 之類的負載平衡器後面的網際網路也很具挑戰性。

遠端寫入協定包含批次處理的機會,例如在單一請求中傳送不同序列的多個樣本。不希望在同一個請求中傳送相同序列的多個樣本,儘管該協定支援此功能。

遠端寫入協定不適用於應用程式將指標推送至 Prometheus 遠端寫入相容接收器。它適用於 Prometheus 遠端寫入相容發送器抓取儀表化應用程式或匯出器,並將遠端寫入訊息傳送至伺服器。

可在 https://github.com/prometheus/compliance/tree/main/remotewrite/sender 找到測試套件。

詞彙表

在本文件中,必須遵循下列定義

  • 「發送器」是發送 Prometheus 遠端寫入資料的物件。
  • 「接收器」是接收 Prometheus 遠端寫入資料的物件。
  • 「樣本」是一對 (時間戳記、值)。
  • 「標籤」是一對 (鍵、值)。
  • 「序列」是樣本清單,由一組唯一的標籤識別。

定義

協定

遠端寫入協定必須由具有下列簽名的 RPC 組成

func Send(WriteRequest)

message WriteRequest {
  repeated TimeSeries timeseries = 1;
  // Cortex uses this field to determine the source of the write request.
  // We reserve it to avoid any compatibility issues.
  reserved  2;

  // Prometheus uses this field to send metadata, but this is
  // omitted from v1 of the spec as it is experimental.
  reserved  3;
}

message TimeSeries {
  repeated Label labels   = 1;
  repeated Sample samples = 2;
}

message Label {
  string name  = 1;
  string value = 2;
}

message Sample {
  double value    = 1;
  int64 timestamp = 2;
}

遠端寫入發送器必須將寫入請求編碼在 HTTP POST 請求的本文中,並透過 HTTP 以提供的 URL 路徑將其傳送至接收器。接收器可以指定任何 HTTP URL 路徑來接收指標。

時間戳記必須是自 Unix epoch 以來以毫秒為單位的 int64。值必須是 float64。

必須隨 HTTP 請求傳送下列標頭

  • Content-Encoding: snappy
  • Content-Type: application/x-protobuf
  • User-Agent: <發送器的名稱和版本>
  • X-Prometheus-Remote-Write-Version: 0.1.0

用戶端可以允許使用者傳送自訂 HTTP 標頭;它們不得允許使用者以會傳送保留標頭的方式設定它們。如需更多資訊,請參閱 https://github.com/prometheus/prometheus/pull/8416

HTTP POST 本文中的遠端寫入請求必須使用 Google Snappy 壓縮。必須使用區塊格式,不得使用框架格式。

遠端寫入請求必須使用 Google Protobuf 3 進行編碼,並且必須使用上述定義的結構描述。請注意,Prometheus 實作使用 gogoproto 最佳化 - 對於以 Golang 以外的語言撰寫的接收器,gogoproto 類型可以替換為行級等效項。

來自遠端寫入接收器的回應本文應該是空的;用戶端必須忽略回應本文。回應本文保留供將來使用。

向前及向後相容性

協定遵循 語義版本控制 2.0:任何 1.x 相容接收器必須能夠讀取任何 1.x 相容發送器,依此類推。破壞性/向後不相容的變更將導致規格的 2.x 版本。

proto 格式本身在某些方面是向前/向後相容的

  • 從 proto 移除欄位將表示主要版本升級。
  • 新增 (選用) 欄位將表示次要版本升級。

交涉

  • 發送器必須在標頭中傳送版本號碼。
  • 接收器可能會在回應標頭 ("X-Prometheus-Remote-Write-Version") 中傳回其支援的最高版本號碼。
  • 希望以 >1.x 格式傳送的發送器必須先傳送一個空的 1.x,並查看回應是否表示接收器支援其他版本。發送器可以使用任何支援的版本。如果回應中沒有版本標頭,發送器必須假設僅支援 1.x 相容性。

標籤

必須隨每個樣本傳送完整的標籤集。此外,與樣本關聯的標籤集

  • 應該包含一個 __name__ 標籤。
  • 不得包含重複的標籤名稱。
  • 必須讓標籤名稱依字典順序排序。
  • 不得包含任何空的標籤名稱或值。

發送器必須只傳送有效的指標名稱、標籤名稱和標籤值

  • 指標名稱必須符合 regex [a-zA-Z_:]([a-zA-Z0-9_:])*
  • 標籤名稱必須符合 regex [a-zA-Z_]([a-zA-Z0-9_])*
  • 標籤值可以是任何 UTF-8 字元序列。

接收器可能會對標籤的數量和長度施加限制,但這將是接收器特定的,並且超出本文件的範圍。

以 "__" 開頭的標籤名稱保留供系統使用,不應使用,請參閱 Prometheus 資料模型

遠端寫入接收器可以擷取寫入請求中其他方面包含無效樣本的有效樣本。對於包含任何無效樣本的寫入請求,接收器必須傳回 HTTP 400 狀態碼 ("Bad Request")。接收器應該在回應本文中提供人類可讀的錯誤訊息。發送器不得嘗試解讀錯誤訊息,並且應按原樣記錄錯誤訊息。

排序

Prometheus 遠端寫入相容發送器必須依時間戳記順序傳送任何給定序列的樣本。Prometheus 遠端寫入相容發送器可以平行傳送不同序列的多個請求。

重試 & 退避

Prometheus 遠端寫入相容發送器必須在 HTTP 5xx 回應上重試寫入請求,並且必須使用退避演算法來防止伺服器負載過重。它們不得在 HTTP 2xx 和 4xx 回應上重試寫入請求,但 429 除外。它們可能會在 HTTP 429 回應上重試,如果伺服器無法跟上,可能會導致發送器「落後」。這樣做是為了確保在伺服器端發生錯誤時不會遺失資料,並且在用戶端發生錯誤時會有所進展。

Prometheus 遠端寫入相容接收器必須在寫入成功時回應 HTTP 2xx 狀態碼。它們必須在寫入失敗且應該重試時回應 HTTP 狀態碼 5xx。它們必須在請求無效、永遠無法成功且不應重試時回應 HTTP 狀態碼 4xx。

過時標記

與 Prometheus 遠端寫入相容的發送器,當時間序列不再有新資料附加時,必須發送過時標記。

過時標記必須使用特殊的 NaN 值 0x7ff0000000000002 來表示。此值不得用於其他用途。

通常,發送器可以使用以下技術偵測到何時不再有新資料附加至時間序列:

  1. 使用服務探索,偵測到暴露該序列的目標已消失
  2. 注意到目標在連續的抓取之間不再暴露該時間序列
  3. 無法抓取最初暴露時間序列的目標
  4. 追蹤記錄和警報規則的配置和評估

超出範圍

本文檔不打算解釋完整 Prometheus 相容監控系統所需的所有功能。特別是,以下領域超出規格的第一個版本範圍:

「up」指標 「up」指標的定義和語義超出遠端寫入協定的範圍,應另行記錄。

HTTP 路徑 HTTP 處理器的路徑可以是任何值,且必須由發送器提供。一般來說,我們期望整個 URL 在設定中指定。

持久性 建議與 Prometheus 遠端寫入相容的發送器,在接收器發生中斷時,應持續緩衝取樣資料。

身份驗證與加密 由於遠端寫入使用 HTTP,我們認為身份驗證與加密是傳輸層的問題。發送器和接收器應支援所有常見的選項(基本身份驗證、TLS 等),並可自由新增潛在的自訂身份驗證選項。Prometheus 遠端寫入發送器和最終代理程式中不應假設支援自訂身份驗證,但我們將盡力支援常見且廣泛使用的身份驗證協定,在可行的情況下。

遠端讀取 這是一個獨立的介面,已經過一些迭代,且使用較不廣泛。

分片 Prometheus 中目前用於遠端寫入平行化的分片方案很大程度上是實作細節,不屬於規格的一部分。當發送器確實實作平行化時,它們必須保留每個序列的取樣順序。

回填 規格沒有限制可以推送多舊的序列,但是可能存在伺服器/實作特定的限制。

限制 標籤的數量和長度、批次大小等的限制超出本文檔的範圍,但預期實作會施加合理的限制。

基於推送的 Prometheus 應用程式將指標推送到與 Prometheus 遠端寫入相容的接收器並非此系統的設計目標,應在單獨的文件中探討。

標籤 每個序列可以包含「job」和/或「instance」標籤,因為這些通常由發送器中的服務探索新增。這些不是強制性的。

未來計畫

本節包含推測性的計畫,這些計畫不被視為協定規格的一部分,但在這裡提及是為了完整性。

交易性 Prometheus 的目標是「交易性」,也就是說,永遠不要向查詢公開部分抓取的目標。我們打算對遠端寫入做同樣的事情。例如,未來我們希望將遠端寫入與抓取「對齊」,也許這樣,單次抓取的所有樣本、中繼資料和範例都會在單次遠端寫入請求中發送。這尚待設計。

中繼資料和範例 與上述一致,我們還會將中繼資料(類型資訊、說明文字)和範例與抓取的樣本一起發送。我們計畫將其打包在單個遠端寫入請求中。規格的未來版本可能會堅持這樣做。Prometheus 目前對發送中繼資料和範例提供實驗性支援。

最佳化 我們希望研究各種最佳化方法,以透過消除標籤名稱和值的重複來減少訊息大小。

相容的發送器和接收器

規格旨在描述以下元件如何互動(截至 2023 年 4 月):

常見問題解答

為什麼不使用 gRPC? 有趣的是,我們最初使用了 gRPC,但後來改為在 HTTP 之上使用 Protos,因為在 2016 年,很難讓它們通過 ELB:https://github.com/prometheus/prometheus/issues/1982

為什麼不串流 protobuf 訊息? 如果您使用持續的 HTTP/1.1 連線,它們非常接近串流……當然,標頭必須重新發送,但這比新的 TCP 設定便宜得多。

為什麼我們要依序發送樣本? 依序限制來自我們在 Prometheus 中用於時間序列資料的編碼,其執行方式僅限附加。可以移除此限制,例如透過緩衝樣本並在編碼之前重新排序它們。我們可以在協定的未來版本中研究此問題。

我們如何在依序限制下平行化請求? 樣本必須 針對給定的序列 依序排列。遠端寫入請求可以平行發送,只要它們是針對不同的序列。在 Prometheus 中,我們將樣本依其標籤分片到單獨的佇列中,然後在每個佇列中依序發生寫入。這可保證同一序列的樣本按順序傳遞,但不同序列的樣本會平行發送,並且在不同序列之間可能會「不按順序」傳遞。

我們認為這是必要的,因為即使接收器可以支援不按順序的樣本,我們也不能讓代理程式發送不按順序的樣本,因為它們永遠無法發送到 Prometheus、Cortex 和 Thanos。我們這樣做是為了確保生態系統的完整性,並防止社群混淆/分叉為「可以寫入 Prometheus 的 Prometheus 代理程式」和不能寫入的代理程式。

本文件是開放原始碼。請透過提交問題或發出提取請求來協助改進它。