Prometheus監控概述


一、監控系統概論

監控系統在這里特指對數據中心的監控,主要針對數據中心內的硬件和軟件進行監控和告警。企業的 IT 架構逐步從傳統的物理服務器,遷移到以虛擬機為主導的 IaaS 雲。無論基礎架構如何調整,都離不開監控系統的支持。

不僅如此。越來越復雜的數據中心環境對監控系統提出了更越來越高的要求:需要監控不同的對象,例如容器,分布式存儲,SDN網絡,分布式系統。各種應用程序等,種類繁多,還需要采集和存儲大量的監控數據,例如每天數TB數據的采集匯總。以及基於這些監控數據的智能分析,告警及預警等。

在每個企業的數據中心內,或多或少都會使用一些開源或者商業的監控系統。從監控對象的角度來看,可以將監控分為網絡監控,存儲監控,服務器監控和應用監控等,因為需要監控數據中心的各個方面。所以監控系統需要做到面面俱到,在數據中心中充當“天眼“角色。

image-20200411183215918

image-20200411183117435

二、基礎資源監控

2.1、網絡監控

網絡性能監控:主要涉及網絡監測,網絡實時流量監控(網絡延遲、訪問量、成功率)和歷史數據統計、匯總和歷史數據分析等功能。

網絡檢測*:主要針對內網或者外網的網絡***。如DDoS的。通過分析異常流量來確定網絡行為。

設備監控:主要針對數據中心內的多種網絡設備進行監控。包括路由器,防火牆和交換機等硬件設備,可以通過snmp等協議收集數據。

2.2、存儲監控

存儲性能監控方面:存儲通常監控塊的讀寫速率,IOPS。讀寫延遲,磁盤用量等;文件存儲通常監控文件系統inode。讀寫速度、目錄權限等。

存儲系統監控方面:不同的存儲系統有不同的指標,例如,對於ceph存儲需要監控OSD, MON的運行狀態,各種狀態pg的數量以及集群IOPS等信息。

存儲設備監控方面:對於構建在x86服務器上的存儲設備,設備監控通過每個存儲節點上的采集器統一收集磁盤、SSD、網卡等設備信息;存儲廠商以黑盒方式提供商業存儲設備,通常自帶監控功能,可監控設備的運行狀態,性能和容量的。

2.3、服務器監控

CPU:涉及整個 CPU 的使用量、用戶態百分比、內核態百分比,每個 CPU 的使用量、等待隊列長度、I/O 等待百分比、CPU 消耗最多的進程、上下文切換次數、緩存命中率等。

內存:涉及內存的使用量、剩余量、內存占用最高的進程、交換分區大小、缺頁異常等。

網絡 I/O:涉及每個網卡的上行流量、下行流量、網絡延遲、丟包率等。

磁盤 I/O:涉及硬盤的讀寫速率、IOPS、磁盤用量、讀寫延遲等。

2.4、中間件監控

消息中間件: RabbitMQ、Kafka

Web 服務中間件:Tomcat、Jetty

緩存中間件:Redis、Memcached

數據庫中間件:MySQL、PostgreSQL

2.5、應用程序監控(APM)

APM主要是針對應用程序的監控,包括應用程序的運行狀態監控,性能監控,日志監控及調用鏈跟蹤等。調用鏈跟蹤是指追蹤整個請求過程(從用戶發送請求,通常指瀏覽器或者應用客戶端)到后端API服務以及API服務和關聯的中間件,或者其他組件之間的調用,構建出一個完整的調用拓撲結構,不僅如此,APM 還可以監控組件內部方法的調用層次(Controller–>service–>Dao)獲取每個函數的執行耗時,從而為性能調優提供數據支撐。

應用程序監控工具除了有 Pinpoint,還有 Twitter 開源的 Zipkin,Apache SkyWalking,美團開源的 CAT等。

調用鍵監控

image-20200411223300479

幾款產品對比

image-20200411223426624

image-20200411223648557

Pinpoint

image-20200410003448279

image-20200410003525710

通過 APM 除了可以截獲方法調用,還可以截獲TCP、HTTP網絡請求,從而獲得執行耗時最長的方法和 SQL 語句、延遲最大的 API 的信息。

三、Prometheus 簡介

3.1、什么是 Prometheus

Prometheus 是一套開源的系統監控報警框架。它啟發於 Google 的 borgmon 監控系統,由工作在 SoundCloud 的 google 前員工在 2012 年創建,作為社區開源項目進行開發,並於 2015 年正式發布。2016 年,Prometheus 正式加入 Cloud Native Computing Foundation,成為受歡迎度僅次於 Kubernetes 的項目。

3.2、優點

  • 強大的多維度數據模型:

    1. 時間序列數據通過 metric 名和鍵值對來區分。
    2. 所有的 metrics 都可以設置任意的多維標簽。
    3. 數據模型更隨意,不需要刻意設置為以點分隔的字符串。
    4. 可以對數據模型進行聚合,切割和切片操作。
    5. 支持雙精度浮點類型,標簽可以設為全 unicode。
  • 靈活而強大的查詢語句(PromQL):在同一個查詢語句,可以對多個 metrics 進行乘法、加法、連接、取分數位等操作。

  • 易於管理: Prometheus server 是一個單獨的二進制文件,可直接在本地工作,不依賴於分布式存儲。

  • 高效:平均每個采樣點僅占 3.5 bytes,且一個 Prometheus server 可以處理數百萬的 metrics。

  • 使用 pull 模式采集時間序列數據,這樣不僅有利於本機測試而且可以避免有問題的服務器推送壞的 metrics。

  • 可以采用 push gateway 的方式把時間序列數據推送至 Prometheus server 端。

  • 可以通過服務發現或者靜態配置去獲取監控的 targets。

  • 有多種可視化圖形界面。

  • 易於伸縮。

3.3、組件

Prometheus 生態圈中包含了多個組件,其中許多組件是可選的:

  • Prometheus Server: 用於收集和存儲時間序列數據。
  • Client Library: 客戶端庫,為需要監控的服務生成相應的 metrics 並暴露給 Prometheus server。當 Prometheus server 來 pull 時,直接返回實時狀態的 metrics。
  • Push Gateway: 主要用於短期的 jobs。由於這類 jobs 存在時間較短,可能在 Prometheus 來 pull 之前就消失了。為此,這次 jobs 可以直接向 Prometheus server 端推送它們的 metrics。這種方式主要用於服務層面的 metrics,對於機器層面的 metrices,需要使用 node exporter。
  • Exporters: 用於暴露已有的第三方服務的 metrics 給 Prometheus。
  • Alertmanager: 從 Prometheus server 端接收到 alerts 后,會進行去除重復數據,分組,並路由到對收的接受方式,發出報警。常見的接收方式有:電子郵件,pagerduty,OpsGenie, webhook 等。
  • 一些其他的工具。

3.4、架構

從這個架構圖,也可以看出 Prometheus 的主要模塊包含, Server, Exporters, Pushgateway, PromQL, Alertmanager, WebUI 等。

它大致使用邏輯是這樣:

  1. Prometheus server 定期從靜態配置的 targets 或者服務發現的 targets 拉取數據。
  2. 當新拉取的數據大於配置內存緩存區的時候,Prometheus 會將數據持久化到磁盤(如果使用 remote storage 將持久化到雲端)。
  3. Prometheus 可以配置 rules,然后定時查詢數據,當條件觸發的時候,會將 alert 推送到配置的 Alertmanager。
  4. Alertmanager 收到警告的時候,可以根據配置,聚合,去重,降噪,最后發送警告。
  5. 可以使用 API, Prometheus Console 或者 Grafana 查詢和聚合數據。

3.5、適用於什么場景

Prometheus 適用於記錄文本格式的時間序列,它既適用於以機器為中心的監控,也適用於高度動態的面向服務架構的監控。在微服務的世界中,它對多維數據收集和查詢的支持有特殊優勢。Prometheus 是專為提高系統可靠性而設計的,它可以在斷電期間快速診斷問題,每個 Prometheus Server 都是相互獨立的,不依賴於網絡存儲或其他遠程服務。當基礎架構出現故障時,你可以通過 Prometheus 快速定位故障點,而且不會消耗大量的基礎架構資源。

3.6、不適合什么場景

Prometheus 非常重視可靠性,即使在出現故障的情況下,你也可以隨時查看有關系統的可用統計信息。如果你需要百分之百的准確度,例如按請求數量計費,那么 Prometheus 不太適合你,因為它收集的數據可能不夠詳細完整。這種情況下,你最好使用其他系統來收集和分析數據以進行計費,並使用 Prometheus 來監控系統的其余部分。

四、數據模型

4.1、數據模型

Prometheus 所有采集的監控數據均以指標(metric)的形式保存在內置的時間序列數據庫當中(TSDB):屬於同一指標名稱,同一標簽集合的、有時間戳標記的數據流。除了存儲的時間序列,Prometheus 還可以根據查詢請求產生臨時的、衍生的時間序列作為返回結果。

指標名稱和標簽

每一條時間序列由指標名稱(Metrics Name)以及一組標簽(鍵值對)唯一標識。其中指標的名稱(metric name)可以反映被監控樣本的含義(例如,http_requests_total — 表示當前系統接收到的 HTTP 請求總量),指標名稱只能由 ASCII 字符、數字、下划線以及冒號組成,同時必須匹配正則表達式 [a-zA-Z_:][a-zA-Z0-9_:]*

[info] 注意

冒號用來表示用戶自定義的記錄規則,不能在 exporter 中或監控對象直接暴露的指標中使用冒號來定義指標名稱。

通過使用標簽,Prometheus 開啟了強大的多維數據模型:對於相同的指標名稱,通過不同標簽列表的集合,會形成特定的度量維度實例(例如:所有包含度量名稱為 /api/tracks 的 http 請求,打上 method=POST 的標簽,就會形成具體的 http 請求)。該查詢語言在這些指標和標簽列表的基礎上進行過濾和聚合。改變任何度量指標上的任何標簽值(包括添加或刪除指標),都會創建新的時間序列。

標簽的名稱只能由 ASCII 字符、數字以及下划線組成並滿足正則表達式 [a-zA-Z_][a-zA-Z0-9_]*。其中以 __ 作為前綴的標簽,是系統保留的關鍵字,只能在系統內部使用。標簽的值則可以包含任何 Unicode 編碼的字符。

時序樣本

在時間序列中的每一個點稱為一個樣本(sample),樣本由以下三部分組成:

  • 指標(metric):指標名稱和描述當前樣本特征的 labelsets;
  • 時間戳(timestamp):一個精確到毫秒的時間戳;
  • 樣本值(value): 一個 folat64 的浮點型數據表示當前樣本的值。

格式

通過如下表達方式表示指定指標名稱和指定標簽集合的時間序列:

<metric name>{<label name>=<label value>, ...} 
  • 1.
 
 

例如,指標名稱為 api_http_requests_total,標簽為 method="POST" 和 handler="/messages" 的時間序列可以表示為:

api_http_requests_total{method="POST", handler="/messages"}
  • 1.
 
 

這與 OpenTSDB 中使用的標記法相同。

4.2、指標類型

Prometheus 的客戶端庫中提供了四種核心的指標類型。但這些類型只是在客戶端庫(客戶端可以根據不同的數據類型調用不同的 API 接口)和在線協議中,實際在 Prometheus server 中並不對指標類型進行區分,而是簡單地把這些指標統一視為無類型的時間序列。不過,將來我們會努力改變這一現狀的。

Counter

  • 一種累加的 metric,典型的應用如:請求的個數,結束的任務數, 出現的錯誤數等等。

例如 Prometheus server 中 http_requests_total, 表示 Prometheus 處理的 http 請求總數,我們可以使用 delta, 很容易得到任意區間數據的增量,這個會在 PromQL 一節中細講。

image-20200410152345078

Gauge

  • 一種常規的 metric,典型的應用如:溫度,運行的 goroutines 的個數。
  • 可以任意加減。

例如 Prometheus server 中 go_goroutines, 表示 Prometheus 當前 goroutines 的數量。

image-20200410152301768

Histogram

  • 可以理解為柱狀圖,典型的應用如:請求持續時間,響應大小。
  • 可以對觀察結果采樣,分組及統計。

例如,查詢 prometheus_http_request_duration_seconds_sum{handler=“/api/v1/query”,instance=“localhost:9090”,job=“prometheus”}時,返回結果如下:

image-20200410152805983

Summary

  • 類似於 Histogram, 典型的應用如:請求持續時間,響應大小。
  • 提供觀測值的 count 和 sum 功能。
  • 提供百分位的功能,即可以按百分比划分跟蹤結果。

4.3、instance 和 jobs

Prometheus 中,將任意一個獨立的數據源(target)稱之為實例(instance)。包含相同類型的實例的集合稱之為作業(job)。 如下是一個含有四個重復實例的作業:

- 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
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
 
 

自生成標簽和時序

Prometheus 在采集數據的同時,會自動在時序的基礎上添加標簽,作為數據源(target)的標識,以便區分:

  • job: The configured job name that the target belongs to.
  • instance: The <host>:<port> part of the target’s URL that was scraped.

如果其中任一標簽已經在此前采集的數據中存在,那么將會根據 honor_labels 設置選項來決定新標簽。詳見官網解釋: scrape configuration documentation

對每一個實例而言,Prometheus 按照以下時序來存儲所采集的數據樣本:

  • up{job="<job-name>", instance="<instance-id>"}: 1 表示該實例正常工作

  • up{job="<job-name>", instance="<instance-id>"}: 0 表示該實例故障

  • scrape_duration_seconds{job="<job-name>", instance="<instance-id>"} 表示拉取數據的時間間隔

  • scrape_samples_post_metric_relabeling{job="<job-name>", instance="<instance-id>"} 表示采用重定義標簽(relabeling)操作后仍然剩余的樣本數

  • scrape_samples_scraped{job="<job-name>", instance="<instance-id>"} 表示從該數據源獲取的樣本數

其中 up 時序可以有效應用於監控該實例是否正常工作。

五、其他監控工具

在前言中,簡單介紹了我們選擇 Prometheus 的理由,以及使用后給我們帶來的好處。

在這里主要和其他監控方案對比,方便大家更好的了解 Prometheus。

Prometheus vs Zabbix

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

Prometheus vs Graphite

  • Graphite 功能較少,它專注於兩件事,存儲時序數據, 可視化數據,其他功能需要安裝相關插件,而 Prometheus 屬於一站式,提供告警和趨勢分析的常見功能,它提供更強的數據存儲和查詢能力。
  • 在水平擴展方案以及數據存儲周期上,Graphite 做的更好。

Prometheus vs InfluxDB

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

Prometheus vs OpenTSDB

  • OpenTSDB 是一個分布式時序數據庫,它依賴 Hadoop 和 HBase,能存儲更長久數據, 如果你系統已經運行了 Hadoop 和 HBase, 它是個不錯的選擇。
  • 如果想搭建監控告警系統,OpenTSDB 需要依賴其他系統。

Prometheus vs Nagios

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

Prometheus vs Sensu

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

總結

  • Prometheus 屬於一站式監控告警平台,依賴少,功能齊全。
  • Prometheus 支持對雲或容器的監控,其他系統主要對主機監控。
  • Prometheus 數據查詢語句表現力更強大,內置更強大的統計函數。
  • Prometheus 在數據存儲擴展性以及持久性上沒有 InfluxDB,OpenTSDB,Sensu 好。

六、Export

6.1、文本格式

在討論 Exporter 之前,有必要先介紹一下 Prometheus 文本數據格式,因為一個 Exporter 本質上就是將收集的數據,轉化為對應的文本格式,並提供 http 請求。

Exporter 收集的數據轉化的文本內容以行 (\n) 為單位,空行將被忽略, 文本內容最后一行為空行

注釋

文本內容,如果以 # 開頭通常表示注釋。

  • 以 # HELP 開頭表示 metric 幫助說明。
  • 以 # TYPE 開頭表示定義 metric 類型,包含 countergaugehistogramsummary, 和 untyped 類型。
  • 其他表示一般注釋,供閱讀使用,將被 Prometheus 忽略。

采樣數據

內容如果不以 # 開頭,表示采樣數據。它通常緊挨着類型定義行,滿足以下格式:

metric_name [
  "{" label_name "=" `"` label_value `"` { "," label_name "=" `"` label_value `"` } [ "," ] "}"
] value [ timestamp ]
  • 1.
  • 2.
  • 3.
 
 

下面是一個完整的例子:

# HELP http_requests_total The total number of HTTP requests.
# TYPE http_requests_total counter
http_requests_total{method="post",code="200"} 1027 1395066363000
http_requests_total{method="post",code="400"}    3 1395066363000

# Escaping in label values:
msdos_file_access_time_seconds{path="C:\\DIR\\FILE.TXT",error="Cannot find file:\n\"FILE.TXT\""} 1.458255915e9

# Minimalistic line:
metric_without_timestamp_and_labels 12.47

# A weird metric from before the epoch:
something_weird{problem="division by zero"} +Inf -3982045

# A histogram, which has a pretty complex representation in the text format:
# HELP http_request_duration_seconds A histogram of the request duration.
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.05"} 24054
http_request_duration_seconds_bucket{le="0.1"} 33444
http_request_duration_seconds_bucket{le="0.2"} 100392
http_request_duration_seconds_bucket{le="0.5"} 129389
http_request_duration_seconds_bucket{le="1"} 133988
http_request_duration_seconds_bucket{le="+Inf"} 144320
http_request_duration_seconds_sum 53423
http_request_duration_seconds_count 144320

# Finally a summary, which has a complex representation, too:
# HELP rpc_duration_seconds A summary of the RPC duration in seconds.
# TYPE rpc_duration_seconds summary
rpc_duration_seconds{quantile="0.01"} 3102
rpc_duration_seconds{quantile="0.05"} 3272
rpc_duration_seconds{quantile="0.5"} 4773
rpc_duration_seconds{quantile="0.9"} 9001
rpc_duration_seconds{quantile="0.99"} 76656
rpc_duration_seconds_sum 1.7560473e+07
rpc_duration_seconds_count 2693
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
 
 

需要特別注意的是,假設采樣數據 metric 叫做 x, 如果 x 是 histogram 或 summary 類型必需滿足以下條件:

  • 采樣數據的總和應表示為 x_sum
  • 采樣數據的總量應表示為 x_count
  • summary 類型的采樣數據的 quantile 應表示為 x{quantile="y"}
  • histogram 類型的采樣分區統計數據將表示為 x_bucket{le="y"}
  • histogram 類型的采樣必須包含 x_bucket{le="+Inf"}, 它的值等於 x_count 的值。
  • summary 和 historam 中 quantile 和 le 必需按從小到大順序排列。

6.2、常用查詢

收集到 node_exporter 的數據后,我們可以使用 PromQL 進行一些業務查詢和監控,下面是一些比較常見的查詢。

注意:以下查詢均以單個節點作為例子,如果大家想查看所有節點,將 instance="xxx" 去掉即可。

CPU 使用率

100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) 
  • 1.
 
 

CPU 各 mode 占比率

avg by (instance, mode) (irate(node_cpu_seconds_total[5m])) * 100 
  • 1.
 
 

機器平均負載

node_load1{instance="xxx"} // 1分鍾負載
node_load5{instance="xxx"} // 5分鍾負載
node_load15{instance="xxx"} // 15分鍾負載
  • 1.
  • 2.
  • 3.
 
 

內存使用率

100 - ((node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes)/node_memory_MemTotal_bytes) * 100
  • 1.
 
 

磁盤使用率

100 - node_filesystem_free{instance="xxx",fstype!~"rootfs|selinuxfs|autofs|rpc_pipefs|tmpfs|udev|none|devpts|sysfs|debugfs|fuse.*"} / node_filesystem_size{instance="xxx",fstype!~"rootfs|selinuxfs|autofs|rpc_pipefs|tmpfs|udev|none|devpts|sysfs|debugfs|fuse.*"} * 100
  • 1.
 
 

或者你也可以直接使用 {fstype=“xxx”} 來指定想查看的磁盤信息

網絡 IO

// 上行帶寬
sum by (instance) (irate(node_network_receive_bytes{instance="xxx",device!~"bond.*?|lo"}[5m])/128)

// 下行帶寬
sum by (instance) (irate(node_network_transmit_bytes{instance="xxx",device!~"bond.*?|lo"}[5m])/128)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
 
 

網卡出/入包

// 入包量
sum by (instance) (rate(node_network_receive_bytes{instance="xxx",device!="lo"}[5m]))

// 出包量
sum by (instance) (rate(node_network_transmit_bytes{instance="xxx",device!="lo"}[5m]))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM