Prometheus(普羅米修斯)
從零搭建Prometheus監控報警系統(一)
Prometheus數據持久化存儲(二)
——— 先“安利”下理論知識
什么是Prometheus?
Prometheus是由SoundCloud開發的開源監控報警系統和時序列數據庫(TSDB)。
Prometheus使用Go語言開發,是Google BorgMon監控系統的開源版本。
Prometheus目前在開源社區相當活躍。
Prometheus和Heapster(Heapster是K8s的一個子項目,用於獲取集群的性能數據)相比功能更加完善、更全面。
Prometheus性能也足夠支撐上萬台規模的集群。
Prometheus的特點
- 多維度數據模型
- 靈活的查詢語言
- 不依賴分布式存儲,單個服務器節點是自主的
- 通過基於HTTP的pull方式采集時序數據
- 可以通過中間網關進行時序列數據推送
- 通過服務發現或者靜態配置來發現目標服務對象
- 支持多種多樣的圖表和界面展示,比如Grafana等
基本原理
Prometheus的基本原理是通過HTTP協議周期性的抓取被監控組件狀態,任意組件只要提供對應的HTTP接口就可以接入監控。不需要任何SDK或者其他的集成過程。這樣做非常適合做虛擬化環境監控系統,比如VM、Docker、Kubernetes等。輸出被監控組件信息的HTTP接口被叫做exporter 。目前互聯網公司常用的組件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系統信息(包括磁盤、內存、CPU、網絡等等)。
服務過程
- Prometheus Daemon負責定時去目標上抓取metrics(指標)數據,每個抓取目標需要暴露一個http服務的接口給它定時抓取。Prometheus支持通過配置文件、文本文件、Zookeeper、Consul、DNS SRV Lookup等方式指定抓取目標。Prometheus采用PULL的方式進行監控,即服務器可以直接通過目標PULL數據或者間接地通過中間網關來Push數據。
- Prometheus在本地存儲抓取的所有數據,並通過一定規則進行清理和整理數據,並把得到的結果存儲到新的時間序列中。
- Prometheus通過PromQL和其他API可視化地展示收集的數據。Prometheus支持很多方式的圖表可視化,例如Grafana、自帶的Promdash以及自身提供的模版引擎等等。Prometheus還提供HTTP API的查詢方式,自定義所需要的輸出。
- PushGateway支持Client主動推送metrics到PushGateway,而Prometheus只是定時去Gateway上抓取數據。
- Alertmanager是獨立於Prometheus的一個組件,可以支持Prometheus的查詢語句,提供十分靈活的報警方式。
組件
- Prometheus :主程序,Prometheus服務端,由於存儲及收集數據,提供相關api對外查詢用,主要是負責存儲、抓取、聚合、查詢方面。
- Alertmanager:告警管理器,主要是負責實現報警功能。
- Pushgateway :程序,主要是實現接收由Client push過來的指標數據,在指定的時間間隔,由主程序來抓取。
- *_exporter :類似傳統意義上的被監控端的agent,有區別的是,它不會主動推送監控數據到server端,而是等待server端定時來收集數據,即所謂的主動監控
———理論太枯燥,安裝部署開始
部署開始
環境描述
名稱 | 版本 |
---|---|
OS | Ubuntu 16.04 |
Docker | 18.09.1-ce |
服務器信息
IP | 角色 |
---|---|
192.168.1.20 | Server |
192.168.1.17 | Client |
登錄Server服務器
ssh user@192.168.1.20
創建工作目錄:mkdir ~/prometheus
cd ~/prometheus
mkdir config data
chmod -R 777 data
一、部署prometheus server
- 通過docker方式部署
目錄結構
prometheus
├── config
│ ├── prometheus.yml
│ └── rules
│ └── alert-rules.yml
├── data
├── docker-compose-prometheus.yml
└── README.md
Prometheus配置文件:
//cat config/prometheus.yml
global:
scrape_interval: 15s # 默認抓取間隔, 15秒向目標抓取一次數據。
external_labels:
monitor: 'codelab-monitor'
# 這里表示抓取對象的配置
scrape_configs:
#這個配置是表示在這個配置內的時間序例,每一條都會自動添加上這個{job_name:"prometheus"}的標簽
- job_name: 'prometheus'
scrape_interval: 5s # 重寫了全局抓取間隔時間,由15秒重寫成5秒
static_configs:
- targets: ['localhost:9090']
- job_name: 'linux-server' # 定義任務名
scrape_interval: 5s
static_configs:
- targets: ['192.168.1.20:9100'] # 客戶端地址
labels:
instance: '192.168.1.20' # 標簽,實例名,在后續報警通知獲取此值
# 配置告警規則位置
rule_files:
- "rules/*rules.yml"
rules 告警規則
//cat config/rules/alert-rules.yml
groups:
- name: alert-rule # 規則組名稱
rules:
- alert: NodeServerDown # 單個規則的名稱
expr: up{job="linux-server"} == 0 # 匹配規則, job與prometheus.yml配置文件內job_name對應
for: 15s # 持續時間
labels: # 標簽
severity: urgent # 自定義lables,級別
annotations: # 告警正文
summary: "服務器實例 {{ $labels.instance }} 丟失" # 告警總結概述
description: "服務器實例 {{ $labels.instance }} 不在線,已經停止" # 告警描述
- alert: NodeFilesystemUsage-high
expr: ( 1 - (node_filesystem_free_bytes{fstype=~"ext3|ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext3|ext4|xfs"}) ) * 100 > 80
for: 2m
labels:
severity: warning
annotations:
summary: "{{$labels.instance}}: 文件系統磁盤使用率過高"
description: "掛載點:{{$labels.mountpoint}} 磁盤使用率高於80%,(當前值為: {{ $value }})"
- alert: NodeMemoryUsage
expr: ( 100 - (((node_memory_MemFree_bytes+node_memory_Buffers_bytes+node_memory_Cached_bytes)/node_memory_MemTotal_bytes) * 100)) > 70
for: 2m
labels:
severity: warning
annotations:
summary: "{{$labels.instance}}: 檢測到節點內存使用率過高"
description: "{{$labels.instance}}: 節點內存使用率超過80%,當前使用率: {{ $value }})"
- alert: NodeCPUUsage
expr: ( 100 - (avg by (instance)(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)) > 80
for: 2m
labels:
severity: warning
annotations:
summary: "{{$labels.instance}}: 檢測到節點CPU使用率過高"
description: "{{$labels.instance}}: 節點CPU使用率超過80%,當前使用率: {{ $value }})"
# ---------------------------------------------------
- alert: "磁盤讀 I/O 超過 30MB/s"
expr: irate(node_disk_read_bytes_total{device="sda"}[1m]) > 30000000
for: 30s
labels:
severity: warning
annotations:
sumary: "服務器實例 {{ $labels.instance }} I/O 讀負載 告警通知"
description: "{{ $labels.instance }}I/O 每分鍾讀已超過 30MB/s,當前值: {{ $value }}"
- alert: "磁盤寫 I/O 超過 30MB/s"
expr: irate(node_disk_written_bytes_total{device="sda"}[1m]) > 30000000
for: 30s
annotations:
labels:
severity: warning
sumary: "服務器實例 {{ $labels.instance }} I/O 寫負載 告警通知"
description: "{{ $labels.instance }}I/O 每分鍾寫已超過 30MB/s,當前值: {{ $value }}"
- alert: "網卡流出速率大於 10MB/s"
expr: (irate(node_network_transmit_bytes_total{device!~"lo"}[1m]) / 1000) > 1000000
for: 30s
labels:
severity: warning
annotations:
sumary: "服務器實例 {{ $labels.instance }} 網卡流量負載 告警通知"
description: "{{ $labels.instance }}網卡 {{ $labels.device }} 流量已經超過 10MB/s, 當前值: {{ $value }}"
Docker-compose啟動文件
//cat docker-compose-prometheus.yml
version: "2.3"
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
hostname: prometheus
volumes:
- /prometheus/prometheus/config:/etc/prometheus
- /prometheus/prometheus/data:/prometheus
- /etc/localtime:/etc/localtime
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--log.level=info'
- '--web.listen-address=0.0.0.0:9090'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention=15d'
- '--query.max-concurrency=50'
- '--web.enable-lifecycle'
ports:
- "9090:9090"
logging:
driver: "json-file"
restart: always
README
# prometheus
* config: 配置文件
* data: 數據文件(用於留存數據)
* docker-compose-prometheus.yml: Docker啟動文件
## 啟動&停止
docker-compose -f docker-compose-prometheus.yml up -d
docker-compose -f docker-compose-prometheus.yml down
# 重新加載配置
curl -X POST http://192.168.1.20:9090/-/reload
# 訪問
http://192.168.1.20:9090/
可以看到Prometheus頁面。

http://192.168.1.20:9090/metrics
默認配置的9090端口,默認prometheus會抓取自己的/metrics接口,在頁面上Graph搜索口輸入“up”可以看到監控數。

二、部署客戶端程序,提供metrics接口
1、通過node exporter提供metrics
Client:192.168.1.17
目錄結構
node_exporter
├── LICENSE
├── node_exporter
├── NOTICE
└── README.md
//下載
curl -OL https://github.com/prometheus/node_exporter/releases/download/v0.17.0/node_exporter-0.17.0.linux-amd64.tar.gz
tar -xzf node_exporter-0.17.0.linux-amd64.tar.gz
mv node_exporter-0.17.0.linux-amd64 node_exporter
//啟動方式1
screen -S node_exporter
./node_exporter
// 指定端口啟動
./node_exporter # 直接啟動默認端口9100
./node_exporter --web.listen-address=":9111" #指定端口啟動
//啟動方式2
創建用戶
groupadd prometheus
useradd -g prometheus -m -d /var/lib/prometheus -s /sbin/nologin prometheus
chown prometheus.prometheus -R /usr/local/prometheus
創建Systemd服務
//mv node_exporter /usr/local/bin/node_exporter
//cat /etc/systemd/system/node_exporter.service
[Unit]
Description=node_exporter
Documentation=https://prometheus.io/
After=network.target
[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/bin/node_exporter
Restart=on-failure
[Install]
WantedBy=multi-user.target
//啟動
systemctl start node_exporter
systemctl enable node_exporter
prometheus.yml配置文件增加如下:
- targets: ['192.168.1.17:9111']
labels:
instance: '192.168.1.17'
然后把接口再次配置到prometheus.yml, 重新載入配置curl -X POST http://192.168.1.20:9090/-/reload
然后訪問http://192.168.1.20:9090/
Status — Targets 可以看到客戶端相關信息
2、通過push gateway提供metrics
- pushgateway是為了允許臨時作業和批處理作業向普羅米修斯公開他們的指標。
由於這類作業的存在時間可能不夠長, 無法抓取到, 因此它們可以將指標推送到推網關中。 - Prometheus采集數據是用的pull也就是拉模型,這從我們剛才設置的5秒參數就能看出來。但是有些數據並不適合采用這樣的方式,對這樣的數據可以使用Push Gateway服務。
它就相當於一個緩存,當數據采集完成之后,就上傳到這里,由Prometheus稍后再pull過來。
//cat docker-compose-pushgateway.yml
version: "2.3"
services:
pushgateway:
image: prom/pushgateway:latest
container_name: pushgateway
hostname: pushgateway
volumes:
- /etc/localtime:/etc/localtime
ports:
- "9091:9091"
restart: always
訪問http://192.168.1.17:9091/
可以看到pushgateway已經運行起來了。
prometheus.yml配置文件增加如下:
Pushgateway 方式配置
- job_name: 'PushGateway'
scrape_interval: 5s
honor_labels: true #加上此配置exporter節點上傳數據中的一些標簽將不會被pushgateway節點的相同標簽覆蓋
static_configs:
- targets: ['192.168.1.17:9091']
labels:
instance: 'PushGateway'
然后把以上接口再次配置到prometheus.yml, 重新載入配置curl -X POST http://192.168.1.20:9090/-/reload
示例一:
// 測試,模擬客戶端推送metric到pushgateway
echo "some_metric 3.14" | curl --data-binary @- http://192.168.1.17:9091/metrics/job/some_job
// 刷新pushgateway頁面,點擊 Metric 頁面,顯示數據
示例二:
// 添加更復雜的數據指標
cat <<EOF | curl --data-binary @- http://192.168.1.17:9091/metrics/job/some1_job/instance/some1_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
示例三:
將node_exporter的metrics傳到pushgateway
curl 192.168.1.17:9111/metrics | curl --data-binary @- http://192.168.1.17:9091/metrics/job/nodestate/instance/192.168.1.20-p/hostname/ip-192.168.1.20
// 刪除某個組下的所有數據:
curl -X DELETE http://192.168.1.17:9091/metrics/job/some_job
// 刪除某個組下的某實例的所有數據:
curl -X DELETE http://192.168.1.17:9091/metrics/job/some_job/instance/some_instance
登錄 Prometheus 頁面查看
自定義metrics並上傳到pushgateway
舉例:
使用curl獲取到百度的http相關指標,如dns解析時間,請求耗時,返回code等。
如下腳本每隔15秒獲取一次metrics並push到pushgateway
#/bin/bash
URL="https://www.baidu.com"
while true;
do
echo '# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds' > metric_temp
echo '# TYPE probe_dns_lookup_time_seconds gauge' >> metric_temp
echo `curl -o /dev/null -s -w "probe_dns_lookup_time_seconds %{time_namelookup}\n" ${URL}` >> metric_temp
echo '# HELP probe_http_status_code Response HTTP status code' >> metric_temp
echo '# TYPE probe_http_status_code gauge' >> metric_temp
echo "probe_http_status_code `curl -I -m 10 -o /dev/null -s -w %{http_code} ${URL}`" >> metric_temp
echo '# HELP probe_duration_seconds Returns how long the probe took to complete in seconds' >> metric_temp
echo '# TYPE probe_duration_seconds gauge' >> metric_temp
echo `curl -o /dev/null -s -w "probe_duration_seconds %{time_total}\n" ${URL}` >> metric_temp
# Push metric to prometheus
cat metric_temp| curl -s --data-binary @- http://192.168.1.17:9091/metrics/job/baidu/instance/baidustate;
date "+%Y-%m-%d %H:%M:%S"
sleep 15;
done
在PushGateway頁面看到對應的metric
然后在Prometheus里查對應的metric值
三、安裝Grafana展示
- Grafana是用於可視化大型測量數據的開源程序,它提供了強大和優雅的方式去創建、共享、瀏覽數據。
Dashboard中顯示了你不同metric數據源中的數據。 - Grafana最常用於因特網基礎設施和應用分析,但在其他領域也有用到,比如:工業傳感器、家庭自動化、過程控制等等。
- Grafana支持熱插拔控制面板和可擴展的數據源,目前已經支持Graphite、InfluxDB、OpenTSDB、Elasticsearch、Prometheus等。
目錄結構
grafana/
├── config
│ ├── grafana.ini
│ └── provisioning
├── dashboards
├── data
├── docker-compose-grafana.yml
├── logs
└── README.md
還是給予docker安裝
mkdir config dashboards data logs
//cat docker-compose-grafana.yml
version: "2.3"
services:
grafana:
image: grafana/grafana:latest
container_name: grafana
hostname: grafana
restart: always
volumes:
- /prometheus/grafana/config:/etc/grafana
- /prometheus/grafana/logs:/var/log/grafana
- /prometheus/grafana/data:/var/lib/grafana
- /prometheus/grafana/dashboards:/etc/grafana/provisioning/dashboards
- /etc/localtime:/etc/localtime
ports:
- "3000:3000"
user: "104"
//cat README
# grafana
* config: 配置文件
* dashboards: 數據文件
* data: 數據文件
* logs: 日志文件
* docker-compose-grafana.yml: Docker啟動文件
#啟動&停止
docker-compose -f docker-compose-grafana.yml up -d
docker-compose -f docker-compose-grafana.yml down
訪問http://192.168.1.20:3000/
默認用戶密碼:admin/admin
Add data source 添加數據源
把Prometheus的地址填上
Save& Test
導入prometheus的模板,增加一個個人認為比較全的模版
到Grafana官網獲取模版
復制模版ID,返回grafana頁面導入模版Import dashboard
一款高大上的圖表就展示出來了,個人根據自己的需要進行修改配置。
四、Alertmanager監控告警
- Pormetheus的警告由獨立的兩部分組成。
- Prometheus服務中的警告規則發送警告到Alertmanager。
然后這個Alertmanager管理這些警告。包括silencing, inhibition, aggregation,以及通過一些方法發送通知,例如:email,PagerDuty,HipChat,釘釘和企業微信等。 - 建立警告和通知的主要步驟:
創建和配置Alertmanager
啟動Prometheus服務時,通過-alertmanager.url標志配置Alermanager地址,以便Prometheus服務能和Alertmanager建立連接
目錄結構
alertmanager/
├── config
│ ├── alertmanager.yml
│ └── template
│ └── wechat.tmpl
├── data
├── docker-compose-alertmanager.yml
└── README.md
通過企業微信自建應用報警通知
mkdir -p config/template data
docker-compose-alertmanager.yml配置文件
// cat docker-compose-alertmanager.yml
version: "2.3"
services:
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
hostname: alertmanager
volumes:
- /prometheus/alertmanager/config:/etc/alertmanager
- /prometheus/alertmanager/data:/alertmanager
- /etc/localtime:/etc/localtime
ports:
- "9093:9093"
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
- '--web.external-url=http://192.168.1.20:9093'
restart: always
alertmanager.yml配置文件
// cat config/alertmanager.yml
global:
resolve_timeout: 5m #處理超時時間,默認為5min
# 定義模板信息,可以自定義html模板,發郵件的時候用自己定義的模板內容發
templates:
- '/etc/alertmanager/template/wechat.tmpl'
# 定義路由樹信息,這個路由可以接收到所有的告警,還可以繼續配置路由,比如project: APP(prometheus 告警規則中自定義的lable)發給誰
route:
group_by: ['alertname'] # 報警分組依據
group_wait: 10s # 最初即第一次等待多久時間發送一組警報的通知
group_interval: 10s # 在發送新警報前的等待時間
repeat_interval: 10m # 發送頻率。發送重復警報的周期 對於email配置中,此項不可以設置過低,否則將會由於郵件發送太多頻繁,被smtp服務器拒絕
receiver: 'wechat' # 發送警報的接收者的名稱,以下receivers name的名稱
# 定義警報接收者信息
receivers:
- name: 'wechat' # 路由中對應的receiver名稱
wechat_configs: # 微信配置
- send_resolved: true
to_user: '617cxxxxxxxxxxxxx' #接受消息用戶ID
# to_party: '2' # 接受消息部門ID,在企業微信后台-通訊錄查看
# to_tag: '3' 接受消息標簽ID,在企業微信后台-通訊錄查看
agent_id: 1000014 # 企業微信agentid
corp_id: 'wwxxxxxxxxx56x' # 企業微信corpid
api_url: 'https://qyapi.weixin.qq.com/cgi-bin/' # 企業微信apiurl
api_secret: 'iIql3qxxxxxxxxxxxxxxxx4' # 企業微信,自建應用apisecret
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
告警&恢復模版
//cat config/template/wechat.tmpl
{{ define "wechat.default.message" }}
{{- if gt (len .Alerts.Firing) 0 -}}{{ range .Alerts }}
========【告警通知】=========
告警程序: prometheus_alert
告警級別: {{ .Labels.severity }}
告警類型: {{ .Labels.alertname }}
告警主機: {{ .Labels.instance }}
告警主題: {{ .Annotations.summary }}
告警詳情: {{ .Annotations.description }}
觸發時間: {{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
{{ end }}{{ end -}}
{{- if gt (len .Alerts.Resolved) 0 -}}{{ range .Alerts }}
========【恢復通知】=========
恢復類型: {{ .Labels.alertname }}
恢復主機: {{ .Labels.instance }}
恢復主題: {{ .Annotations.summary }}
觸發時間: {{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
恢復時間: {{ (.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
{{ end }}{{ end -}}
{{- end }}
- Prometheus 郵件告警自定義模板的默認使用的是utc時間。其中
Add 28800e9
就是表示加8個小時。
Prometheus.yml配置文件增加如下:
# 配置alertmanager告警發送消息配置
alerting:
alertmanagers:
- static_configs:
- targets: ['192.168.1.20:9093']
記得重新加載:curl -X POST http://192.168.1.20:9090/-/reload
五、配置Grafana,實現釘釘告警通知
// 編輯config/grafana.ini
修改root_url為root_url = http://192.168.1.20:3000/
否則如果通過grafana配置報警,報警通知的地址是localhost
記得重啟grafana服務
釘釘群聊創建機器人,獲取webbook
步驟一:【電腦釘釘 】-【群聊】-【群設置】-【智能群助手】-【添加更多】-【添加機器人】-【自定義】-【添加】,編輯機器人名稱和選擇添加的群組。完成必要的安全設置(至少選擇一種),勾選 我已閱讀並同意《自定義機器人服務及免責條款》,點擊“完成”即可
//登錄Grafana頁面,添加告警
模版配置相應的規則
告警信息
根據配置的規則觸發報警
Grafana 集成到自己的web項目
- 在Web項目中可以使用iframe直接嵌套進去(需要設置grafana設置成匿名登錄)
// 修改grafana.ini文件
[auth.anonymous]
# enable anonymous access
enabled = true
# specify organization name that should be used for unauthenticated users
org_name = new_orgs ; 組織名,可以自定義,稍候需要在grafana同步修改
# specify role for unauthenticated users
org_role = Viewer ; 組織權限,有Viewer,Editor和Admin
// 重啟grafana
docker-compose -f docker-compose-grafana.yml down
docker-compose -f docker-compose-grafana.yml up -d
// 登錄grafana修改組織名
// 分享頁面
// 可以使用瀏覽器打開新窗口查看此鏈接,或嵌套在自己的web項目代碼中
最后附上,完整的Prometheus.yml配置文件
global:
scrape_interval: 15s # 默認抓取間隔, 15秒向目標抓取一次數據。
external_labels:
monitor: 'codelab-monitor'
# 這里表示抓取對象的配置
scrape_configs:
#這個配置是表示在這個配置內的時間序例,每一條都會自動添加上這個{job_name:"prometheus"}的標簽
- job_name: 'prometheus'
scrape_interval: 5s # 重寫了全局抓取間隔時間,由15秒重寫成5秒
static_configs:
- targets: ['localhost:9090']
- job_name: 'linux-server' # 定義任務名
scrape_interval: 5s
static_configs:
- targets: ['192.168.1.20:9100'] # 客戶端地址
labels:
instance: '192.168.1.20' # 標簽,實例名,在后續報警通知獲取此值
- targets: ['192.168.1.17:9111']
labels:
instance: '192.168.1.17'
# Pushgateway 方式配置
# - job_name: 'pushgateway'
# scrape_interval: 5s
# static_configs:
# - targets: ['192.168.1.17:9091']
# labels:
# instance: '192.168.1.17'
# 配置告警規則位置
rule_files:
- "rules/*rules.yml"
# 配置alertmanager告警發送消息配置
alerting:
alertmanagers:
- static_configs:
- targets: ['192.168.1.20:9093']
參考資料-從零搭建Prometheus監控報警系統(推薦)
參考資料-Prometheus+Grafana監控簡介(推薦)
參考資料-prometheus-book
參考資料-prometheus配置企業微信報警
參考資料-prometheus報警規則模版
參考資料-監控指標-報警規則
官網文檔