一、安裝部署
Prometheus基於Golang編寫,編譯后的軟件包,不依賴於任何的第三方依賴。用戶只需要下載對應平台的二進制包,解壓並且添加基本的配置即可正常啟動Prometheus Server。
二進制部署
1、下載安裝包
為您的平台下載最新版本的Prometheus,然后解壓縮並運行它:
https://prometheus.io/download/
https://prometheus.io/docs/prometheus/latest/getting_started/
tar xvfz prometheus-*.tar.gz cd prometheus-* mv prometheus-* /usr/local/prometheus
2、注冊為服務
Centos7上,注冊為服務:
cat /usr/lib/systemd/system/prometheus.service
[Unit] Description=https://prometheus.io [Service] Restart=on-failure ExecStart=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prometheus.yml [Install] WantedBy=multi-user.target
Centos6上,注冊為服務:
#!/bin/bash # # Comments to support chkconfig # chkconfig: 2345 98 02 # description: prometheus service script # # Source function library. . /etc/init.d/functions ### Default variables prog_name="prometheus" config_file="/usr/local/${prog_name}/${prog_name}.yml" prog_path="/usr/local/${prog_name}/${prog_name}" data_path="/usr/local/${prog_name}/data" pidfile="/var/run/${prog_name}.pid" prog_logs="/var/log/${prog_name}.log" #啟動項,監聽本地9090端口,支持配置熱加載 options="--web.listen-address=0.0.0.0:9090 --config.file=${config_file} --storage.tsdb.path=${data_path}" DESC="Prometheus Server" # Check if requirements are met [ -x "${prog_path}" ] || exit 1 RETVAL=0 start(){ action $"Starting $DESC..." su -s /bin/sh -c "nohup $prog_path $options >> $prog_logs 2>&1 &" 2> /dev/null RETVAL=$? PID=$(pidof ${prog_path}) [ ! -z "${PID}" ] && echo ${PID} > ${pidfile} echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog_name return $RETVAL } stop(){ echo -n $"Shutting down $prog_name: " killproc -p ${pidfile} RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog_name return $RETVAL } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart) restart ;; status) status $prog_path RETVAL=$? ;; *) echo $"Usage: $0 {start|stop|restart|status}" RETVAL=1 esac exit $RETVAL
3、啟動promethues
Centos7:
systemctl start prometheus
Centos6:
service prometheus start
Docker方式部署
https://prometheus.io/docs/prometheus/latest/installation/
prometheus.yml
通過運行以下命令將您從主機綁定:
docker run -p 9090:9090 -v /tmp/prometheus.yml:/etc/prometheus/prometheus.yml \ prom/prometheus
或者為配置使用額外的卷:
docker run -p 9090:9090 -v /prometheus-data \ prom/prometheus --config.file=/prometheus-data/prometheus.yml
二、界面訪問
http://localhost:9090訪問自己的狀態頁面
可以通過訪問localhost:9090驗證Prometheus自身的指標:localhost:9090/metrics
三、自我監控
Prometheus從目標機上通過http方式拉取采樣點數據, 它也可以拉取自身服務數據並監控自身的健康狀況
當然Prometheus服務拉取自身服務采樣數據,並沒有多大的用處,但是它是一個好的DEMO。保存下面的Prometheus配置,並命名為:prometheus.yml:
global: scrape_interval: 15s # 默認情況下,每15s拉取一次目標采樣點數據。 # 我們可以附加一些指定標簽到采樣點度量標簽列表中, 用於和第三方系統進行通信, 包括:federation, remote storage, Alertmanager external_labels: monitor: 'codelab-monitor' # 下面就是拉取自身服務采樣點數據配置 scrape_configs: # job名稱會增加到拉取到的所有采樣點上,同時還有一個instance目標服務的host:port標簽也會增加到采樣點上 - job_name: 'prometheus' # 覆蓋global的采樣點,拉取時間間隔5s scrape_interval: 5s static_configs: - targets: ['localhost:9090']
重啟promethues服務。
通過http://10.11.100.99:9090/targets,就可以查看到了:
四、配置文件
配置文件的格式是YAML,使用--config.file指定配置文件的位置。本節列出重要的配置項。
1、全局配置文件
有關配置選項的完整,請參閱:https://prometheus.io/docs/prometheus/latest/configuration/configuration/
Prometheus以scrape_interval規則周期性從監控目標上收集數據,然后將數據存儲到本地存儲上。scrape_interval可以設定全局也可以設定單個metrics。
Prometheus以evaluation_interval規則周期性對告警規則做計算,然后更新告警狀態。evaluation_interval只有設定在全局。
global:全局配置
alerting:告警配置
rule_files:告警規則
scrape_configs:配置數據源,稱為target,每個target用job_name命名。又分為靜態配置和服務發現
global: # 默認抓取周期,設置每15s采集數據一次,默認1分鍾 [ scrape_interval: <duration> | default = 1m ] # 默認抓取超時 [ scrape_timeout: <duration> | default = 10s ] # 估算規則的默認周期 # 每15秒計算一次規則。默認1分鍾 [ evaluation_interval: <duration> | default = 1m ] # 和外部系統(例如AlertManager)通信時為時間序列或者警情(Alert)強制添加的標簽列表 external_labels: [ <labelname>: <labelvalue> ... ] # 規則文件列表 rule_files: [ - <filepath_glob> ... ] # 抓取配置列表 scrape_configs: [ - <scrape_config> ... ] # Alertmanager相關配置 alerting: alert_relabel_configs: [ - <relabel_config> ... ] alertmanagers: [ - <alertmanager_config> ... ] # 遠程讀寫特性相關的配置 remote_write: [ - <remote_write> ... ] remote_read: [ - <remote_read> ... ]
其中,比較重要的配置為scrape_configs.
2、scrape_configs
根據配置的任務(job)以http/s周期性的收刮(scrape/pull)
指定目標(target)上的指標(metric)。目標(target)
可以以靜態方式或者自動發現方式指定。Prometheus將收刮(scrape)的指標(metric)保存在本地或者遠程存儲上。
使用scrape_configs定義采集目標
配置一系列的目標,以及如何抓取它們的參數。一般情況下,每個scrape_config對應單個Job。
目標可以在scrape_config中靜態的配置,也可以使用某種服務發現機制動態發現。
# 任務名稱,自動作為抓取到的指標的一個標簽 job_name: <job_name> # 抓取周期 [ scrape_interval: <duration> | default = <global_config.scrape_interval> ] # 每次抓取的超時 [ scrape_timeout: <duration> | default = <global_config.scrape_timeout> ] # 從目標抓取指標的URL路徑 [ metrics_path: <path> | default = /metrics ] # 當添加標簽發現指標已經有同名標簽時,是否保留原有標簽不覆蓋 [ honor_labels: <boolean> | default = false ] # 抓取協議 [ scheme: <scheme> | default = http ] # HTTP請求參數 params: [ <string>: [<string>, ...] ] # 身份驗證信息 basic_auth: [ username: <string> ] [ password: <secret> ] [ password_file: <string> ] # Authorization請求頭取值 [ bearer_token: <secret> ] # 從文件讀取Authorization請求頭 [ bearer_token_file: /path/to/bearer/token/file ] # TLS配置 tls_config: [ <tls_config> ] # 代理配置 [ proxy_url: <string> ] # DNS服務發現配置 dns_sd_configs: [ - <dns_sd_config> ... ] # 文件服務發現配置 file_sd_configs: [ - <file_sd_config> ... ] # K8S服務發現配置 kubernetes_sd_configs: [ - <kubernetes_sd_config> ... ] # 此Job的靜態配置的目標列表,用的最多的配置!!! static_configs: [ - <static_config> ... ] # 目標重打標簽配置 relabel_configs: [ - <relabel_config> ... ] # 指標重打標簽配置 metric_relabel_configs: [ - <relabel_config> ... ] # 每次抓取允許的最大樣本數量,如果在指標重打標簽后,樣本數量仍然超過限制,則整個抓取認為失敗 # 0表示不限制 [ sample_limit: <int> | default = 0
3、relabel_configs
relabel_configs :允許在采集之前對任何目標及其標簽進行修改
重新標簽的意義?
- 重命名標簽名
- 刪除標簽
- 過濾目標
action:重新標簽動作
- replace:默認,通過regex匹配source_label的值,使用replacement來引用表達式匹配的分組
- keep:刪除regex與連接不匹配的目標 source_labels
- drop:刪除regex與連接匹配的目標 source_labels
- labeldrop:刪除regex匹配的標簽
- labelkeep:刪除regex不匹配的標簽
- hashmod:設置target_label為modulus連接的哈希值source_labels
- labelmap:匹配regex所有標簽名稱。然后復制匹配標簽的值進行分組,replacement分組引用(${1},${2},…)替代
4、基於文件的服務發現
支持服務發現的來源:
- azure_sd_configs
- consul_sd_configs
- dns_sd_configs
- ec2_sd_configs
- openstack_sd_configs
- file_sd_configs
- gce_sd_configs
- kubernetes_sd_configs
- marathon_sd_configs
- nerve_sd_configs
- serverset_sd_configs
- triton_sd_configs
Prometheus也提供了服務發現功能,可以從consul,dns,kubernetes,file等等多種來源發現新的目標。
其中最簡單的是從文件發現服務。
https://github.com/prometheus/prometheus/tree/master/discovery
服務發現支持: endpoints,ingress,kubernetes,node,pod,service
五、監控案例
監控Linux服務器
node_exporter:用於*NIX系統監控,使用Go語言編寫的收集器。
使用文檔:https://prometheus.io/docs/guides/node-exporter/
GitHub:https://github.com/prometheus/node_exporter
exporter列表:https://prometheus.io/docs/instrumenting/exporters/
收集到 node_exporter 的數據后,我們可以使用 PromQL 進行一些業務查詢和監控,下面是一些比較常見的查詢。
注意:以下查詢均以單個節點作為例子,如果大家想查看所有節點,將 instance="xxx" 去掉即可。
CPU使用率: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100) 內存使用率: 100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100 磁盤使用率: 100 - (node_filesystem_free_bytes{mountpoint="/",fstype=~"ext4|xfs"} / node_filesystem_size_bytes{mountpoint="/",fstype=~"ext4|xfs"} * 100)
監控Mysql數據庫
mysql_exporter:用於收集MySQL性能信息。
https://github.com/prometheus/mysqld_exporter
https://grafana.com/dashboards/7362
登錄mysql為exporter創建賬號: mysql> CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'XXXXXXXX' WITH MAX_USER_CONNECTIONS 3; mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost'; # cat .my.cnf [client] user=exporter password=exporter123 # ./mysqld_exporter --config.my-cnf=.my.cnf - job_name: 'mysql' static_configs: - targets: ['localhost:9104']
六、可視化方案
Grafana是一個開源的最近非常流行的度量分析和可視化工具。
https://grafana.com/grafana/download
Grafana支持查詢普羅米修斯。自Grafana 2.5.0(2015-10-28)以來,包含了Prometheus的Grafana數據源。
Grafana.com維護着一組共享儀表板 ,可以下載並與Grafana的獨立實例一起使用。
比如
https://grafana.com/dashboards/9276
七、監控告警
告警無疑是監控中非常重要的環節,雖然監控數據可視化了,也非常容易觀察到運行狀態。但我們很難做到時刻盯着監控,所以程序來幫巡檢並自動告警,這個程序是幕后英雄,保障業務穩定性就靠它了。
前面講到過Prometheus的報警功能主要是利用Alertmanager這個組件。當Alertmanager接收到 Prometheus 端發送過來的 Alerts 時,Alertmanager 會對 Alerts 進行去重復,分組,按標簽內容發送不同報警組,包括:郵件,微信,webhook。
使用prometheus進行告警分為兩部分:Prometheus Server中的告警規則會向Alertmanager發送。然后,Alertmanager管理這些告警,包括進行重復數據刪除,分組和路由,以及告警的靜默和抑制。
1、部署Alertmanager
在Prometheus平台中,警報由獨立的組件Alertmanager處理。通常情況下,我們首先告訴Prometheus Alertmanager所在的位置,然后在Prometheus配置中創建警報規則,最后配置Alertmanager來處理警報並發送給接收者(郵件,webhook、slack等)。
地址1:https://prometheus.io/download/
地址2:https://github.com/prometheus/alertmanager/releases
注冊為服務
#!/bin/bash # # Comments to support chkconfig # chkconfig: 2345 98 02 # description: prometheus service script # # Source function library. . /etc/init.d/functions ### Default variables base_name="alertmanager" prog_name="alertmanager" config_file="/usr/local/${base_name}/${prog_name}.yml" prog_path="/usr/local/${base_name}/${prog_name}" data_path="/usr/local/${base_name}/data" pidfile="/var/run/${porg_name}.pid" prog_logs="/var/log/${prog_name}.log" #啟動項,監聽本地9090端口,支持配置熱加載 options="--config.file=${config_file}" DESC="altermanager" # Check if requirements are met [ -x "${prog_path}" ] || exit 1 RETVAL=0 start(){ action $"Starting $DESC..." su -s /bin/sh -c "nohup $prog_path $options>> $prog_logs 2>&1 &" 2> /dev/null RETVAL=$? PID=$(pidof ${prog_path}) [ ! -z "${PID}" ] && echo ${PID} > ${pidfile} echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog_name return $RETVAL } stop(){ echo -n $"Shutting down $prog_name: " killproc -p ${pidfile} RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog_name return $RETVAL } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart) restart ;; status) status $prog_path RETVAL=$? ;; *) echo $"Usage: $0 {start|stop|restart|status}" RETVAL=1 esac exit $RETVAL
啟動Alertmanager
service alertmanager start
2、配置alertmanager
一個完整的alertmanager.yml如下:
# 全局配置項 global: resolve_timeout: 5m #處理超時時間,默認為5min smtp_smarthost: 'smtp.sina.com:25' # 郵箱smtp服務器代理 smtp_from: '******@sina.com' # 發送郵箱名稱 smtp_auth_username: '******@sina.com' # 郵箱名稱 smtp_auth_password: '******' # 郵箱密碼或授權碼 wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/' # 企業微信地址 # 定義模板信心 templates: - 'template/*.tmpl' # 定義路由樹信息 route: group_by: ['alertname'] # 報警分組依據 group_wait: 10s # 最初即第一次等待多久時間發送一組警報的通知 group_interval: 10s # 在發送新警報前的等待時間 repeat_interval: 1m # 發送重復警報的周期 對於email配置中,此項不可以設置過低,否則將會由於郵件發送太多頻繁,被smtp服務器拒絕 receiver: 'email' # 發送警報的接收者的名稱,以下receivers name的名稱 # 定義警報接收者信息 receivers: - name: 'email' # 警報 email_configs: # 郵箱配置 - to: '******@163.com' # 接收警報的email配置 html: '{{ template "test.html" . }}' # 設定郵箱的內容模板 headers: { Subject: "[WARN] 報警郵件"} # 接收郵件的標題 webhook_configs: # webhook配置 - url: 'http://127.0.0.1:5001' send_resolved: true wechat_configs: # 企業微信報警配置 - send_resolved: true to_party: '1' # 接收組的id agent_id: '1000002' # (企業微信-->自定應用-->AgentId) corp_id: '******' # 企業信息(我的企業-->CorpId[在底部]) api_secret: '******' # 企業微信(企業微信-->自定應用-->Secret) message: '{{ template "test_wechat.html" . }}' # 發送消息模板的設定 # 一個inhibition規則是在與另一組匹配器匹配的警報存在的條件下,使匹配一組匹配器的警報失效的規則。兩個警報必須具有一組相同的標簽。 inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['alertname', 'dev', 'instance']
設置告警和通知的主要步驟如下:
- 部署Alertmanager
- 配置Prometheus與Alertmanager通信
- 在Prometheus中創建告警規則
a、配置Prometheus與Alertmanager通信
# vi prometheus.yml alerting: alertmanagers: - static_configs: - targets: - 127.0.0.1:9093
b、在Prometheus中創建告警規則
# vi prometheus.yml rule_files: - "rules/*.yml" # vi rules/node.yml groups: - name: example # 報警規則組名稱 rules: # 任何實例5分鍾內無法訪問發出告警 - alert: InstanceDown expr: up == 0 for: 5m #持續時間 , 表示持續一分鍾獲取不到信息,則觸發報警 labels: severity: page # 自定義標簽 annotations: summary: "Instance {{ $labels.instance }} down" # 自定義摘要 description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes." # 自定義具體描述
c、觸發告警
d、告警狀態
一旦這些警報存儲在Alertmanager,它們可能處於以下任何狀態:
- Inactive:這里什么都沒有發生。
- Pending:已觸發閾值,但未滿足告警持續時間(即rule中的for字段)
- Firing:已觸發閾值且滿足告警持續時間。警報發送到Notification Pipeline,經過處理,發送給接受者。
這樣目的是多次判斷失敗才發告警,減少郵件。
3、告警分配
route
屬性用來設置報警的分發策略,它是一個樹狀結構,按照深度優先從左向右的順序進行匹配。
route: receiver: 'default-receiver' group_wait: 30s group_interval: 5m repeat_interval: 4h group_by: [cluster, alertname] # 所有不匹配以下子路由的告警都將保留在根節點,並發送到“default-receiver” routes: # 所有service=mysql或者service=cassandra的告警分配到數據庫接收端 - receiver: 'database-pager' group_wait: 10s match_re: service: mysql|cassandra # 所有帶有team=frontend標簽的告警都與此子路由匹配 # 它們是按產品和環境分組的,而不是集群 - receiver: 'frontend-pager' group_by: [product, environment] match: team: frontend
group_by
:報警分組依據
group_wait
:為一個組發送通知的初始等待時間,默認30s
group_interval
:在發送新告警前的等待時間。通常5m或以上
repeat_interval
:發送重復告警的周期。如果已經發送了通知,再次發送之前需要等待多長時間。通常3小時或以上
主要處理流程:
- 接收到Alert,根據labels判斷屬於哪些Route(可存在多個Route,一個Route有多個Group,一個Group有多個Alert)。
- 將Alert分配到Group中,沒有則新建Group。
- 新的Group等待group_wait指定的時間(等待時可能收到同一Group的Alert),根據resolve_timeout判斷Alert是否解決,然后發送通知。
- 已有的Group等待group_interval指定的時間,判斷Alert是否解決,當上次發送通知到現在的間隔大於repeat_interval或者Group有更新時會發送通知。
4、告警收斂(分組、抑制、靜默)
告警面臨最大問題,是警報太多,相當於狼來了的形式。收件人很容易麻木,不再繼續理會。關鍵的告警常常被淹沒。在一問題中,alertmanger在一定程度上得到很好解決。
Prometheus成功的把一條告警發給了Altermanager,而Altermanager並不是簡簡單單的直接發送出去,這樣就會導致告警信息過多,重要告警被淹沒。所以需要對告警做合理的收斂。
告警收斂手段:
分組(group):將類似性質的警報分類為單個通知
抑制(Inhibition):當警報發出后,停止重復發送由此警報引發的其他警報
靜默(Silences):是一種簡單的特定時間靜音提醒的機制
5、Prometheus一條告警怎么觸發的?
報警處理流程如下:
- Prometheus Server監控目標主機上暴露的http接口(這里假設接口A),通過上述Promethes配置的'scrape_interval'定義的時間間隔,定期采集目標主機上監控數據。
- 當接口A不可用的時候,Server端會持續的嘗試從接口中取數據,直到"scrape_timeout"時間后停止嘗試。這時候把接口的狀態變為“DOWN”。
- Prometheus同時根據配置的"evaluation_interval"的時間間隔,定期(默認1min)的對Alert Rule進行評估;當到達評估周期的時候,發現接口A為DOWN,即UP=0為真,激活Alert,進入“PENDING”狀態,並記錄當前active的時間;
- 當下一個alert rule的評估周期到來的時候,發現UP=0繼續為真,然后判斷警報Active的時間是否已經超出rule里的‘for’ 持續時間,如果未超出,則進入下一個評估周期;如果時間超出,則alert的狀態變為“FIRING”;同時調用Alertmanager接口,發送相關報警數據。
- AlertManager收到報警數據后,會將警報信息進行分組,然后根據alertmanager配置的“group_wait”時間先進行等待。等wait時間過后再發送報警信息。
- 屬於同一個Alert Group的警報,在等待的過程中可能進入新的alert,如果之前的報警已經成功發出,那么間隔“group_interval”的時間間隔后再重新發送報警信息。比如配置的是郵件報警,那么同屬一個group的報警信息會匯總在一個郵件里進行發送。
- 如果Alert Group里的警報一直沒發生變化並且已經成功發送,等待‘repeat_interval’時間間隔之后再重復發送相同的報警郵件;如果之前的警報沒有成功發送,則相當於觸發第6條條件,則需要等待group_interval時間間隔后重復發送。
- 同時最后至於警報信息具體發給誰,滿足什么樣的條件下指定警報接收人,設置不同報警發送頻率,這里有alertmanager的route路由規則進行配置。
6、編寫告警規則案例
# cat rules/general.yml groups: - name: general.rules rules: - alert: InstanceDown expr: up == 0 for: 2m labels: severity: error annotations: summary: "Instance {{ $labels.instance }} 停止工作" description: "{{ $labels.instance }}: job {{ $labels.job }} 已經停止5分鍾以上." # cat rules/node.yml groups: - name: node.rules rules: - alert: NodeFilesystemUsage expr: 100 - (node_filesystem_free_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"} * 100) > 80 for: 2m labels: severity: warning annotations: summary: "{{$labels.instance}}: {{$labels.mountpoint }} 分區使用過高" description: "{{$labels.instance}}: {{$labels.mountpoint }} 分區使用大於 80% (當前值: {{ $value }})" - alert: NodeMemoryUsage expr: 100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100 > 80 for: 2m labels: severity: warning annotations: summary: "{{$labels.instance}}: 內存使用過高" description: "{{$labels.instance}}: 內存使用大於 80% (當前值: {{ $value }})" - alert: NodeCPUUsage expr: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100) > 80 for: 2m labels: severity: warning annotations: summary: "{{$labels.instance}}: CPU使用過高" description: "{{$labels.instance}}: CPU使用大於 80% (當前值: {{ $value }})" # cat rules/reload.yml groups: - name: prometheus.rules rules: - alert: AlertmanagerReloadFailed expr: alertmanager_config_last_reload_successful == 0 for: 10m labels: severity: warning annotations: summary: "{{$labels.instance}}: Alertmanager配置重新加載失敗" description: "{{$labels.instance}}: Alertmanager配置重新加載失敗" - alert: PrometheusReloadFailed expr: prometheus_config_last_reload_successful == 0 for: 10m labels: severity: warning annotations: summary: "{{$labels.instance}}: Prometheus配置重新加載失敗" description: "{{$labels.instance}}: Prometheus配置重新加載失敗"