Docker環(huán)境部署Prometheus+Grafana監(jiān)控系統(tǒng)
點(diǎn)擊上方“程序員大白”,選擇“星標(biāo)”公眾號(hào)
重磅干貨,第一時(shí)間送達(dá)
原文鏈接:https://www.jianshu.com/p/dde0dc1761ec
文章轉(zhuǎn)自:DevOps技術(shù)棧
一、Prometheus簡介
Prometheus是由SoundCloud開發(fā)的開源監(jiān)控報(bào)警系統(tǒng)和時(shí)序列數(shù)據(jù)庫(TSDB)。

Prometheus使用Go語言開發(fā),是Google BorgMon監(jiān)控系統(tǒng)的開源版本。2016年由Google發(fā)起Linux基金會(huì)旗下的原生云基金會(huì)(Cloud Native Computing Foundation), 將Prometheus納入其下第二大開源項(xiàng)目。Prometheus目前在開源社區(qū)相當(dāng)活躍。Prometheus和Heapster(Heapster是K8S的一個(gè)子項(xiàng)目,用于獲取集群的性能數(shù)據(jù)。)相比功能更完善、更全面。Prometheus性能也足夠支撐上萬臺(tái)規(guī)模的集群。
1.系統(tǒng)架構(gòu)圖

2.基本原理
Prometheus的基本原理是通過HTTP協(xié)議周期性抓取被監(jiān)控組件的狀態(tài),任意組件只要提供對應(yīng)的HTTP接口就可以接入監(jiān)控。不需要任何SDK或者其他的集成過程。這樣做非常適合做虛擬化環(huán)境監(jiān)控系統(tǒng),比如VM、Docker、Kubernetes等。輸出被監(jiān)控組件信息的HTTP接口被叫做exporter 。目前互聯(lián)網(wǎng)公司常用的組件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系統(tǒng)信息(包括磁盤、內(nèi)存、CPU、網(wǎng)絡(luò)等等)。
其大概的工作流程是:
Prometheus server 定期從配置好的 jobs 或者 exporters 中拉 metrics,或者接收來自 Pushgateway 發(fā)過來的 metrics,或者從其他的 Prometheus server 中拉 metrics。 Prometheus server 在本地存儲(chǔ)收集到的 metrics,并運(yùn)行已定義好的 alert.rules,記錄新的時(shí)間序列或者向 Alertmanager 推送警報(bào)。 Alertmanager 根據(jù)配置文件,對接收到的警報(bào)進(jìn)行處理,發(fā)出告警。 在Grafana圖形界面中,可視化查看采集數(shù)據(jù)。
3.Prometheus的特性
多維度數(shù)據(jù)模型。
靈活的查詢語言。
不依賴分布式存儲(chǔ),單個(gè)服務(wù)器節(jié)點(diǎn)是自主的。
通過基于HTTP的pull方式采集時(shí)序數(shù)據(jù)。
可以通過中間網(wǎng)關(guān)進(jìn)行時(shí)序列數(shù)據(jù)推送。
通過服務(wù)發(fā)現(xiàn)或者靜態(tài)配置來發(fā)現(xiàn)目標(biāo)服務(wù)對象。
支持多種多樣的圖表和界面展示,比如Grafana等。
4.Prometheus的組件
Prometheus Server 主要負(fù)責(zé)數(shù)據(jù)采集和存儲(chǔ),提供PromQL查詢語言的支持。
Alertmanager 警告管理器,用來進(jìn)行報(bào)警。
Push Gateway 支持臨時(shí)性Job主動(dòng)推送指標(biāo)的中間網(wǎng)關(guān)。
Exporters 輸出被監(jiān)控組件信息的HTTP接口。
Grafana 監(jiān)控?cái)?shù)據(jù)展示W(wǎng)eb UI。
5.服務(wù)發(fā)現(xiàn)
由于 Prometheus 是通過 Pull 的方式主動(dòng)獲取監(jiān)控?cái)?shù)據(jù),也就是每隔幾秒鐘去各個(gè)target采集一次metric。所以需要手工指定監(jiān)控節(jié)點(diǎn)的列表,當(dāng)監(jiān)控的節(jié)點(diǎn)增多之后,每次增加節(jié)點(diǎn)都需要更改配置文件,盡管可以使用接口去熱更新配置文件,但仍然非常麻煩,這個(gè)時(shí)候就需要通過服務(wù)發(fā)現(xiàn)(service discovery,SD)機(jī)制去解決。
Prometheus 支持多種服務(wù)發(fā)現(xiàn)機(jī)制,可以自動(dòng)獲取要收集的 targets,包含的服務(wù)發(fā)現(xiàn)機(jī)制包括:azure、consul、dns、ec2、openstack、file、gce、kubernetes、marathon、triton、zookeeper(nerve、serverset),配置方法可以參考手冊的配置頁面。可以說 SD 機(jī)制是非常豐富的,但目前由于開發(fā)資源有限,已經(jīng)不再開發(fā)新的 SD 機(jī)制,只對基于文件的 SD 機(jī)制進(jìn)行維護(hù)。針對我們現(xiàn)有的系統(tǒng)情況,我們選擇了靜態(tài)配置方式。
二、部署PrometheusServer
1. 使用官方鏡像運(yùn)行
由于Prometheus官方鏡像沒有開啟熱加載功能,而且時(shí)區(qū)相差八小時(shí),所以我們選擇了自己制作鏡像,當(dāng)然你也可以使用官方的鏡像,提前創(chuàng)建Prometheus配置文件prometheus.yml和Prometheus規(guī)則文件rules.yml,然后通過如下命令掛載到官方鏡像中運(yùn)行:
$ docker run -d -p 9090:9090 --name=prometheus \
-v /root/prometheus/conf/:/etc/prometheus/ \
prom/prometheus
使用官方鏡像部署可以參考我的這篇文章:Docker部署Prometheus實(shí)現(xiàn)微信郵件報(bào)警。
2. 制作鏡像
現(xiàn)在我們創(chuàng)建自己的Prometheus鏡像,當(dāng)然你也可以直接使用我制作的鏡像
$ docker pull zhanganmin2017/prometheus:v2.9.0
首先去Prometheus下載二進(jìn)制文件安裝包解壓到package目錄下,我的Dockerfile目錄結(jié)構(gòu)如下:
$ tree prometheus-2.9.0/
prometheus-2.9.0/
├── conf
│ ├── CentOS7-Base-163.repo
│ ├── container-entrypoint
│ ├── epel-7.repo
│ ├── prometheus-start.conf
│ ├── prometheus-start.sh
│ ├── prometheus.yml
│ ├── rules
│ │ └── service_down.yml
│ └── supervisord.conf
├── Dockerfile
└── package
├── console_libraries
├── consoles
├── LICENSE
├── NOTICE
├── prometheus
├── prometheus.yml
└── promtool
5 directories, 26 files
分別創(chuàng)建圖中的目錄,可以看到conf目錄中有一些名為supervisord的文件,這是因?yàn)樵谌萜髦械倪M(jìn)程我們選擇使用supervisor進(jìn)行管理,當(dāng)然如果不想使用的化可以進(jìn)行相應(yīng)的修改。
制作prometheus-start.sh啟動(dòng)腳本,Supervisor啟動(dòng)Prometheus會(huì)調(diào)用該腳本
#!/bin/bash
/bin/prometheus \
--config.file=/data/prometheus/prometheus.yml \
--storage.tsdb.path=/data/prometheus/data \
--web.console.libraries=/data/prometheus/console_libraries \
--web.enable-lifecycle \
--web.console.templates=/data/prometheus/consoles
制作Prometheus-start.conf啟動(dòng)文件,Supervisord的配置文件
[program:prometheus]
command=sh /etc/supervisord.d/prometheus-start.sh ; 程序啟動(dòng)命令
autostart=false ; 在supervisord啟動(dòng)的時(shí)候不自動(dòng)啟動(dòng)
startsecs=10 ; 啟動(dòng)10秒后沒有異常退出,就表示進(jìn)程正常啟動(dòng)了,默認(rèn)1秒
autorestart=false ; 關(guān)閉程序退出后自動(dòng)重啟,可選值:[unexpected,true,false],默認(rèn)為unexpected,表示進(jìn)程意外殺死才重啟
startretries=0 ; 啟動(dòng)失敗自動(dòng)重試次數(shù),默認(rèn)是3
user=root ; 用哪個(gè)用戶啟動(dòng)進(jìn)程,默認(rèn)是root
redirect_stderr=true ; 把stderr重定向到stdout,默認(rèn)false
stdout_logfile_maxbytes=20MB ; stdout 日志文件大小,默認(rèn)是50MB
stdout_logfile_backups=30 ; stdout 日志文件備份數(shù),默認(rèn)是10;
# stdout 日志文件,需要注意當(dāng)指定目錄不存在時(shí)無法正常啟動(dòng),所以需要手動(dòng)創(chuàng)建目錄(supervisord 會(huì)自動(dòng)創(chuàng)建日志文件)
stdout_logfile=/data/prometheus/prometheus.log
stopasgroup=true
killasgroup=tru
制作supervisord.conf啟動(dòng)文件
[unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
chmod=0700 ; sockef file mode (default 0700)
[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
user=root
minfds=10240
minprocs=200
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
[program:sshd]
command=/usr/sbin/sshd -D
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/ssh_out.log
stderr_logfile=/var/log/supervisor/ssh_err.log
[include]
files = /etc/supervisord.d/*.conf
制作container-entrypoint守護(hù)文件,容器啟動(dòng)后執(zhí)行的腳本
#!/bin/sh
set -x
if [ ! -d "/data/prometheus" ];then
mkdir -p /data/prometheus/data
fi
mv /usr/local/src/* /data/prometheus/
exec /usr/bin/supervisord -n
exit
在conf目錄下新建Prometheus.yml配置文件,這個(gè)是Prometheus配置監(jiān)控主機(jī)的文件
global:
scrape_interval: 60s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 60s # Evaluate rules every 15 seconds. The default is every 1 minute.
alerting:
alertmanagers:
- static_configs:
- targets: [ '192.168.133.110:9093']
rule_files:
- "rules/host_sys.yml"
scrape_configs:
- job_name: 'Host'
static_configs:
- targets: ['10.1.250.36:9100']
labels:
appname: 'DEV01_250.36'
- job_name: 'prometheus'
static_configs:
- targets: [ '10.1.133.210:9090']
labels:
appname: 'Prometheus'
在conf目錄下新建rules目錄,編寫service_down.yml規(guī)則文件,這個(gè)也可以等到容器創(chuàng)建后再編寫,這里我們就直接寫好添加到鏡像中
groups:
- name: servicedown
rules:
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
name: instance
severity: Critical
annotations:
summary: " {{ $labels.appname }}"
description: " 服務(wù)停止運(yùn)行 "
value: "{{ $value }}"
制作dockerfile 鏡像文件
FROM docker.io/centos:7
MAINTAINER from [email protected]
# install repo
RUN rm -rf /etc/yum.repos.d/*.repo
ADD conf/CentOS7-Base-163.repo /etc/yum.repos.d/
ADD conf/epel-7.repo /etc/yum.repos.d/
# yum install
RUN yum install -q -y openssh-server openssh-clients net-tools \
vim supervisor && yum clean all
# install sshd
RUN ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key \
&& ssh-keygen -q -N "" -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key \
&& ssh-keygen -q -N "" -t ed25519 -f /etc/ssh/ssh_host_ed25519_key \
&& sed -i 's/#UseDNS yes/UseDNS no/g' /etc/ssh/sshd_config
# UTF-8 and CST +0800
ENV LANG=zh_CN.UTF-8
RUN echo "export LANG=zh_CN.UTF-8" >> /etc/profile.d/lang.sh \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
# install Prometheus
COPY package/prometheus /bin/prometheus
COPY package/promtool /bin/promtool
COPY package/console_libraries/ /usr/local/src/console_libraries/
COPY package/consoles/ /usr/local/src/consoles/
COPY conf/prometheus.yml /usr/local/src/prometheus.yml
COPY conf/rules/ /usr/local/src/rules/
# create user
RUN echo "root:123456" | chpasswd
# supervisord
ADD conf/supervisord.conf /etc/supervisord.conf
ADD conf/prometheus-start.conf /etc/supervisord.d/prometheus-start.conf
ADD conf/container-entrypoint /container-entrypoint
ADD conf/prometheus-start.sh /etc/supervisord.d/prometheus-start.sh
RUN chmod +x /container-entrypoint
# cmd
CMD ["/container-entrypoint"]
Dockerfile中安裝了supervisor進(jìn)程管理工具和SSH服務(wù),指定了字符集和時(shí)區(qū)。
生成鏡像并運(yùn)行容器服務(wù)
$ docker build -t zhanganmin2017/prometheus:v2.9.0 .
$ docker run -itd -h prometheus139-210 -m 8g --cpuset-cpus=28-31 --name=prometheus139-210 --network trust139 --ip=10.1.133.28 -v /data/works/prometheus139-210:/data 192.168.166.229/1an/prometheus:v2.9.0
$ docker exec -it prometheus139-210 /bin/bash
$ supervisorctl start prometheus首先去Prometheus
訪問prometheus Web頁面 IP:9090

三、部署監(jiān)控組件Exporter
Prometheus 是使用 Pull 的方式來獲取指標(biāo)數(shù)據(jù)的,要讓 Prometheus 從目標(biāo)處獲得數(shù)據(jù),首先必須在目標(biāo)上安裝指標(biāo)收集的程序,并暴露出 HTTP 接口供 Prometheus 查詢,這個(gè)指標(biāo)收集程序被稱為 Exporter ,不同的指標(biāo)需要不同的 Exporter 來收集,目前已經(jīng)有大量的 Exporter 可供使用,幾乎囊括了我們常用的各種系統(tǒng)和軟件,官網(wǎng)列出了一份常用Exporter的清單 ,各個(gè) Exporter 都遵循一份端口約定,避免端口沖突,即從 9100 開始依次遞增,這里是完整的 Exporter端口列表 。另外值得注意的是,有些軟件和系統(tǒng)無需安裝 Exporter,這是因?yàn)樗麄儽旧砭吞峁┝吮┞?Prometheus 格式的指標(biāo)數(shù)據(jù)的功能,比如 Kubernetes、Grafana、Etcd、Ceph 等。
1. 部署主機(jī)監(jiān)控組件
各節(jié)點(diǎn)主機(jī)使用主機(jī)網(wǎng)絡(luò)模式部署主機(jī)監(jiān)控組件node-exporter,官方不建議將其部署為Docker容器,因?yàn)樵搉ode_exporter設(shè)計(jì)用于監(jiān)控主機(jī)系統(tǒng)。需要訪問主機(jī)系統(tǒng),而且通過容器的方式部署發(fā)現(xiàn)磁盤數(shù)據(jù)不太準(zhǔn)確。二進(jìn)制部署就去看項(xiàng)目文檔吧
$ docker run -d \
--net="host" \
--pid="host" \
-v "/:/host:ro,rslave" \
quay.io/prometheus/node-exporter \
--path.rootfs=/host
容器正常運(yùn)行后,進(jìn)入Prometheus容器,在Prometheus.yml 文件中添加node-exporter組件地址
$ docker exec -it prometheus-133-210 /bin/bash
$ vim /data/prometheus/prometheus.yml
global:
scrape_interval: 60s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 60s # Evaluate rules every 15 seconds. The default is every 1 minute.
rule_files:
- "rules/service_down.yml"
scrape_configs:
- job_name: 'Host'
static_configs:
- targets: ['10.1.250.36:9100'] #node-exporter地址
labels:
appname: 'DEV01_250.36' #添加的標(biāo)簽
- job_name: 'prometheus'
static_configs:
- targets: [ '10.2.139.210:9090']
labels:
appname: 'prometheus'
熱加載更新Prometheus
$ curl -X POST http://10.1.133.210:9090/-/reload
查看Prometheus的web頁面已經(jīng)可以看到node-exporter,然后我們就可以定義報(bào)警規(guī)則和展示看板了,這部分內(nèi)容在后面配置Alertmanager和Grafana上會(huì)詳細(xì)介紹。

2.部署容器監(jiān)控組件
各節(jié)點(diǎn)主機(jī)部署容器監(jiān)控組件cadvisor-exporter,我這邊Docker網(wǎng)絡(luò)使用的macvlan方式,所以直接給容器分配了IP地址。
# docker run -d -h cadvisor139-216 --name=cadvisor139-216 --net=none -m 8g --cpus=4 --ip=10.1.139.216 --volume=/:/rootfs:ro --volume=/var/run:/var/run:rw --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --volume=/dev/disk/:/dev/disk:ro google/cadvisor:latest
同樣的,容器正常運(yùn)行后,我們訪問Cadvisor的Web頁面 IP+8080 端口

現(xiàn)在我們進(jìn)入Prometheus容器,在prometheus.yml主機(jī)文件中添加cadvisor組件
-----------
- job_name: 'Cadvisor'
static_configs:
- targets: [ '10.1.139.216:8080']
labels:
appname: 'DEV_Cadvisor01'
熱加載更新Prometheus
$ curl -X POST http://10.1.133.210:9090/-/reload
可以看到,Prometheus添加的cadvisor狀態(tài)為UP,說明正常接收數(shù)據(jù)。

3. 部署Redis監(jiān)控組件
容器部署Redis服務(wù)監(jiān)控組件redis_exporter,--redis.passwd指定認(rèn)證口令,如果你的redis訪問沒有密碼那么就無需指定后面參數(shù)。
$ docker run -d -h redis_exporter139-218 --name redis_exporter139-218 --network trust139 --ip=10.1.139.218 -m 8g --cpus=4 oliver006/redis_exporter --redis.passwd 123456
在prometheus.yml 添加redis-exporter
---------
- job_name: 'Redis-exporter' #exporter地址
static_configs:
- targets: ['10.2.139.218:9121'']
labels:
appname: 'redis-exporter'
- job_name: 'RedisProxy' #需要監(jiān)控的redis地址
static_configs:
- targets:
- redis://10.2.139.70:6379
- redis://10.2.139.71:6379
labels:
appname: RedisProxy
metrics_path: /scrape
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 10.2.139.218:9121
然后熱加載更新,步驟同上。
4.部署應(yīng)用監(jiān)控組件
中間件部署JVM監(jiān)控組件jmx_exporter, 這種方式是適用于代碼中沒有暴露應(yīng)用metrics信息的服務(wù),無需進(jìn)行代碼改動(dòng),在應(yīng)用啟動(dòng)時(shí)調(diào)用該jar包暴露jmx信息,然后在Prometheus分別指定應(yīng)用的地址即可。
首先下載jar :https://github.com/prometheus/jmx_exporter(jmx_prometheus_javaagent-0.11.0.jar ) 下載配置文件,有tomcat和weblogic注意區(qū)分:https://github.com/prometheus/jmx_exporter/tree/master/example_configs 然后在中間件啟動(dòng)參數(shù)添加以下內(nèi)容,指定配置文件和jar包的路徑:
CATALINA_OPTS="-javaagent:/app/tomcat-8.5.23/lib/jmx_prometheus_javaagent-0.11.0.jar=12345:/app/tomcat-8.5.23/conf/config.yaml"
上面我指定暴露metrics信息的端口為12345,所以我們在prometheus.yml文件中添加即可:
---------
- job_name: 'MIDL'
static_configs:
- targets: ['192.168.166.18:12345','192.168.166.19:12345']
labels:
appname: 'ORDER'
- targets: ['10.2.139.111:12345','10.2.139.112:12345']
labels:
appname: 'WEB'
其他步驟同上,Prometheus熱加載更新即可。
5. 部署進(jìn)程監(jiān)控組件
因?yàn)槲覀內(nèi)萜魇鞘褂脝为?dú)的網(wǎng)絡(luò)部署的,相當(dāng)于胖容器的方式,所以需要在監(jiān)控的容器中部署process-exporter進(jìn)程監(jiān)控組件來監(jiān)控容器的進(jìn)程,
軟件包下載:
wget https://github.com/ncabatoff/process-exporter/releases/download/v0.5.0/process-exporter-0.5.0.linux-amd64.tar.gz
配置文件:process-name.yaml
process_names:
- name: "{{.Matches}}"
cmdline:
- 'redis-shake' #匹配進(jìn)程,支持正則
啟動(dòng)參數(shù):
$ nohup ./process-exporter -config.path process-name.yaml &
在Prometheus.yml 添加該容器的IP地址,端口號(hào)為9256
-----------
- job_name: 'process'
static_configs:
- targets: [ '10.2.139.186:9256']
labels:
appname: 'Redis-shake'
ok,現(xiàn)在我們熱加載更新Prometheus的主機(jī)文件
$ curl -X POSThttp://10.2.139.210:9090/-/reload
四、部署Alertmanager報(bào)警組件
1. Alertmanager 概述
Alertmanager處理客戶端應(yīng)用程序(如Prometheus服務(wù)器)發(fā)送的告警。它負(fù)責(zé)對它們進(jìn)行重復(fù)數(shù)據(jù)刪除,分組和路由,以及正確的接收器集成,例如電子郵件,PagerDuty或OpsGenie。它還負(fù)責(zé)警報(bào)的靜默和抑制。
以下描述了Alertmanager實(shí)現(xiàn)的核心概念。請參閱配置文檔以了解如何更詳細(xì)地使用它們。
分組(Grouping)
分組將類似性質(zhì)的告警分類為單個(gè)通知。這在大型中斷期間尤其有用,因?yàn)樵S多系統(tǒng)一次失敗,并且可能同時(shí)發(fā)射數(shù)百到數(shù)千個(gè)警報(bào)。
示例:發(fā)生網(wǎng)絡(luò)分區(qū)時(shí),群集中正在運(yùn)行數(shù)十或數(shù)百個(gè)服務(wù)實(shí)例。一半的服務(wù)實(shí)例無法再訪問數(shù)據(jù)庫。Prometheus中的告警規(guī)則配置為在每個(gè)服務(wù)實(shí)例無法與數(shù)據(jù)庫通信時(shí)發(fā)送告警。結(jié)果,數(shù)百個(gè)告警被發(fā)送到Alertmanager。
作為用戶,只能想要獲得單個(gè)頁面,同時(shí)仍能夠確切地看到哪些服務(wù)實(shí)例受到影響。因此,可以將Alertmanager配置為按群集和alertname對警報(bào)進(jìn)行分組,以便發(fā)送單個(gè)緊湊通知。
這些通知的接收器通過配置文件中的路由樹配置告警的分組,定時(shí)的進(jìn)行分組通知。抑制(Inhibition)
如果某些特定的告警已經(jīng)觸發(fā),則某些告警需要被抑制。
示例:如果某個(gè)告警觸發(fā),通知無法訪問整個(gè)集群。Alertmanager可以配置為在該特定告警觸發(fā)時(shí)將與該集群有關(guān)的所有其他告警靜音。這可以防止通知數(shù)百或數(shù)千個(gè)與實(shí)際問題無關(guān)的告警觸發(fā)。靜默(SILENCES)
靜默是在給定時(shí)間內(nèi)簡單地靜音告警的方法。基于匹配器配置靜默,就像路由樹一樣。檢查告警是否匹配或者正則表達(dá)式匹配靜默。如果匹配,則不會(huì)發(fā)送該告警的通知。在Alertmanager的Web界面中可以配置靜默。客戶端行為(Client behavior)
Alertmanager對其客戶的行為有特殊要求。這些僅適用于不使用Prometheus發(fā)送警報(bào)的高級用例。#制作鏡像方式和Prometheus類似,稍作更改即可,此步省略。
設(shè)置警報(bào)和通知的主要步驟如下:
設(shè)置并配置Alertmanager; 配置Prometheus對Alertmanager訪問; 在普羅米修斯創(chuàng)建警報(bào)規(guī)則;
2. 部署Alertmanager組件
首先需要?jiǎng)?chuàng)建Alertmanager的報(bào)警通知文件,我這里使用企業(yè)微信報(bào)警,其中企業(yè)微信需要申請賬號(hào)認(rèn)證,方式如下:
訪問網(wǎng)站注冊企業(yè)微信賬號(hào)(不需要企業(yè)認(rèn)證)。
訪問apps創(chuàng)建第三方應(yīng)用,點(diǎn)擊創(chuàng)建應(yīng)用按鈕 -> 填寫應(yīng)用信息:
創(chuàng)建報(bào)警組,獲取組ID:



新建alertmanager.yml報(bào)警通知文件
global:
resolve_timeout: 2m
smtp_smarthost: smtp.163.com:25
smtp_from: [email protected]
smtp_auth_username: [email protected]
smtp_auth_password: zxxx
templates:
- '/data/alertmanager/conf/template/wechat.tmpl'
route:
group_by: ['alertname_wechat']
group_wait: 1s
group_interval: 1s
receiver: 'wechat'
repeat_interval: 1h
routes:
- receiver: wechat
match_re:
serverity: wechat
receivers:
- name: 'email'
email_configs:
- to: '[email protected]'
send_resolved: true
- name: 'wechat'
wechat_configs:
- corp_id: 'wwd402ce40b4720f24'
to_party: '2'
agent_id: '1000002'
api_secret: '9nmYa4p12OkToCbh_oNc'
send_resolved: true ## 發(fā)送已解決通知
參數(shù)說明:
corp_id: 企業(yè)微信賬號(hào)唯一 ID, 可以在我的企業(yè)中查看。
to_party: 需要發(fā)送的組。
agent_id: 第三方企業(yè)應(yīng)用的 ID,可以在自己創(chuàng)建的第三方企業(yè)應(yīng)用詳情頁面查看。
api_secret: 第三方企業(yè)應(yīng)用的密鑰,可以在自己創(chuàng)建的第三方企業(yè)應(yīng)用詳情頁面查看。
然后我們創(chuàng)建企業(yè)微信的消息模板,template/wechat.tmpl
{{ define "wechat.default.message" }}
{{ range $i, $alert :=.Alerts }}
【系統(tǒng)報(bào)警】
告警狀態(tài):{{ .Status }}
告警級別:{{ $alert.Labels.severity }}
告警應(yīng)用:{{ $alert.Annotations.summary }}
告警詳情:{{ $alert.Annotations.description }}
觸發(fā)閥值:{{ $alert.Annotations.value }}
告警主機(jī):{{ $alert.Labels.instance }}
告警時(shí)間:{{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
{{ end }}
這個(gè)報(bào)警的模板其中的值是在Prometheus觸發(fā)的報(bào)警信息中提取的,所以你可以根據(jù)自己的定義進(jìn)行修改。
運(yùn)行Alertmanager容器
$ docker run -d -p 9093:9093 --name alertmanager -m 8g --cpus=4 -v /opt/alertmanager.yml:/etc/alertmanager/alertmanager.yml -v /opt/template:/etc/alertmanager/template docker.io/prom/alertmanager:latest
容器運(yùn)行完成后查看web頁面 IP:9093

3. 配置報(bào)警規(guī)則
Prometheus的報(bào)警規(guī)則通過PromQL語句編寫
進(jìn)入Prometheus容器的rules目錄,上面我們制作鏡像的時(shí)候已經(jīng)創(chuàng)建好并掛載到了容器中,現(xiàn)在我們編寫其他的規(guī)則文件
編寫主機(jī)監(jiān)控規(guī)則文件,rules/host_sys.yml
cat host_sys.yml
groups:
- name: Host
rules:
- alert: HostMemory Usage
expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 90
for: 1m
labels:
name: Memory
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: "宿主機(jī)內(nèi)存使用率超過90%."
value: "{{ $value }}"
- alert: HostCPU Usage
expr: sum(avg without (cpu)(irate(node_cpu_seconds_total{mode!='idle'}[5m]))) by (instance,appname) > 0.8
for: 1m
labels:
name: CPU
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: "宿主機(jī)CPU使用率超過80%."
value: "{{ $value }}"
- alert: HostLoad
expr: node_load5 > 20
for: 1m
labels:
name: Load
severity: Warning
annotations:
summary: "{{ $labels.appname }} "
description: " 主機(jī)負(fù)載5分鐘超過20."
value: "{{ $value }}"
- alert: HostFilesystem Usage
expr: (node_filesystem_size_bytes-node_filesystem_free_bytes)/node_filesystem_size_bytes*100>80
for: 1m
labels:
name: Disk
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 宿主機(jī) [ {{ $labels.mountpoint }} ]分區(qū)使用超過80%."
value: "{{ $value }}%"
- alert: HostDiskio writes
expr: irate(node_disk_writes_completed_total{job=~"Host"}[1m]) > 10
for: 1m
labels:
name: Diskio
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 宿主機(jī) [{{ $labels.device }}]磁盤1分鐘平均寫入IO負(fù)載較高."
value: "{{ $value }}iops"
- alert: HostDiskio reads
expr: irate(node_disk_reads_completed_total{job=~"Host"}[1m]) > 10
for: 1m
labels:
name: Diskio
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 宿機(jī) [{{ $labels.device }}]磁盤1分鐘平均讀取IO負(fù)載較高."
value: "{{ $value }}iops"
- alert: HostNetwork_receive
expr: irate(node_network_receive_bytes_total{device!~"lo|bond[0-9]|cbr[0-9]|veth.*|virbr.*|ovs-system"}[5m]) / 1048576 > 10
for: 1m
labels:
name: Network_receive
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 宿主機(jī) [{{ $labels.device }}] 網(wǎng)卡5分鐘平均接收流量超過10Mbps."
value: "{{ $value }}3Mbps"
- alert: hostNetwork_transmit
expr: irate(node_network_transmit_bytes_total{device!~"lo|bond[0-9]|cbr[0-9]|veth.*|virbr.*|ovs-system"}[5m]) / 1048576 > 10
for: 1m
labels:
name: Network_transmit
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 宿主機(jī) [{{ $labels.device }}] 網(wǎng)卡5分鐘內(nèi)平均發(fā)送流量超過10Mbps."
value: "{{ $value }}3Mbps"
編寫容器監(jiān)控規(guī)則文件,rules/container_sys.yml
groups:
- name: Container
rules:
- alert: ContainerCPU
expr: (sum by(name,instance) (rate(container_cpu_usage_seconds_total{image!=""}[5m]))*100) > 200
for: 1m
labels:
name: CPU_Usage
severity: Warning
annotations:
summary: "{{ $labels.name }} "
description: " 容器CPU使用超200%."
value: "{{ $value }}%"
- alert: Memory Usage
expr: (container_memory_usage_bytes{name=~".+"} - container_memory_cache{name=~".+"}) / container_spec_memory_limit_bytes{name=~".+"} * 100 > 200
for: 1m
labels:
name: Memory
severity: Warning
annotations:
summary: "{{ $labels.name }} "
description: " 容器內(nèi)存使用超過200%."
value: "{{ $value }}%"
- alert: Network_receive
expr: irate(container_network_receive_bytes_total{name=~".+",interface=~"eth.+"}[5m]) / 1048576 > 10
for: 1m
labels:
name: Network_receive
severity: Warning
annotations:
summary: "{{ $labels.name }} "
description: "容器 [{{ $labels.device }}] 網(wǎng)卡5分鐘平均接收流量超過10Mbps."
value: "{{ $value }}Mbps"
- alert: Network_transmit
expr: irate(container_network_transmit_bytes_total{name=~".+",interface=~"eth.+"}[5m]) / 1048576 > 10
for: 1m
labels:
name: Network_transmit
severity: Warning
annotations:
summary: "{{ $labels.name }} "
description: "容器 [{{ $labels.device }}] 網(wǎng)卡5分鐘平均發(fā)送流量超過10Mbps."
value: "{{ $value }}Mbps"
編寫redis監(jiān)控規(guī)則文件,redis_check.yml
groups:
- name: redisdown
rules:
- alert: RedisDown
expr: redis_up == 0
for: 1m
labels:
name: instance
severity: Critical
annotations:
summary: " {{ $labels.alias }}"
description: " 服務(wù)停止運(yùn)行 "
value: "{{ $value }}"
- alert: Redis linked too many clients
expr: redis_connected_clients / redis_config_maxclients * 100 > 80
for: 1m
labels:
name: instance
severity: Warning
annotations:
summary: " {{ $labels.alias }}"
description: " Redis連接數(shù)超過最大連接數(shù)的80%. "
value: "{{ $value }}"
- alert: Redis linked
expr: redis_connected_clients / redis_config_maxclients * 100 > 80
for: 1m
labels:
name: instance
severity: Warning
annotations:
summary: " {{ $labels.alias }}"
description: " Redis連接數(shù)超過最大連接數(shù)的80%. "
value: "{{ $value }}"
編寫服務(wù)停止監(jiān)控規(guī)則,rules/service_down.yml
- alert: ProcessDown
expr: namedprocess_namegroup_num_procs == 0
for: 1m
labels:
name: instance
severity: Critical
annotations:
summary: " {{ $labels.appname }}"
description: " 進(jìn)程停止運(yùn)行 "
value: "{{ $value }}"
- alert: Grafana down
expr: absent(container_last_seen{name=~"grafana.+"} ) == 1
for: 1m
labels:
name: grafana
severity: Critical
annotations:
summary: "Grafana"
description: "Grafana容器停止運(yùn)行"
value: "{{ $value }}"
編寫報(bào)警規(guī)則可以參考后面Grafana展示看板后的數(shù)據(jù)展示語句,需要注意的是,我們?nèi)萜魇褂玫氖桥秩萜鞯姆绞剑串?dāng)作虛擬機(jī)來使用,所以需要添加應(yīng)用和服務(wù)停止的Exporter,如果你的容器守護(hù)進(jìn)程直接就是應(yīng)用的話,只需要監(jiān)控容器的啟停就可以了。
測試微信報(bào)警

五、Grafana展示組件
雖然 Prometheus 提供的 Web UI 也可以很好的查看不同指標(biāo)的視圖,但是這個(gè)功能非常簡單,只適合用來調(diào)試。要實(shí)現(xiàn)一個(gè)強(qiáng)大的監(jiān)控系統(tǒng),還需要一個(gè)能定制展示不同指標(biāo)的面板,能支持不同類型的展現(xiàn)方式(曲線圖、餅狀圖、熱點(diǎn)圖、TopN 等),這就是儀表盤(Dashboard)功能。
Prometheus 開發(fā)了一套儀表盤系統(tǒng)PromDash,不過很快這套系統(tǒng)就被廢棄了,官方開始推薦使用 Grafana 來對 Prometheus 的指標(biāo)數(shù)據(jù)進(jìn)行可視化,這不僅是因?yàn)?Grafana 的功能非常強(qiáng)大,而且它和 Prometheus 可以完美的無縫融合。
Grafana是一個(gè)用于可視化大型測量數(shù)據(jù)的開源系統(tǒng),它的功能非常強(qiáng)大,界面也非常漂亮,使用它可以創(chuàng)建自定義的控制面板,你可以在面板中配置要顯示的數(shù)據(jù)和顯示方式,它支持很多不同的數(shù)據(jù)源,比如:Graphite、InfluxDB、OpenTSDB、Elasticsearch、Prometheus 等,而且它也支持眾多的插件 。
1. 部署Grafana服務(wù)容器
$ docker run -d -h grafana139-211 -m 8g --network trust139 --ip=10.2.139.211 --cpus=4 --name=grafana139-211 -e "GF_SERVER_ROOT_URL=http://10.2.139.211" -e "GF_SECURITY_ADMIN_PASSWORD=passwd" grafana/grafana
運(yùn)行后訪問IP:3000,user:admin pass:passwd

2. 添加Prometheus數(shù)據(jù)源

3. 導(dǎo)入監(jiān)控模板
使用編號(hào)導(dǎo)入模板,Grafana服務(wù)需要聯(lián)網(wǎng),否則需要到Grafana模板下載JSON文件導(dǎo)入。

下面是我使用的幾個(gè)模板,導(dǎo)入后可以根據(jù)自己的情況定義變量值

主機(jī)監(jiān)控展示看板Node-exporter導(dǎo)入 8919 模板 容器監(jiān)控展示看板cadvisor-exporter導(dǎo)入193 模板 應(yīng)用監(jiān)控展示看板jmx-exporter導(dǎo)入8563 模板 Redis監(jiān)控展示看板Redis-exporter導(dǎo)入2751 模板 進(jìn)程監(jiān)控展示看板Process-exporter導(dǎo)入249 模板
六、PromQL語句
七、使用Concul HTTP注冊方式實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)
一般是用服務(wù)發(fā)現(xiàn)需要應(yīng)用需要服務(wù)注冊,我們這邊因?yàn)槲⒎?wù)改造還沒完成,還有一些tomcat和weblogic中間件,而且選用的注冊中心是Eurka,所以為了在代碼不改動(dòng)的情況下使用服務(wù)發(fā)現(xiàn),選擇了concul 作為注冊中心,因?yàn)槭莄onsul是可以通過http方式注冊的。
1. consul 內(nèi)部原理

Consul分為Client和Server兩種節(jié)點(diǎn)(所有的節(jié)點(diǎn)也被稱為Agent),Server節(jié)點(diǎn)保存數(shù)據(jù),Client負(fù)責(zé)健康檢查及轉(zhuǎn)發(fā)數(shù)據(jù)請求到Server;Server節(jié)點(diǎn)有一個(gè)Leader和多個(gè)Follower,Leader節(jié)點(diǎn)會(huì)將數(shù)據(jù)同步到Follower,Server的數(shù)量推薦是3個(gè)或者5個(gè),在Leader掛掉的時(shí)候會(huì)啟動(dòng)選舉機(jī)制產(chǎn)生一個(gè)新的Leader。
集群內(nèi)的Consul節(jié)點(diǎn)通過gossip協(xié)議(流言協(xié)議)維護(hù)成員關(guān)系,也就是說某個(gè)節(jié)點(diǎn)了解集群內(nèi)現(xiàn)在還有哪些節(jié)點(diǎn),這些節(jié)點(diǎn)是Client還是Server。單個(gè)數(shù)據(jù)中心的流言協(xié)議同時(shí)使用TCP和UDP通信,并且都使用8301端口。跨數(shù)據(jù)中心的流言協(xié)議也同時(shí)使用TCP和UDP通信,端口使用8302。
集群內(nèi)數(shù)據(jù)的讀寫請求既可以直接發(fā)到Server,也可以通過Client使用RPC轉(zhuǎn)發(fā)到Server,請求最終會(huì)到達(dá)Leader節(jié)點(diǎn),在允許數(shù)據(jù)輕微陳舊的情況下,讀請求也可以在普通的Server節(jié)點(diǎn)完成,集群內(nèi)數(shù)據(jù)的讀寫和復(fù)制都是通過TCP的8300端口完成。
具體consul的原理及架構(gòu)請?jiān)L問:http://blog.didispace.com/consul-service-discovery-exp/
2. 使用docker部署consul 集群
#啟動(dòng)第1個(gè)Server節(jié)點(diǎn),集群要求要有3個(gè)Server,將容器8500端口映射到主機(jī)8900端口,同時(shí)開啟管理界面
docker run -d --name=consul1 -p 8900:8500 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --bootstrap-expect=3 --client=0.0.0.0 -ui
#啟動(dòng)第2個(gè)Server節(jié)點(diǎn),并加入集群
docker run -d --name=consul2 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.1
#啟動(dòng)第3個(gè)Server節(jié)點(diǎn),并加入集群
docker run -d --name=consul3 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2
#啟動(dòng)第4個(gè)Client節(jié)點(diǎn),并加入集群
docker run -d --name=consul4 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=false --client=0.0.0.0 --join 172.17.0.2
瀏覽器訪問容器映射的8900端口:

3. 服務(wù)注冊到Consul
使用HTTP API 方式注冊node-exporter服務(wù)到Consul
curl -X PUT -d '{"id": "192.168.16.173","name": "node-exporter","address": "192.168.16.173","port": ''9100,"tags": ["DEV"], "checks": [{"http": "http://192.168.16.173:9100/","interval": "5s"}]}' http://172.17.0.4:8500/v1/agent/service/register
解注冊:
curl --request PUT http://172.17.0.4:8500/v1/agent/service/deregister/192.168.166.14
注冊多個(gè)服務(wù)到consul,使用腳本:
#!/bin/bash
all_IP=`cat /opt/ip`
name=cadvisor
port=9100
for I in $all_IP
do
curl -X PUT -d '{"id": "'$I'","name": "'$name'","address": "'$I'","port": '$port',"tags": ["cadvisor"], "checks": [{"http": "http://'$I':'$port'/","interval": "5s"}]}' http://172.17.0.4:8500/v1/agent/service/register
done

4. Prometheus 配置consul 服務(wù)發(fā)現(xiàn)
consul 可以使用的元標(biāo)簽:
__meta_consul_address:目標(biāo)的地址
__meta_consul_dc:目標(biāo)的數(shù)據(jù)中心名稱
__meta_consul_tagged_address_<key>:每個(gè)節(jié)點(diǎn)標(biāo)記目標(biāo)的地址鍵值
__meta_consul_metadata_<key>:目標(biāo)的每個(gè)節(jié)點(diǎn)元數(shù)據(jù)鍵值
__meta_consul_node:為目標(biāo)定義的節(jié)點(diǎn)名稱
__meta_consul_service_address:目標(biāo)的服務(wù)地址
__meta_consul_service_id:目標(biāo)的服務(wù)ID
__meta_consul_service_metadata_<key>:目標(biāo)的每個(gè)服務(wù)元數(shù)據(jù)鍵值
__meta_consul_service_port:目標(biāo)的服務(wù)端口
__meta_consul_service:目標(biāo)所屬服務(wù)的名稱
__meta_consul_tags:標(biāo)記分隔符連接的目標(biāo)的標(biāo)記列表
修改Prometheus.yml 文件,使用relabel將consul的元標(biāo)簽重寫便于查看
- job_name: 'consul'
consul_sd_configs:
- server: '192.168.16.173:8900'
services: [] #匹配所有service
relabel_configs:
- source_labels: [__meta_consul_service] #service 源標(biāo)簽
regex: "consul" #匹配為"consul" 的service
action: drop # 執(zhí)行的動(dòng)作
- source_labels: [__meta_consul_service] # 將service 的label重寫為appname
target_label: appname
- source_labels: [__meta_consul_service_address]
target_label: instance
- source_labels: [__meta_consul_tags]
target_label: job
Prometheus 熱加載更新
curl -X POST http://192.168.16.173:9090/-/reload
訪問Prometheus web頁面

應(yīng)用注冊到consul
在不需要開發(fā)修改代碼的前提下,我們可以使用Prometheus的jmx-exporter收集應(yīng)用的相關(guān)指標(biāo),在應(yīng)用中間件tomcat/weblogic等調(diào)用jmx-exporter,具體方式查看https://www.jianshu.com/p/dfd6ba5206dc
啟動(dòng)應(yīng)用后會(huì)啟動(dòng)12345端口暴露jvm數(shù)據(jù),現(xiàn)在我們要做的就是將這個(gè)端口注冊到Consul上,然后Prometheus會(huì)從consul 拉取應(yīng)用主機(jī)。
使用腳本實(shí)現(xiàn)
$ cat ip
TEST 192.168.166.10 192.168.166.11
UNMIN 192.168.166.12 192.168.166.13
---------------
$ cat consul.sh
#!/bin/bash
port=12345
while read app
do
echo ${app}
app_tmp=(${app})
echo ${app_tmp[0]}
length=${#app_tmp[@]}
echo ${length}
for((k=1;k<${length};k++));
do
echo ${app_tmp[k]}
curl -X PUT -d '{"id": "'${app_tmp[k]}'","name": "'${app_tmp[0]}'","address": "'${app_tmp[k]}'","port": '$port',"tags": ["MIDL"],"checks": [{"http": "http://'${app_tmp[k]}':'$port'/","interval": "5s"}]}' http://172.17.0.4:8500/v1/agent/service/register
done
done < ip
執(zhí)行腳本注冊到consul

配置Grafana JVM 監(jiān)控模板
Load 8563模板

推薦閱讀
國產(chǎn)小眾瀏覽器因屏蔽視頻廣告,被索賠100萬(后續(xù))
年輕人“不講武德”:因看黃片上癮,把網(wǎng)站和786名女主播起訴了
關(guān)于程序員大白
程序員大白是一群哈工大,東北大學(xué),西湖大學(xué)和上海交通大學(xué)的碩士博士運(yùn)營維護(hù)的號(hào),大家樂于分享高質(zhì)量文章,喜歡總結(jié)知識(shí),歡迎關(guān)注[程序員大白],大家一起學(xué)習(xí)進(jìn)步!


