Prometheus + Grafana詳解

  • 2019 年 10 月 8 日
  • 筆記

一 概述

Prometheus 是一個開源監控系統,它前身是 SoundCloud的告警工具包。從 2012 年開始,許多公司和組織開始使用 Prometheus。該項目的開發人員和用戶社區非常活躍,越來越多的開發人員和用戶參與到該項目中。目前它是一個獨立的開源項目,且不依賴於任何公司。為了強調這點和明確該項目治理結構,Prometheus 在 2016 年繼Kurberntes 之後,加入了 Cloud Native Computing Foundation

1.1 prometheus核心概念

1.1.1 數據模型

Prometheus 從根本上存儲的所有數據都是時間序列數據(Time Serie Data,簡稱時序數據)。時序數據是具有時間戳的數據流,該數據流屬於某個度量指標(Metric)和該度量指標下的多個標籤(Label)。除了提供存儲功能,Prometheus 還可以利用查詢表達式來執行非常靈活和複雜的查詢。

  • 度量指標和標籤

每個時間序列(Time Serie,簡稱時序)由度量指標和一組標籤鍵值對唯一確定。

度量指標名稱描述了被監控系統的某個測量特徵(比如 httprequests_total 表示 http 請求總數)。度量指標名稱由 ASCII 字母、數字、下劃線和冒號組成,須匹配正則表達式 `[a-zA-Z:]a-zA-Z0-9_:*`。

標籤開啟了 Prometheus 的多維數據模型。對於同一個度量指標,不同標籤值組合會形成特定維度的時序。Prometheus 的查詢語言可以通過度量指標和標籤對時序數據進行過濾和聚合。改變任何度量指標上的任何標籤值,都會形成新的時序。標籤名稱可以包含 ASCII 字母、數字和下劃線,須匹配正則表達式 [a-zA-Z_][a-zA-Z0-9_]*,帶有 _ 下劃線的標籤名稱保留為內部使用。標籤值可以包含任意 Unicode 字元,包括中文。

  • 取樣值(Sample)

時序數據其實就是一系列取樣值。每個取樣值包括:

  • 一個 64 位的浮點數值
  • 一個精確到毫秒的時間戳
  • 註解(Notation)

一個註解由一個度量指標和一組標籤鍵值對構成。形式如下:

[metric name]{[label name]=[label value], ...}

例如,度量指標為 api_http_requests_total,標籤為 method="POST"、handler="/messages" 的註解表示如下:

api_http_requests_total{method="POST", handler="/messages"}

1.1.2 度量指標類型

  • 計數器(Counter)

計數器是一種累計型的度量指標,它是一個只能遞增的數值。計數器主要用於統計類似於服務請求數、任務完成數和錯誤出現次數這樣的數據。

  • 計量器(Gauge)

計量器表示一個既可以增加, 又可以減少的度量指標值。計量器主要用於測量類似於溫度、記憶體使用量這樣的瞬時數據。

  • 直方圖(Histogram)

直方圖對觀察結果(通常是請求持續時間或者響應大小這樣的數據)進行取樣,並在可配置的桶中對其進行統計。有以下幾種方式來產生直方圖(假設度量指標為 <basename>):

  • 按桶計數,相當於 <basename>_bucket{le="<upper inclusive bound>"}
  • 取樣值總和,相當於 <basename>_sum
  • 取樣值總數,相當於 <basename>_count ,也等同於把所有取樣值放到一個桶里來計數 <basename>_bucket{le="+Inf"}
  • 匯總(Summary)

類似於直方圖,匯總也對觀察結果進行取樣。除了可以統計取樣值總和和總數,它還能夠按分位數統計。有以下幾種方式來產生匯總(假設度量指標為 <basename>):

  • 按分位數,也就是取樣值小於該分位數的個數佔總數的比例小於 φ,相當於 <basename>{quantile="<φ>"}
  • 取樣值總和,相當於 <basename>_sum
  • 取樣值總數,相當於 <basename>_count

1.1.3 任務(Job)和實例(Instance)

在 Prometheus 里,可以從中抓取取樣值的端點稱為實例,為了性能擴展而複製出來的多個這樣的實例形成了一個任務。

例如下面的 api-server 任務有四個相同的實例:

job: api-server  instance 1: 1.2.3.4:5670  instance 2: 1.2.3.4:5671  instance 3: 5.6.7.8:5670  instance 4: 5.6.7.8:5671

Prometheus 抓取完取樣值後,會自動給取樣值添加下面的標籤和值:

  • job: 抓取所屬任務。
  • instance: 抓取來源實例

另外每次抓取時,Prometheus 還會自動在以下時序里插入取樣值:

  • up{job="[job-name]", instance="instance-id"}:取樣值為 1 表示實例健康,否則為不健康
  • scrape_duration_seconds{job="[job-name]", instance="[instance-id]"}:取樣值為本次抓取消耗時間
  • scrape_samples_post_metric_relabeling{job="<job-name>", instance="<instance-id>"}:取樣值為重新打標籤後的取樣值個數
  • scrape_samples_scraped{job="<job-name>", instance="<instance-id>"}:取樣值為本次抓取到的取樣值個數

1.2 prometheus特點

  • 多維度數據模型,一個時間序列由一個度量指標和多個標籤鍵值對確定
  • 靈活的查詢語言,對收集的時許數據進行重組
  • 強大的數據可視化功能,除了內置的瀏覽器,也支援grafana集成
  • 高效存儲,記憶體加本地磁碟,可通過功能分片和聯盟來拓展性能
  • 運維簡單,只依賴於本地磁碟,go二進位安裝包沒有任何其他依賴
  • 精簡告警
  • 非常多的客戶端庫
  • 提供了許多導出器來收集常用系統指標

1.3 altermanager 核心概念

1.3.1 分組

分組將類似性質的警報分類為單個通知。在許多系統一次性失敗並且數百到數千個警報可能同時發生的較大中斷期間,這尤其有用。

示例:發生網路分區時,群集中正在運行數十或數百個服務實例。一半的服務實例無法再訪問資料庫。Prometheus中的警報規則配置為在每個服務實例無法與資料庫通訊時發送警報。結果,數百個警報被發送到Alertmanager。

作為用戶,人們只想獲得單個頁面,同時仍能夠確切地看到哪些服務實例受到影響。因此,可以將Alertmanager配置為按群集和alertname對警報進行分組,以便發送單個緊湊通知。

通過配置文件中的路由樹配置警報的分組,分組通知的定時以及這些通知的接收器。

1.3.2 抑制

如果某些其他警報已經觸發,則抑制是抑制某些警報的通知的概念。示例:正在觸發警報,通知無法訪問整個集群。Alertmanager可以配置為在該特定警報觸發時將與該集群有關的所有其他警報靜音。這可以防止數百或數千個與實際問題無關的觸發警報的通知。通過Alertmanager的配置文件配置禁止。

1.3.3 沉默

沉默是在給定時間內簡單地靜音警報的簡單方法。基於匹配器配置靜默,就像路由樹一樣。檢查傳入警報它們是否匹配活動靜默的所有相等或正則表達式匹配器。如果他們這樣做,則不會發送該警報的通知。在Alertmanager的Web介面中配置了靜音。

1.3.4 客戶端行為

Alertmanager對其客戶的行為有特殊要求。這些僅適用於不使用Prometheus發送警報的高級用例。

1.3.5 高可用

Alertmanager支援配置以創建用於高可用性的集群。這可以使用–cluster- *標誌進行配置。重要的是不要在Prometheus和它的Alertmanagers之間載入平衡流量,而是將Prometheus指向所有Alertmanagers的列表。

二 架構

2.1 prometheus架構圖

2.2 altermanager架構圖

三 與其他監控系統對不

3.1 Prometheus vs. Zabbix

  • Zabbix 使用的是 C 和 PHP, Prometheus 使用 Golang, 整體而言 Prometheus 運行速度更快一點。
  • Zabbix 屬於傳統主機監控,主要用於物理主機、交換機、網路等監控,Prometheus 不僅適用主機監控,還適用於 Cloud、SaaS、Openstack、Container 監控。
  • Zabbix 在傳統主機監控方面,有更豐富的插件。
  • Zabbix 可以在 WebGui 中配置很多事情,Prometheus 需要手動修改文件配置。、

3.2 Prometheus vs. Nagios

  • Nagios 數據不支援自定義 Labels, 不支援查詢,告警也不支援去噪、分組, 沒有數據存儲,如果想查詢歷史狀態,需要安裝插件。
  • Nagios 是上世紀 90 年代的監控系統,比較適合小集群或靜態系統的監控Nagios 太古老,很多特性都沒有,Prometheus 要優秀很多。

3.3 Prometheus vs Sensu

  • Sensu 廣義上講是 Nagios 的升級版本,它解決了很多 Nagios 的問題,如果你對 Nagios 很熟悉,使用 Sensu 是個不錯的選擇。
  • Sensu 依賴 RabbitMQ 和 Redis,數據存儲上擴展性更好。

3.4 Prometheus vs InfluxDB

  • InfluxDB 是一個開源的時序資料庫,主要用於存儲數據,如果想搭建監控告警系統,需要依賴其他系統。
  • InfluxDB 在存儲水平擴展以及高可用方面做的更好, 畢竟核心是資料庫。

四 安裝部署

4.1 prometheus安裝

  • 二進位安裝
cd /opt && wget https://github.com/prometheus/prometheus/releases/download/v2.12.0/prometheus-2.12.0.linux-amd64.tar.gz  tar -zxf prometheus-2.12.0.linux-amd64.tar.gz  mv prometheus-2.12.0.linux-amd64 prometheus  chown root.root prometheus -R    # 配置為服務  cat >/usr/lib/systemd/system/prometheus.service <<EOF  [Unit]  Description=Prometheus  Documentation=https://prometheus.io/  After=network.target    [Service]  Type=simple  ExecStart=/opt/prometheus/prometheus --config.file=/opt/prometheus/prometheus.yml  Restart=on-failure    [Install]  WantedBy=multi-user.target  EOF    # 設置服務開機自啟動  systemctl enable prometheus  systemctl start prometheus    # 直接啟動  nohup ./prometheus --config.file=prometheus.yml 2>&1 1>prometheus.log &    # 查看服務  [root@VM_0_13_centos pushgateway]# netstat -lntup |grep prometheus  tcp6       0      0 :::9090                 :::*                    LISTEN      16655/prometheus
  • 源碼編譯安裝
$ go get github.com/prometheus/prometheus/cmd/...  $ prometheus --config.file=your_config.yml      # 或者make build  $ mkdir -p $GOPATH/src/github.com/prometheus  $ cd $GOPATH/src/github.com/prometheus  $ git clone https://github.com/prometheus/prometheus.git  $ cd prometheus  $ make build  $ ./prometheus --config.file=your_config.yml
  • docker安裝
docker run --name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus

4.2 alertmanager安裝

  • 二進位安裝
cd /opt && wget -c https://github.com/prometheus/alertmanager/releases/download/v0.18.0/alertmanager-0.18.0.linux-amd64.tar.gz  tar zxf alertmanager-0.18.0.linux-amd64.tar.gz  mv alertmanager-0.18.0.linux-amd64 alertmanager  chown root.root alertmanager -R    # 配置服務  cat >/usr/lib/systemd/system/alertmanager.service <<EOF  [Unit]  Description=Alertmanager  Documentation=https://prometheus.io/  After=network.target    [Service]  Type=simple  ExecStart=/opt/alertmanager/alertmanager --config.file=/opt/alertmanager/alertmanager.yml  Restart=on-failure    [Install]  WantedBy=multi-user.target  EOF    # 設置服務開機自啟動  systemctl enable alertmanager  systemctl start alertmanager    # 直接啟動  nohup ./alertmanager --config.file=alertmanager.yml 2>&1 1>alertmanager.log &    # 查看服務  [root@VM_0_13_centos pushgateway]# netstat -lntup |grep alertmanager  tcp6       0      0 :::9094                 :::*                    LISTEN      17237/alertmanager  tcp6       0      0 :::9093                 :::*                    LISTEN      17237/alertmanager  udp6       0      0 :::9094                 :::*                                17237/alertmanager
  • 編譯安裝
$ GO15VENDOREXPERIMENT=1 go get github.com/prometheus/alertmanager/cmd/...  # cd $GOPATH/src/github.com/prometheus/alertmanager  $ alertmanager --config.file=<your_file>    # 手動源碼構建  $ mkdir -p $GOPATH/src/github.com/prometheus  $ cd $GOPATH/src/github.com/prometheus  $ git clone https://github.com/prometheus/alertmanager.git  $ cd alertmanager  $ make build  $ ./alertmanager --config.file=<your_file>    # amtool構建  $ make build BINARIES=amtool
  • docker安裝
docker pull quay.io/prometheus/alertmanager

4.3 node_export安裝

利用node_export來監控主機,官方也提供了很多其他的export可以用來直接使用

  • 二進位安裝
cd /opt && wget -c https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz  tar zxf node_exporter-0.18.1.linux-amd64.tar.gz  mv node_exporter-0.18.1.linux-amd64 node_exporter  chown root.root node_exporter -R    # 配置服務  cat >/usr/lib/systemd/system/node_exporter.service <<EOF  [Unit]  Description=node_exporter  Documentation=https://prometheus.io/  After=network.target    [Service]  Type=simple  ExecStart=/opt/node_exporter/node_exporter  Restart=on-failure    [Install]  WantedBy=multi-user.target  EOF    # 設置服務開機自啟動  systemctl enable node_exporter  systemctl start node_exporter    # 直接啟動  nohup ./node_exporter --config.file=node_exporter.yml 2>&1 1>node_exporter.log &    # 查看服務  [root@VM_0_13_centos pushgateway]# netstat -lntup |grep node_export  tcp6       0      0 :::9100                 :::*                    LISTEN      4551/node_exporter

4.4 pushgateway

  • 安裝
cd /opt && wget -c https://github.com/prometheus/pushgateway/releases/download/v0.9.1/pushgateway-0.9.1.linux-amd64.tar.gz  tar zxf pushgateway-0.9.1.linux-amd64.tar.gz  mv pushgateway-0.9.1.linux-amd64 pushgateway  chown root.root pushgateway -R    # 配置服務  cat >/usr/lib/systemd/system/pushgateway.service <<EOF  [Unit]  Description=pushgateway  Documentation=https://prometheus.io/  After=network.target    [Service]  Type=simple  ExecStart=/opt/pushgateway/pushgateway  Restart=on-failure    [Install]  WantedBy=multi-user.target  EOF    # 設置服務開機自啟動  systemctl enable pushgateway  systemctl start pushgateway    # 直接啟動  nohup ./pushgateway --config.file=node_exporter.yml 2>&1 1>node_exporter.log &    # 查看服務  [root@VM_0_13_centos pushgateway]# netstat -lntup |grep push  tcp6       0      0 :::9091                 :::*                    LISTEN      5982/pushgateway
  • 查看web頁面
  • shell命令創建
echo "some_metric 3.14" | curl --data-binary @- http://localhost:9091/metrics/job/some_job
  • 發送複雜數據
cat <<EOF | curl --data-binary @- http://localhost:9091/metrics/job/some_job/instance/some_instance  # TYPE some_metric counter  some_metric{label="val1"} 42  # TYPE another_metric gauge  # HELP another_metric Just an example.  another_metric 2398.283  EOF

4.5 Grafana配置

4.5.1 grafana安裝

  • 安裝grafana
wget https://dl.grafana.com/oss/release/grafana-6.3.3-1.x86_64.rpm  sudo yum localinstall grafana-6.3.3-1.x86_64.rpm -y    systemctl enable grafana-server.service  systemctl start grafana-server.service  # web頁面3000 登錄資訊:admin/admin    # 安裝插件  grafana-cli plugins install grafana-piechart-panel  systemctl restart grafana-server

4.5.2 添加數據源

添加prometheus,填寫prometheus的管理地址

  • 導入dashboard

通過https://grafana.com/grafana/dashboards中獲取

  • 配置dashboard

4.5.3 grafana告警郵件配置

  • 修改grafana配置文件,添加email配置
# 修改/etc/grafana/grafana.ini    [smtp]  enabled = true  host = smtp.163.com:465  user = 18329903316  # If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;"""  password = xxxxxxxxxxxx  ;cert_file =  ;key_file =  ;skip_verify = false  from_address = [email protected]  ;from_name = Grafana  ;ehlo_identity = dashboard.example.com
  • grafana web介面配置Notification channels

4.5.4 alter配置

⚠️:Template variables are not supported in alert queries,在查詢中不能使用模版語法,不然無法創建告警

告警測試

查看告警歷史

告警觸發

五 PromQL

PromQL(Prometheus Query Language)是 Prometheus 自己開發的表達式語言,語言表現力很豐富,內置函數也很多。使用它可以對時序數據進行篩選和聚合。

5.1 PromQL語法

5.1.1 數據類型

PromQL 表達式計算出來的值有以下幾種類型:

  • 瞬時向量 (Instant vector): 一組時序,每個時序只有一個取樣值
  • 區間向量 (Range vector): 一組時序,每個時序包含一段時間內的多個取樣值
  • 標量數據 (Scalar): 一個浮點數
  • 字元串 (String): 一個字元串,暫時未用

5.1.2 時序選擇器

  • 瞬時向量選擇器

瞬時向量選擇器用來選擇一組時序在某個取樣點的取樣值。

最簡單的情況就是指定一個度量指標,選擇出所有屬於該度量指標的時序的當前取樣值。比如下面的表達式:


http_requests_total


可以通過在後面添加用大括弧包圍起來的一組標籤鍵值對來對時序進行過濾。比如下面的表達式篩選出了 job 為 prometheus,並且 group 為 canary 的時序:


http_requests_total{job="prometheus", group="canary"}


匹配標籤值時可以是等於,也可以使用正則表達式。總共有下面幾種匹配操作符:

  • =:完全相等
  • !=: 不相等
  • =~: 正則表達式匹配
  • !~: 正則表達式不匹配

下面的表達式篩選出了 environment 為 staging 或 testing 或 development,並且 method 不是 GET 的時序:


http_requests_total{environment=~"staging|testing|development",method!="GET"}


度量指標名可以使用內部標籤 __name__ 來匹配,表達式 http_requests_total 也可以寫成 {__name__="http_requests_total"}。表達式 {__name__=~"job:.*"} 匹配所有度量指標名稱以 job: 打頭的時序。

  • 區間向量選擇器

區間向量選擇器類似於瞬時向量選擇器,不同的是它選擇的是過去一段時間的取樣值。可以通過在瞬時向量選擇器後面添加包含在 [] 里的時長來得到區間向量選擇器。比如下面的表達式選出了所有度量指標為 http_requests_total 且 job 為 prometheus 的時序在過去 5 分鐘的取樣值。


http_requests_total{job="prometheus"}5m


時長的單位可以是下面幾種之一:

  • s:seconds
  • m:minutes
  • h:hours
  • d:days
  • w:weeks
  • y:years
  • 偏移修飾器

前面介紹的選擇器默認都是以當前時間為基準時間,偏移修飾器用來調整基準時間,使其往前偏移一段時間。偏移修飾器緊跟在選擇器後面,使用 offset 來指定要偏移的量。比如下面的表達式選擇度量名稱為 http_requests_total 的所有時序在 5 分鐘前的取樣值。


http_requests_total offset 5m


下面的表達式選擇 http_requests_total 度量指標在 1 周前的這個時間點過去 5 分鐘的取樣值。


http_requests_total5m offset 1w


5.2 PromQL操作符

5.2.1 二元操作符

PromQL 的二元操作符支援基本的邏輯和算術運算,包含算術類、比較類和邏輯類三大類。

  • 算術類二元操作符

算術類二元操作符有以下幾種:

  • +:加
  • -:減
  • *:乘
  • /:除
  • %:求余
  • ^:乘方

算術類二元操作符可以使用在標量與標量、向量與標量,以及向量與向量之間

二元操作符上下文里的向量特指瞬時向量,不包括區間向量。

  • 標量與標量之間,結果很明顯,跟通常的算術運算一致。
  • 向量與標量之間,相當於把標量跟向量里的每一個標量進行運算,這些計算結果組成了一個新的向量。
  • 向量與向量之間,會稍微麻煩一些。運算的時候首先會為左邊向量里的每一個元素在右邊向量里去尋找一個匹配元素(匹配規則後面會講),然後對這兩個匹配元素執行計算,這樣每對匹配元素的計算結果組成了一個新的向量。如果沒有找到匹配元素,則該元素丟棄。
  • 比較類二元操作符

比較類二元操作符有以下幾種:

  • == (equal)
  • != (not-equal)
  • > (greater-than)
  • < (less-than)
  • >= (greater-or-equal)
  • <= (less-or-equal)

比較類二元操作符同樣可以使用在標量與標量、向量與標量,以及向量與向量之間。默認執行的是過濾,也就是保留值。可以通過在運算符後面跟 bool 修飾符來使得返回值 0 和 1,而不是過濾。

  • 標量與標量之間,必須跟 bool 修飾符,因此結果只可能是 0(false) 或 1(true)。
  • 向量與標量之間,相當於把向量里的每一個標量跟標量進行比較,結果為真則保留,否則丟棄。如果後面跟了 bool 修飾符,則結果分別為 1 和 0。
  • 向量與向量之間,運算過程類似於算術類操作符,只不過如果比較結果為真則保留左邊的值(包括度量指標和標籤這些屬性),否則丟棄,沒找到匹配也是丟棄。如果後面跟了 bool 修飾符,則保留和丟棄時結果相應為 1 和 0。
  • 邏輯類二元操作符

邏輯操作符僅用於向量與向量之間。

  • and:交集
  • or:合集
  • unless:補集

具體運算規則如下:

  • vector1 and vector2 的結果由在 vector2 里有匹配(標籤鍵值對組合相同)元素的 vector1 里的元素組成。
  • vector1 or vector2 的結果由所有 vector1 里的元素加上在 vector1 里沒有匹配(標籤鍵值對組合相同)元素的 vector2 里的元素組成。
  • vector1 unless vector2 的結果由在 vector2 里沒有匹配(標籤鍵值對組合相同)元素的 vector1 里的元素組成。
  • 二元操作符優先順序

PromQL 的各類二元操作符運算優先順序如下:

  1. ^
  2. *, /, %
  3. +, –
  4. ==, !=, <=, <, >=, >
  5. and, unless
  6. or

5.2.2 向量匹配

前面算術類和比較類操作符都需要在向量之間進行匹配。共有兩種匹配類型,one-to-onemany-to-one / one-to-many

  • One-to-one 向量匹配

相同則為匹配,並且只會有一個匹配元素。可以使用 ignoring 關鍵詞來忽略不參與匹配的標籤,或者使用 on關鍵詞來指定要參與匹配的標籤。語法如下:


<vector expr> <bin-op> ignoring(<label list>) <vector expr>

<vector expr> <bin-op> on(<label list>) <vector expr>


比如對於下面的輸入:


method_code:http_errors:rate5m{method="get", code="500"} 24

method_code:http_errors:rate5m{method="get", code="404"} 30

method_code:http_errors:rate5m{method="put", code="501"} 3

method_code:http_errors:rate5m{method="post", code="500"} 6

method_code:http_errors:rate5m{method="post", code="404"} 21

method:http_requests:rate5m{method="get"} 600

method:http_requests:rate5m{method="del"} 34

method:http_requests:rate5m{method="post"} 120


執行下面的查詢:


method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m


得到的結果為:


{method="get"} 0.04 // 24 / 600

{method="post"} 0.05 // 6 / 120


也就是每一種 method 里 code 為 500 的請求數佔總數的百分比。由於 method 為 put 和 del 的沒有匹配元素所以沒有出現在結果里。

  • Many-to-one / one-to-many 向量匹配

這種匹配模式下,某一邊會有多個元素跟另一邊的元素匹配。這時就需要使用 group_leftgroup_right 組修飾符來指明哪邊匹配元素較多,左邊多則用 group_left,右邊多則用 group_right。其語法如下:


<vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr>

<vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr>

<vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr>

<vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>


組修飾符只適用於算術類和比較類操作符。

對於前面的輸入,執行下面的查詢:


method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m


將得到下面的結果:


{method="get", code="500"} 0.04 // 24 / 600

{method="get", code="404"} 0.05 // 30 / 600

{method="post", code="500"} 0.05 // 6 / 120

{method="post", code="404"} 0.175 // 21 / 120


也就是每種 method 的每種 code 錯誤次數占每種 method 請求數的比例。這裡匹配的時候 ignoring 了 code,才使得兩邊可以形成 Many-to-one 形式的匹配。由於左邊多,所以需要使用 group_left 來指明。

Many-to-one / one-to-many 過於高級和複雜,要盡量避免使用。很多時候通過 ignoring 就可以解決問題。

5.2.3 聚合操作符

PromQL 的聚合操作符用來將向量里的元素聚合得更少。總共有下面這些聚合操作符:

  • sum:求和
  • min:最小值
  • max:最大值
  • avg:平均值
  • stddev:標準差
  • stdvar:方差
  • count:元素個數
  • count_values:等於某值的元素個數
  • bottomk:最小的 k 個元素
  • topk:最大的 k 個元素
  • quantile:分位數

聚合操作符語法如下:

<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]

其中 without 用來指定不需要保留的標籤(也就是這些標籤的多個值會被聚合),而 by 正好相反,用來指定需要保留的標籤(也就是按這些標籤來聚合)。

下面來看幾個示例:

sum(http_requests_total) without (instance)

http_requests_total 度量指標帶有 application、instance 和 group 三個標籤。上面的表達式會得到每個 application 的每個 group 在所有 instance 上的請求總數。效果等同於下面的表達式:

sum(http_requests_total) by (application, group)

下面的表達式可以得到所有 application 的所有 group 的所有 instance 的請求總數。

sum(http_requests_total)

5.3 函數

Prometheus 內置了一些函數來輔助計算,下面介紹一些典型的,完整的列表請參考 官方文檔

  • abs():絕對值
  • sqrt():平方根
  • exp():指數計算
  • ln():自然對數
  • ceil():向上取整
  • floor():向下取整
  • round():四捨五入取整
  • delta():計算區間向量里每一個時序第一個和最後一個的差值
  • sort():排序

六 配置告警規則

將報警集成到睿象雲

6.1 prometheus集成altermanager

# 編輯prometheus.yml    alerting:    alertmanagers:    - static_configs:      - targets:         - 'localhost:9093'    rule_files:    - "onealter.yml"

6.2 編寫rule_files規則文件

# 編寫onealter.yml  groups:    - name: test-rule      rules:        - alert: 節點記憶體使用量          expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes+node_memory_Buffers_bytes+node_memory_Cached_bytes )) / node_memory_MemTotal_bytes * 100 > 40          for: 1m          labels:            user: prometheus          annotations:            summary: "{{$labels.instance}}:記憶體超過40%"            description: "{{$labels.instance}}:記憶體超過40%"

6.3 編輯altermanager.yml配置webhook回調

# 編輯    global:    resolve_timeout: 5m    route:    group_by: ['alertname']    group_wait: 10s    group_interval: 10s    repeat_interval: 1h    receiver: 'team-X-pager'  receivers:  - name: 'team-X-pager'    webhook_configs:    - url: 'http://api.aiops.com/alert/api/event/prometheus/f307ded7-9a96-4e34-101d-dfc421a8743a'      send_resolved: true  inhibit_rules:    - source_match:        severity: 'critical'      target_match:        severity: 'warning'      equal: ['alertname', 'dev', 'instance']

6.4 查看alter告警

參考鏈接