Prometheus 的單機架構在小型團隊中運作良好,但面對更大規模的監控需求時,擴充套件性和可靠性就變得至關重要。透過 Alertmanager 的叢集架構,可以有效提升警示處理的容錯能力,避免單點故障。同時,Prometheus 也支援功能分片和水平分片等擴充套件策略,可以根據實際需求靈活調整監控系統的架構。聯邦 API 允許從不同的 Prometheus 伺服器抓取和彙總指標,方便進行跨區域或跨團隊的監控。此外,遠端儲存和第三方工具如 Cortex 和 Thanos,也為構建更具擴充套件性和可靠性的 Prometheus 監控系統提供了更多選擇。

第7章:擴充套件與可靠性

到目前為止,我們已經瞭解了Prometheus作為單一伺服器與單一Alertmanager的運作模式。這種架構適用於許多監控場景,特別是在團隊層級監控自己的資源時。然而,當面對多個團隊時,這種架構往往無法擴充套件,也缺乏足夠的彈性和強健性。如果我們的Prometheus伺服器或Alertmanager過載或故障,監控或警示功能也會隨之失效。

我們將這些問題分為兩個主要關注點:

  • 可靠性與容錯能力
  • 擴充套件性

Prometheus針對每個問題都有不同的解決方案,但我們將探討一些架構上的選擇如何同時解決這兩個問題。在本章中,我們將討論Prometheus處理每個問題的哲學和方法論,並瞭解如何構建更具擴充套件性和強健性的Prometheus實作。

可靠性與容錯能力

Prometheus處理容錯問題的方法受到運作和技術複雜性的影響。在許多情況下,監控服務的容錯能力是透過使監控服務高度可用來實作的,通常是透過叢集化實作。然而,叢集化解決方案需要相對複雜的網路組態和節點間的狀態管理。

值得注意的是,正如我們在第2章提到的,Prometheus專注於即時監控,通常具有有限的資料保留時間,並且假設組態是由組態管理工具管理的。從可用性的角度來看,單個Prometheus伺服器通常被視為可丟棄的。Prometheus的架構認為,實作叢集化和節點間資料一致性所需的投資高於資料本身的價值。

然而,Prometheus並沒有忽視容錯的需求。事實上,Prometheus推薦的容錯解決方案是執行兩個完全相同的Prometheus伺服器平行運作,兩者同時活躍。這種組態產生的重複警示由上游的Alertmanager使用其分組(以及抑制功能)來處理。與其關注Prometheus伺服器的容錯能力,推薦的方法是使上游的Alertmanager具有容錯能力。

圖7.1:容錯架構

這是透過建立Alertmanager叢集來實作的。所有Prometheus伺服器都會向所有Alertmanager傳送警示。如前所述,Alertmanager會負責重複資料刪除,並透過叢集分享警示狀態。

這種方法顯然有一些缺點。首先,兩個Prometheus伺服器都會收集指標,這會使任何潛在的負載加倍。然而,可以認為刮取產生的負載足夠低,不會成為問題。其次,如果單個Prometheus伺服器故障或遭受中斷,您將在一個伺服器上出現資料缺口。這意味著在查詢該伺服器上的資料時需要注意這個缺口。考慮到還有另一個伺服器可供查詢,並且一般關注的是即時資料而非使用Prometheus資料進行長期趨勢分析,這也是一個相對較小的問題。

TIP

有一些方法可以在PromQL中補償這個問題。例如,當請求來自兩個來源的單一指標值時,可以使用兩個指標的最大值。或者,當從可能存在資料缺口的單個工作節點發出警示時,可以增加for子句以確保有多個測量值。

設定Alertmanager叢集

Alertmanager包含由Hashicorp的memberlist函式庫提供的叢集功能。Memberlist是一個Go語言函式庫,使用根據八卦協定(gossip-based protocol)的成員資格管理和成員故障檢測,在本例中是SWIM協定的擴充套件。

要組態叢集,我們需要在多台主機上安裝Alertmanager。在我們的例子中,我們將在三台主機上執行它:am1、am2和am3。首先,我們在每台主機上安裝Alertmanager,就像在第6章中所做的那樣。然後,我們將使用am1主機來初始化叢集。

清單7.1:啟動Alertmanager叢集

am1$ alertmanager --config.file alertmanager.yml --cluster.listen-address 172.19.0.10:8001

內容解密:

  • 執行alertmanager指令並指定設定檔alertmanager.yml
  • 使用--cluster.listen-address指定叢集監聽地址和埠(本例為172.19.0.10:8001

我們執行了alertmanager二進位制檔案,指定了一個組態檔案(可以使用第6章建立的檔案),以及一個叢集監聽地址和埠。應該在叢集中的每個節點上使用相同的組態,以確保警示處理的一致性和叢集行為的一致性。

警告

所有Alertmanager都應使用相同的組態!如果組態不相同,那麼它就不是真正的高用性。

我們指定了am1主機的IP地址(172.19.0.10)和埠(8001)。Alertmanager叢集中的其他節點將使用這個地址連線到叢集,因此需要在Alertmanager叢集節點之間的網路上開放該埠。

TIP

如果不指定叢集監聽地址,它將預設為0.0.0.0,埠為9094。

然後,我們可以在剩下的兩台主機上執行Alertmanager,分別監聽它們的本地IP地址,並參照剛剛建立的叢集節點的IP地址和埠。

提升 Alertmanager 的擴充套件性與可靠性

在建構高用性的監控系統時,Alertmanager 的叢集設定是至關重要的環節。透過建立 Alertmanager 叢集,我們可以確保即使某個節點發生故障,其他節點仍能繼續處理警示,從而提升整體系統的可靠性和容錯能力。

建立 Alertmanager 叢集

要建立 Alertmanager 叢集,需要在多個節點上執行 Alertmanager 程式,並指定叢集監聽地址和對等節點。例如:

am2$ alertmanager --config.file alertmanager.yml --cluster.listen-address 172.19.0.20:8001 --cluster.peer 172.19.0.10:8001
am3$ alertmanager --config.file alertmanager.yml --cluster.listen-address 172.19.0.30:8001 --cluster.peer 172.19.0.10:8001

內容解密:

  • --config.file alertmanager.yml:指定 Alertmanager 的組態檔案。
  • --cluster.listen-address:指定當前節點的叢集監聽地址和埠。
  • --cluster.peer:指定用於加入叢集的對等節點地址和埠。

在上述範例中,我們在 am2am3 節點上啟動了 Alertmanager,並將它們加入到以 am1 為初始節點的叢集中。

驗證 Alertmanager 叢集狀態

要確認叢集是否正常運作,可以存取任意 Alertmanager 節點的 /status 路徑,例如 https://172.19.0.10:9093/status。如果叢集設定正確,你應該能夠看到所有節點的狀態。

此圖示說明瞭 Alertmanager 叢集的狀態:

內容解密:

  • 圖中顯示了 am1am2am3 三個節點之間的叢集內通訊。
  • 每個節點都能與其他節點進行通訊,確保警示能夠在叢集內分享和處理。

組態 Prometheus 以支援 Alertmanager 叢集

為了讓 Prometheus 能夠與 Alertmanager 叢集協同工作,我們需要在 Prometheus 的組態中指定所有的 Alertmanager 節點。這可以透過靜態組態或服務發現機制來實作。

靜態組態範例:

alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - am1:9093
            - am2:9093
            - am3:9093

使用 DNS SRV 記錄進行服務發現:

alerting:
  alertmanagers:
    - dns_sd_configs:
        - names:
            - '_alertmanager._tcp.example.com'

內容解密:

  • static_configs 用於靜態指定 Alertmanager 節點的地址和埠。
  • dns_sd_configs 用於透過 DNS SRV 記錄動態發現 Alertmanager 節點。
  • 使用服務發現機制可以提高組態的靈活性和可維護性。

Prometheus 與 Alertmanager 叢集協同工作

當 Prometheus 組態完成後,它將能夠與所有的 Alertmanager 節點進行通訊,並將警示傳送到叢集中的任意可用節點。Alertmanager 叢集負責處理警示的重複資料刪除和狀態分享,從而確保警示能夠被正確處理。

此圖示展示了 Prometheus 與 Alertmanager 叢集之間的互動:

內容解密:

  • Prometheus 將警示傳送到所有的 Alertmanager 節點。
  • Alertmanager 節點之間進行叢集內通訊,以分享警示狀態並處理重複資料。

擴充套件 Prometheus

除了提升 Alertmanager 的可靠性之外,我們還可以透過多種方式來擴充套件 Prometheus,以滿足大規模監控需求。主要的擴充套件策略包括功能分片和水平分片。

功能分片

功能分片是將不同的監控任務分配到不同的 Prometheus 伺服器上,例如按照地理位置或邏輯域進行劃分。這種方法可以簡化管理和降低單一伺服器的負載。

此圖示展示了功能分片的概念:

內容解密:

  • 不同地區的 Prometheus 伺服器負責監控各自區域內的伺服器。
  • 這種分片方式有助於分散負載和管理複雜度。

水平分片

水平分片是將監控目標分散到多個 Prometheus 工作節點上,並由一個主節點彙總資料。這種方法適用於大規模環境,能夠進一步提升監控系統的可擴充套件性。

此圖示展示了水平分片的概念:

內容解密:

  • 多個工作節點負責抓取不同的監控目標。
  • 主節點從工作節點彙總資料,提供統一的檢視。

綜上所述,透過建立 Alertmanager 叢集和擴充套件 Prometheus,我們可以構建一個高用性和可擴充套件性的監控系統,從而更好地滿足業務需求並提升系統的穩定性。

第7章:擴充套件與可靠性

在Prometheus的架構中,主要伺服器(primary server)不僅彙總指標,還作為預設的資料來源,供Grafana等工具進行圖表展示或指標暴露。若需要進一步擴充套件,可以新增多層次的工作者(worker)和主要伺服器。例如,可以根據不同的可用區域(Availability Zone)或邏輯區域,設定區域性的主要伺服器和工作者,再由全域性主要伺服器彙總這些區域性主要伺服器的資料。

注意事項

  • 當需要查詢未被彙總的指標時,必須直接查詢收集該指標的工作者伺服器。
  • 使用工作者標籤(worker label)來識別正確的工作者。

這種擴充套件方式存在風險和限制。首先,需要從工作者伺服器中抓取部分指標,而非所有指標,這形成了一個類別似金字塔的層級結構,而非分散式結構。主要伺服器對工作者的抓取請求也會增加負載。

此外,這種架構還會影響資料的一致性和正確性。工作者按照各自的抓取間隔收集目標資料,而主要伺服器再從工作者抓取資料,這會導致資料到達主要伺服器的延遲,可能會扭曲資料或延遲警示觸發。因此,不建議在主要伺服器上集中處理警示,而是將警示推到工作者伺服器上處理。

建立分片工作者

為了實作上述架構,首先需要建立多個工作者,並為每個工作者設定唯一的識別資訊。可以使用外部標籤(external labels)來實作這一點。外部標籤會被新增到每個從Prometheus伺服器輸出的時間序列或警示中。

工作者設定範例

global:
  external_labels:
    worker: 0
rule_files:
  - "rules/node_rules.yml"
scrape_configs:
  - job_name: 'node'
    file_sd_configs:
      - files:
          - targets/nodes/*.json
        refresh_interval: 5m
    relabel_configs:
      - source_labels: [__address__]
        modulus: 3
        target_label: __tmp_hash
        action: hashmod
      - source_labels: [__tmp_hash]
        regex: ^0$
        action: keep

在這個設定中,我們為工作者新增了一個名為worker的外部標籤,其值為0。我們還定義了一個抓取任務,使用檔案基礎的服務發現來載入目標清單,並使用重新標記(relabeling)來均勻分配目標到不同的工作者。

聚合時間序列

為了彙總需要被聯邦的時間序列,我們可以使用規則(rules)。例如,可以使用以下規則來彙總CPU、記憶體和磁碟等指標:

groups:
  - name: node_rules
    rules:
      - record: instance:node_cpu:avg_rate5m
        expr: 100 - avg (irate(node_cpu{job="node",mode="idle"}[5m])) by (instance) * 100

這個規則會建立新的時間序列,然後由主要Prometheus伺服器抓取。

主要分片伺服器設定

主要Prometheus伺服器需要設定一個任務來抓取工作者的時間序列。以下是一個範例設定:

scrape_configs:
  - job_name: 'node_workers'
    file_sd_configs:
      - files:
          - 'targets/workers/*.json'
        refresh_interval: 5m
    honor_labels: true
    metrics_path: /federate
    params:
      'match[]':
        - '{__name__=~"^instance:.*"}'

在這個設定中,我們定義了一個名為node_workers的任務,使用檔案基礎的服務發現來發現工作者清單。我們還啟用了honor_labels標誌,以避免主要伺服器覆寫工作者的標籤。

工作者檔案發現範例

[{
  "targets": [
    "worker0:9090",
    "worker1:9090",
    "worker2:9090"
  ]
}]

這個JSON檔案列出了所有工作者的位址。

設定解密:

  1. global.external_labels: 為Prometheus伺服器新增外部標籤,用於識別不同的工作者。
  2. rule_files: 指定規則檔案的位置,用於定義時間序列的彙總規則。
  3. scrape_configs: 定義抓取任務,包括目標的發現和重新標記規則。
  4. relabel_configs: 使用重新標記規則來均勻分配目標到不同的工作者。
  5. honor_labels: 啟用此標誌,以避免主要伺服器覆寫工作者的標籤。
  6. metrics_pathparams: 設定抓取任務使用/federate API,並指定需要比對的時間序列。

第7章:擴充套件與可靠性

聯邦API端點

聯邦(federate)API端點允許我們向遠端Prometheus伺服器查詢特定的時間序列,這些序列由比對引數指定。

比對引數範例

metrics_path: /federate
params:
  'match[]':
    - '{__name__=~"^instance:.*"}'

我們使用params選項來指定match[]引數。match[]引數接受一個即時向量選擇器,用於比對我們想要傳回的特定時間序列。在我們的例子中,我們是根據時間序列的名稱進行比對。

match[]條件

'{__name__=~"^instance:.*"}'

提示:您可以指定多個match[]引數,Prometheus將傳回所有條件的聯集。

這個比對是一個正規表示式比對,傳回所有以instance:開頭的時間序列。我們用來聚合Node Exporter指標的所有規則都以instance:為字首,因此CPU、記憶體和磁碟的時間序列將被主伺服器選取和抓取。

驗證查詢結果

我們可以透過使用curl或瀏覽至/federate路徑(帶有適當的match[]引數)來檢視查詢引數將選取的內容。

聯邦API結果

此圖示

@startuml
skinparam backgroundColor #FEFEFE
skinparam sequenceArrowThickness 2

title Prometheus擴充套件與可靠性叢集架構

actor "客戶端" as client
participant "API Gateway" as gateway
participant "認證服務" as auth
participant "業務服務" as service
database "資料庫" as db
queue "訊息佇列" as mq

client -> gateway : HTTP 請求
gateway -> auth : 驗證 Token
auth --> gateway : 認證結果

alt 認證成功
    gateway -> service : 轉發請求
    service -> db : 查詢/更新資料
    db --> service : 回傳結果
    service -> mq : 發送事件
    service --> gateway : 回應資料
    gateway --> client : HTTP 200 OK
else 認證失敗
    gateway --> client : HTTP 401 Unauthorized
end

@enduml

我們的查詢傳回了所有以instance:開頭的時間序列。主伺服器的node_workers任務將在每次執行時抓取這些指標。然後,您可以使用主伺服器查詢和圖表所有由工作伺服器抓取的目標的聚合指標。

遠端儲存

在擴充套件方面,我們還需要提及最後一點:遠端儲存。Prometheus具有將指標寫入(在某些情況下也可讀取)遠端儲存的能力。寫入遠端儲存的功能允許您將指標從Prometheus傳送到遠端系統,繞過其在可擴充套件性方面的限制。

遠端儲存協定

遠端儲存協定使用根據HTTP的Snappy壓縮協定緩衝編碼。它透過remote_writeremote_read區塊在Prometheus中組態。

目前,Prometheus支援多種寫入和讀取的端點。您可以在Prometheus檔案中找到完整的列表,其中包括Chronix、CrateDB、Graphite、InfluxDB、OpenTSDB和PostgreSQL等。

第三方工具

有一些第三方工具旨在使Prometheus擴充套件更容易。這些工具包括:

  • Cortex - 一個可擴充套件的Prometheus即服務工具。
  • Thanos - 一個具有長期儲存能力的高用性Prometheus設定。
  • Vulcan - 一個現已停止開發的嘗試建立更具擴充套件性的Prometheus專案。主要用作參考。