測量什么
在計划度量收集時,必然會出現一個問題,即定義要觀察哪些度量。為了回答這個問題,我們應該求助於當前的最佳實踐和方法。在下面的主題中,我們將概述一些最具影響力和最受關注的方法,這些方法可以降低噪聲,提高性能和一般可靠性方面的可視性。
1.谷歌提出應該監控如下的四個指標:
延遲:服務請求所需的時間
流量:正在發出的請求的數量
錯誤:請求失敗的比率
飽和:未處理的工作量,通常在隊列中。
2.brendan的方法更關注於機器,它聲明對於每個資源(CPU、磁盤、網絡接口等等),應該監視以下指標:
利用率:以資源繁忙的百分比來衡量
飽和:資源無法處理的工作量,通常會排隊
錯誤:發生的錯誤數量
3.湯姆.威爾基的紅色方法
RED方法更側重於服務級別的方法,而不是底層系統本身。顯然,這種策略對於監視服務很有用,對於預測挖補客戶的體驗也很有價值。如果服務的錯誤率增加,那么就可以合理地假設這些錯誤將直接或間接地影響客戶的體驗。這些是需要注意的度量標准:
速率:轉換成每秒請求數
錯誤:每秒失敗請求的數量
持久性:這些請求所花費的時間
prometheus本地存儲

本地存儲時在prometheus存儲數據的標准方法。在一個非常高的層次上,Prometheus的存儲設計是一個索引實現的組合,它使用了所有當前存儲的標簽及其值得發布列表,以及他自己的時間序列數據格式。
1.數據流:Prometheus在本地存儲收集到的數據的方式可以被看作是一個分為三個部分的過程。下面的主題描述了數據在成功持久化之前所經歷的各個階段。
1)最新的一批數據保存在內存中長達兩個小時。這包括在兩個小時時間窗口期收集的一個或多個數據塊。這種方法極大地減少了磁盤IO的兩倍;最新的數據存儲在內存中,查詢速度快的驚人;數據塊是在內存中創建的,避免了持續的磁盤寫操作。
2)預寫日志:
而在內存中,數據不是持久的,如果進程非正常終止,塊被寫入磁盤。這些塊是不可變的,即使數據可以刪除,他也不是原子操作的。相反,tombstone文件是用不再需要的數據信息創建的。
2.布局
我們在下面的例子中可以看到,Prometheus中數據的存儲方式被組織到一系列的目錄(塊)中,這些目錄(塊)包含了數據塊,這些數據的levelDB索引就是一個元數據。帶有人類可讀的關於塊的信息的json文件,以及不再需要的數據的tombstone。每個塊代表一個數據庫。
在頂層,你還可以看到數據沒有刷新到自己的數據塊的WAL:
...
|---01CZMVW4CB6DCKK8Q33XY%ESQH
| |--- chunks
| | |__000001
| |---index
| |---meta.json
| |---tmbstones
|---01CZNGF9GG10R2P56R9G39NTSJE
| |---chunks
| | |__000001
| |---index
| |---meta.json
| |___tombstones
.....................
.....................
prometheus數據模型
prometheus將數據存儲位時間序列,其中包括稱為標簽的鍵值對、時間戳和最后的值。下面的主題將對這些組件進行擴展,並提供每個組件的基礎知識。
1.表示法
普羅米修斯的時間序列如下:
<metric_name>[{<label_1="value_1">,<label_N="value_N">}] <datapoint<numerical_value>
如下案例:
api_http_requests_total{method="POST",handler="messages"}
如您所見,他表示為一個度量名稱,可選地后跟一組或多組花括號內的標簽名稱/值,然后是度量的值。此外,樣本還具有毫秒精度的時間戳。
2.Metric names
盡管這是一個實現細節,度量名稱只不過是一個名為"name"的特殊標簽的值。因此,如果您在內部有一個名為"beverages_total"的度量,他被表示為"_name=beverages_total"。請記住,被“”包圍的標簽是普羅米修斯內的,任何以“__”為前綴的標簽只在度量收集周期的某些階段可用。
標簽(鍵/值)和度量名稱的組合定義了時間序列的標識。
普羅米修斯中的每一個度量名稱都必須符合以下正則表達式:
"[a-zA-Z_:][a-zA-Z0-9_:]*"
只允許英文字母(a-z)、下划線(_)、冒號(:)和阿拉伯數字(0-9)的大小寫字母,不允許使用數字的第一個字符除外。
3.Metric Labels
- 標簽,或與某個度量相關的鍵/值對,向度量添加維度。這時普羅米修斯如此擅長對事件序列進行切片和切割的一個重要部分。
- 雖然標簽值可以是完整的UTF-8,但標簽名稱必須與正則表達式匹配才能被認為是有效的;[例如,“- za-z0-9_]*"。
他們在度量名稱方面的主要區別是標簽名稱不允許冒號(😃。
4.Samples
樣本是采集的數據點,代表時間序列數據的數值。定義一個實例所需要的組件是一個float64值和一個精確到毫秒的時間戳。需要記住的是,不按順序收集的樣本會被普羅米修斯丟棄。同樣的情況也發生在具有相同度量單位和不同樣本值得樣本上。
指標類型
1.counter:計數,該指標數值只增不減,適合統計網卡收發包的數量和字節數、以及系統正常運行的時間等等。除非重啟,不然一直遞增。
2.Gauge:測量是一種度量,它在收集時對給定的測量進行快照,可以增加或減少(例如濕度、磁盤空間和內存使用量)
3.Histogram:在大多數情況下人們都傾向於使用某些量化指標的平均值,例如CPU的平均使用率、頁面的平均響應時間。這種方式的問題很明顯,以系統API調用的平均響應時間為例:如果大多數API請求都維持在100ms的響應時間范圍內,而個別請求的響應時間需要5s,那么就會導致某些web頁面的響應時間落到中位數的情況,而這種現象被稱為長尾問題。
Histogram常常用於觀察,一個Histogram包含下列值得合並:
(1)Buckets:桶是觀察的計數器。它應該有個最大值的邊界和最小值的邊界。他的格式為<basename>_bucket{le="<bound_value>"}
(2)觀察結果的和,這是所有觀察的和。針對它的格式是<basename>_sum
(3)觀察結果統計,這是在本次觀察的和。它的格式為<basename>_count
一個普羅米修斯HTTP請求持續時間以秒為單位,分為桶,這是顯示在Grafana熱圖,以更好地說明桶的概念:
4.Summaries:與Histogram類型類似,用於表示一段時間內的數據采樣結果(通常是請求持續時間或響應大小等),但它直接存儲了分位數(通過客戶端計算,然后展示出來),而不是通過區間來計算。
指標摘要
通常來說,單個指標對我們價值很小,往往需要聯合並可視化多個指標,這其中需要一些數學變換,例如,我們可能會統計函數應用用於指標或只標組,一些可能應用常見函數包括:
計數:計算特定時間間隔內的觀察點數。
求和:將特定時間間隔內所有觀察的值累計相加。
平均值:提供特定時間間隔內所有值的平均值。
中間數:數值的集合中點,正好50%的數值位於它前面,而另外50%則位於它后面。
百分位數:度量占總數特定百分比的觀察點的值。
標准差:顯示指標分布中與平均值的標准差,這可以測量出數據集的差異程度。標准差為0表示數據都等於平均值,較高的標准差意味着數據分布的范圍很廣。
變化率:顯示時間序列中數據之間的變化程度。
指標聚合
除了上述的指標摘要外,可能經常希望能看到來自多個源的指標的聚合視圖,例如所有應用程序服務器的磁盤空間使用情況。指標聚合最典型的樣式就是在一張圖上顯示多個指標,這有助於你識別環境的發展趨勢。例如,負載均衡器中的間歇性故障可能導致多個服務器的web流量下降,這通常比通過查看每個單獨的指標更容易發現。
prometheus安裝和部署
1.Prometheus二進制安裝
去清華源下載二進制包,本實驗使用的是: prometheus-2.31.1.linux-amd64.tar.gz
Prometheus二進制包文件的組織架構:

1.前期准備工作
1)各個主機的DNS解析正確,時間同步。
2)克隆項目
2.安裝prometheus
1)創建新的系統用戶
useradd --system prometheus
2)解壓tar包,並把每個文件放到正確目錄
tar xvf prometheus-2.31.1.linux-amd64.tar.gz
mkdir -pv /usr/share/prometheus/consoles
install -m 0644 -D -t /usr/share/prometheus/consoles prometheus-2.31.1.linux-amd64/consoles/*
mkdir -p /usr/share/prometheus/consoles_libraries
install -m 0644 -D -t /usr/share/prometheus/consoles_libraries prometheus-2.31.1.linux-amd64/console_libraries/*
install -m 0755 prometheus-2.31.1.linux-amd64/promtool /usr/bin/
install -m 0755 prometheus-2.31.1.linux-amd64/prometheus /usr/bin/
install -d -o prometheus -g prometheus /var/lib/prometheus
vim prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
rule_files:
- "first_rules.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets:
- 'prometheus:9090'
- job_name: 'node'
static_configs:
- targets:
- 'prometheus:9100'
- 'grafana:9100'
- 'alertmanager:9100'
- job_name: 'grafana'
static_configs:
- targets:
- 'grafana:3000'
- job_name: 'alertmanager'
static_configs:
- targets:
- 'alertmanager:9093'
vim prometheus.service
# vim:ser ft=systemd
[Unit]
Description=The Prometheus monitoring system and time series database.
Documentation=https://prometheus.io
After=network.target
[Service]
User=prometheus
LimitNOFILE=8192
ExecStart=/usr/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus/data \
--web.console.templates=/usr/share/prometheus/consoles \
--web.console.libraries=/usr/share/prometheus/console_libraries
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
vim first_rules.yml
groups:
- name: example.rules
rules:
- alert: ExampleAlert
expr: vector(42)
labels:
severity: "critical"
annotations:
description: Example alert is firing.
link: http://example.com
install -m 0644 -D prometheus.yml /etc/prometheus/prometheus.yml
install -m 0644 -D first_rules.yml /etc/prometheus/first_rules.yml
install -m 0644 -D prometheus.service /etc/systemd/system/
systemctl daemon-reload
systemctl start prometheus # 或者用prometheus命令:prometheus --config.file=/etc/prometheus.yml
systemctl status prometheus
systemctl enable prometheus
ss -lnt # prometheus監聽在9090端口
2.Prometheus容器安裝
1.docker的安裝推薦方式
prometheus鏡像存儲Docker Hub
如果知識簡單的運行: docker run -p 9090:9090 prom/prometheus 那么只是使用簡單的配置文件,並把它導出為9090端口來運行的。
prometheus鏡像使用一個卷存儲實際的度量。針對生產環境來講,強烈建議使用基於數據卷的容器。
2.如果向使用自己的配置,可以有以下兩種方式:
2.1 卷綁定掛載
(1)使用卷啟動時就掛載(我用的是這種方法)
docekr run -p 9090:9090 -v ~/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
(2)針對配置或者使用其它的卷
docker run -p 9090:9090 -v /path/to/config:/etc/prometheus prom/prometheus
2.2 自定義鏡像
為了比賣你管理主機上的文件並綁定掛載它,可以將配置嵌入到映像中。如果配置本身是靜態的,並且在所有環境中都是相同的,那么這種方法就可以很好地工作。
(1)創建Dockerfile文件內容如下所示:
FROM:prom/prometheus
ADD prometheus.yml /etc/prometheus
(2)執行構建
docker build -t my-prometheus .
docker run -p 9090:9090 my-prometheus
通過docker-compose 管理容器
1.安裝docker-compose
直接去阿里鏡像站下載,那里提供了有關docker的工具包(docker toolbox:docker machine/docker compose/Docker Client/Docker Kitematic
VirtualBox)二進制包,包括docker compose,地址:https://developer.aliyun.com/mirror/docker-toolbox?spm=a2c6h.13651102.0.0.25e31b11yICXdm
# 安裝方法:
1.此包就是二進制,並沒有壓縮,直接下載相應版本docker-compose二進制就行了。
2.執行以下命令:
mv docker-compose-Linux-x86_64 /usr/local/docker-compose # 重命名
ln -s /usr/local/docker-compose /usr/bin/docker-compose
chmod a+x /usr/local/docker-compose
chmod a+x /usr/bin/docker-compose
3. docker-compose -v # 檢查docker-compose版本
2.編寫docker-compose.yml
version: '3'
networks:
monitor: # 創建一個名稱為monitor的網絡,使用的驅動為--driver=bridge; docker network ls。但在啟動容器時會將網絡名稱修改為第一個容器名稱+_monitor
driver: bridge
services:
prometheus:
image: prom/prometheus
container_name: prometheus
hostname: prometheus
user: root
restart: always
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- ./rules:/etc/prometheus/rules
- /prometheus-data:/promtheus # bind volume方式,將prometheus容器內數據庫文件掛載到宿主機,不然默認掛載路徑可以通過docker inspect prometheus查看,/var/lib/docker/volumes/..../_data/
ports:
- "9090:9090"
networks:
- monitor
docker-compose up -d # 啟動docker-compose.yml文件定義所有docker容器
docker-compose down # 停止所有容器
docker-compose start service # 啟動某個容器,前提是此容器已經被創建了
docker-compose restart service # 重啟
docker-compose kill service #殺死某個容器
docker-compose -h # 查看docker-compose命令使用選項
prometheus配置
1.配置prometheus去監控它自身
prometheus通過收集這些目標上的HTTP斷點數據來收集被監控目標的數據。因為普羅米修斯也會以同樣的方式暴露自己的數據,所以它也可以收集可監控自己的健康狀況。
# 配置prometheus.yml文件
global:
scrape_interval: 15s
external_labels:
monitor: 'codelab-monitor'
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'
# Override the global default and scrape targets from this job every 5 seconds.
scrape_interval: 5s
static_configs:
- targets: ['localhost:9090']
prometheus配置命令詳解
prometheus配置主要有兩種方式:
1.直接采用命令行加選項及參數的形式運行;
2.把選項和參數放入到一個配置文件中運行;
prometheus可以在運行時重新加載配置。如果新配置不是有效的配置,則不會應用更改。通過向Prometheus進程發送SIGHUP或向/-/reload 端點發送HTTP POST請求來觸發配置重新加載。這還將重新加載。這還將重新加載任何已配置的規則文件。
1.Prometheus啟動配置

1.1 config
通常首先通過 --config.file選項要設置的是普羅米修斯配置文件路徑。默認Prometheus啟動命令會在在當前目錄查找Prometheus.yml文件。
1.2 storage
--storage.tsdb.path指定數據存儲的路徑。默認的存儲當前目錄中的/data目錄。
1.3 web
--web.external-url 選項指定Prometheus服務器的URL地址。
--web.enable-admin-api選項啟用的話,那么就可以通過HTTP端點執行一些高級管理操作。比如創建數據快照,刪除時間序列數據。
1.4 query
如何調優查詢引擎的內部工作方式。有些非常容易理解,比如給定的查詢在終止之前可以運行多長時間(--query.tumeout),或者可以並發查詢多少(--query.max-concurrency)
2.prometheus配置文件概覽
我們可以把配置文件拆分成如下部分:
global
scrape_configs
alerting
rule_files
remote_read
remote_write
3.全局配置案例
全局配置指定所有其它配置上下文中有效的參數。它們還可以作為其他配置部分的默認值。
global:
scrape_interval: 1m # 抓取度量時間的間隔值,通常10秒-1分鍾之間
scrape_timeout: 10s #設置采取度量的等待時間
evaluation_interval: 1m
external_labels: # 給數據打上標簽
dc: dc1
prom: prom1
# ==================================================================================
1.scrape_interval: <duration> | default =1m:抓取度量的間隔值,默認值為1分鍾
2.[scrape_timeout: <duration> | default = 10s ]:設置抓取度量值的超時時間。
3.[ evaluation_interval: <duration> | default = 1m]:評估警告的間隔,往往和scrape_interval一樣的。
4.external_labels:
[ <labelname>: <labelname> ... ] :當和外部系統(聯綁,遠端存儲,AlertManager)通信時,添加到時間序列數據或警告的標簽。
5. [ query_log_file:<strins>]:PromQL查詢記錄
4.scrape的配置案例
該配置主要指定在收集度量的目標,間的地說,就是采集哪些服務上的值。
配置案例如下所示:
# The job name assigned to scraped metrics by default.
job_name: <job_name>
# How frequently to scrape targets from this job.
[ scrape_interval: <duration> | default = <global_config.scrape_interval> ]
# Per-scrape timeout when scraping this job.
[ scrape_time: <duration> | default = <global_config.scrape_timeout> ]
# The HTTP resource path on whuch to fetch metrics from targets.
[ metrics_path: <path> | default = /metrics ]
# Configures the protocol scheme used for requests.
[ scheme: <scheme> | default = http ]
# Optional HTTP URL parameters.
params:
[ <string>: [<string>,...] ]
# Sets the 'Authorization' header on every scrape request with the configured username and password. password and password_file are mutually exclusive.
basic_auth:
[ username: <string> ]
[ password: <secret> ]
[password_file: <string>]
5.標簽的分類
標簽基本可以分為拓撲標簽和模式標簽:
1.拓撲標簽:通過物理或邏輯組成來切割服務組件。比如Job的名稱,在那個數據中心等等。
2.模式標簽是url,錯誤代碼或user。
6.prometheus的relabel_configs的理解
重新標記是個強大的工具,可以在目標的標簽集被抓取之前俺動態地重寫它。每隔刮擦配置可以配置多個重新標記步驟。他們按在配置文件中出現的順序應用於每隔目標的標簽集。
最初,除了為每隔目標配置的標簽外,還將目標的job標簽設置為各個刮取配置的job_name值。比如__address__標簽設置為目標的
以__開頭的標簽將在目標重新貼標簽完成后從標簽集中移除。
如果重新標記步驟只需要臨時存儲標簽值,使用__tmp的標簽前綴,這個前綴保證普羅米修斯自己永遠不會使用。
# The source labels select values from existing labels. Their content is concatenated using the configured separator and matched against the configured regular expression for the replace,keep,and drop action.
[ source_labels: '[' <labelname> [,...] ']' ]
# Sepatator placed between concatenated source label values.
[ separator: <string> | default = ; ]
# Label to which the resulting value is written in a replace action. It is mandatory for replace actions. Regex capture groups are available.
[ target_label: <labelname> ]
# Regualr expression against which the extrected value is matched.
[ regex: <regex> | default = (.*) ]
# Modulus to take of the hash of the source label values.
[ modulus: ,uint64> ]
# Replacement value againt which a regex replace is performed if the regular expression matches. Regex capture groups are available.
[ replacement: <string> | default = $1 ]
# Action to perform based on regex matching.
[ action: <relabel_action> | default = replace ]
<relable_action>決定着重新標記的動作。
replace:將regex與source_labels進行匹配,如果匹配,那么設置target_label為replacement,如果正則表達式不匹配,那么就不執行動作。
keep:針對正則表達式不匹配source_labels的目標,就丟棄。
drop:針對正則表達式匹配的source_labels的目標,就丟棄。
labeldrop:將regex與所有標簽匹配。任何匹配的標簽都將從標簽集中刪除。
labelkeep:將regex與所有標簽名匹配。任何不匹配的標簽將從標簽集中刪除。
如果沒有定義action,那么默認的就是replace。
我們有兩個階段可以重新標記。第一階段是對來自服務發現的目標進行重新標記,這是對於來自服務發現的元數據標簽中的信息應用於指標上的標簽來說非常有用。第二階段是抓取指標之后但是在存儲系統之前。這樣就可以確定哪些指標需要保存,哪些需要丟棄以及這些指標的樣式。
抓取之前使用relabel_configs,抓取之后使用metrics_relabel_configs.
使用案例
1.丟棄不需要的度量值
2.丟棄不需要的時間序列(帶有特定變量的度量值)
3.丟棄敏感或者某些不想含有某些標簽的度量值。
4.修改最終的標簽格式
在實現這些場景時,Prometheus將在數據被社區和永久存儲之前對這些數據應用一些邏輯。
1.丟棄不需要的度量
- job_name: cadvisor
...
metric_relabel_configs:
- source_labels: [__name__]
regex: '(container_tasks_state|container_memory_failure_total)'
action: drop
他將使帶有名稱container_tasks_state和container_memory_failure_total的metric完全刪除,並且不會存儲在數據庫中,而__name__針對metric名稱的保留的。
2.丟棄不需要的時間序列
- job_name: cadvisor
...
metric_relabel_configs:
- source_labels: [id]
regex: '/system.slice/var-lib-docker-containers.*-shm.mount'
action: drop
- source_labels: [container_label_JenkinsId]
regex: '.+'
action: drop
丟棄所有含有標簽對id='/system.slice/var-lib-docker-containers.*-shm.mount'或者標簽container_label_JenkinsId的時間序列。如果它屬於一個單一的度量,這就沒有必要了。他將適用於所有具有預定義標簽集的指標。這可能又有助於避免不必要的垃圾對指標數據的污染。對於container_label_JenkinsId,當您讓Jenkins在Docker容器中運行從服務器,並且不希望他們打亂底層主機容器指標(例如Jenkins服務器容器本身、系統容器等)時,這一點特別有用。
3.丟棄敏感或者不想要的某些標簽的度量
- job_name: cadvisor
...
metric_relabel_configs:
- regex: 'container_label_com_amazonaws_ecs_task_arn'
action: labeldrop
這個代碼端將中刪除名稱為container_label_com_amazonaws_ecs_task_arn的標簽。當處於安全原因不希望普羅米修斯記錄敏感數據時,這是非常有用的。在我的例子中,我寧願不存儲AWS資源標識符,因為我甚至不需要它們。注意,在刪除標簽時,您需要確保標簽刪除后的最終指標仍然是唯一標記的,並且不會導致具有不同值得重復時間序列。
4.修改最終得標簽格式
- job_name: cadvisor
...
metric_relabel_configs:
- source_labels: [image]
regex: '.*/(.*)'
replacement: '$1'
target_label: id
- source_labels: [service]
regex: 'ecs-.*:ecs-([a-z]+-*[a-z]*).*:[0-9]+'
replacement: '$1'
target_label: service
有兩個規則執行。第一個拿有含有image標簽名得度量,且匹配./(.),把它放到新標簽id得最后面。比如:
container_memery_rss{image="quiq/logspout:20170306"}就會變成 container_memery_rss{id="logspout:20170306"}。
第二條規則解析容器名稱,默認情況下,ECS-agent在AWS ECS實例上創建容器名稱,並提取其可識別得服務名稱,並將其放入服務標簽中。通過這種方式,您可以使用人類可讀的容器服務名稱進行操作。
