基于Prometheus的全方位监控平台--告警中心消息转发系统PrometheusAlert一、为什么要用PrometheusAlert?1.1、背景1.2、架构原理1.3、PrometheusAlert 优点二、prometheusAlert部署配置2.1、在kubernetes中运行2.2、使用helm部署2.3、使用控制器文件部署2.4、配置PrometheusAlert使用mysql作为后端数据存储三、prometheusAlert配置管理3.1、编辑自定义模版3.2、新增自定义模版3.3、告警测试3.4、告警路由四、配置Alertmanager接入PrometheusAlert五、测试验证六、总结
官方站点:Prometheus Alert是开源的运维告警中心消息转发系统
手册:README - PrometheusAlert (gitbook.io)
Exports --> Prometheus --> Prometheus Rules --> Alertmanager --> webhook --> PrometheusAlert --> Routes --> 企微/钉钉/飞书...
配置灵活:通过web UI界面配置操作,相较于configmap较灵活。
功能强大:支持在线修改告警模版,告警路由,告警记录,测试等。
自定义强度高:通过路由匹配规则触发更多的告警媒介(企微,钉钉,飞书,公有云电话/短消息接口)。
开源免费:PrometheusAlert 是一款完全开源的软件,可以免费使用和定制,而且有广泛的社区支持。
xxxxxxxxxx
#Kubernetes中运行可以直接执行以下命令行即可(注意默认的部署模版中未挂载模版数据库文件 db/PrometheusAlertDB.db,为防止模版数据丢失,请自行增加挂载配置 )
$ kubectl apply -n monitor -f https://raw.githubusercontent.com/feiyu563/PrometheusAlert/master/example/kubernetes/PrometheusAlert-Deployment.yaml
#启动后可使用浏览器打开以下地址查看:http://[YOUR-PrometheusAlert-URL]:8080
#默认登录帐号和密码在app.conf中有配置
xxxxxxxxxx
#clone项目源代码
$ git clone https://github.com/feiyu563/PrometheusAlert.git
$ cd PrometheusAlert/example/helm
#如需修改配置文件,请更新config中的app.conf
#helm部署模版支持配置Ingress域名,可在values.yaml中进行配置
#配置修改完成后,通过以下命令启动即可(注意默认的部署模版中未挂载模版数据库文件 db/PrometheusAlertDB.db,为防止模版数据丢失,请自行增加挂载配置 )
$ helm upgrade --install monitor prometheusalert -n monitor
#启动后可使用浏览器打开以下地址查看: http://[Ingress_url]:[Ingress_port]
#默认登录帐号和密码在app.conf中有配置
为防止模版数据丢失,增加挂载配置
xxxxxxxxxx
apiVersion v1
kind PersistentVolumeClaim
metadata
name prome-alert-data-pvc
namespace monitor
spec
accessModes
ReadWriteMany
storageClassName"nfs-storage"
resources
requests
storage 5Gi
下载官方配置文件
xxxxxxxxxx
$ wget https://raw.githubusercontent.com/feiyu563/PrometheusAlert/master/example/kubernetes/PrometheusAlert-Deployment.yaml
修改配置文件
xxxxxxxxxx
app.conf
#---------------------↓全局配置-----------------------
appname = PrometheusAlert
#登录用户名
login_user=admin
#登录密码
login_password=admin123
#监听地址
httpaddr = "0.0.0.0"
#监听端口
httpport = 8080
...
#数据库驱动,支持sqlite3,mysql,postgres如使用mysql或postgres,请开启db_host,db_port,db_user,db_password,db_name的注释
db_driver=mysql
db_host=192.10.192.134
db_port=3306
db_user=root
db_password=XXXXXXXXXXX
db_name=prometheusalert
...
#是否开启告警记录定时删除 0为关闭,1为开启
RecordLive=1
#告警记录定时删除周期,单位天
RecordLiveDay=7
...
#是否开启微信告警通道,可同时开始多个通道0为关闭,1为开启
open-weixin=1
#默认企业微信机器人地址
wxurl=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=b3738de5-9f00-45de-9e3d-45e6309bc54c
...
name prometheus-alert-db
mountPath /app/db
name prometheus-alert-db
persistentVolumeClaim
claimName prome-alert-data-pvc
...
配置Ingress路由
xxxxxxxxxx
apiVersion networking.k8s.io/v1
kind Ingress
metadata
name prometheus-alert-ing
namespace monitor
annotations
prometheus.io/http_probe"true"
spec
ingressClassName nginx
rules
host prometheusalert.kubernets.cn
http
paths
pathType Prefix
backend
service
name prometheus-alert-center
port
number8080
path /
部署mysql到Kubernetes集群:
xxxxxxxxxx
## 创建秘钥
kubectl create secret generic mysql-root-password --from-literal=password=mysqlpwd123
## 创建pvc
apiVersion v1
kind PersistentVolumeClaim
metadata
name mysql-pvc
spec
accessModes
ReadWriteMany
resources
requests
storage 10Gi
storageClassName nfs-storage
## 创建mysql控制器
apiVersion apps/v1
kind Deployment
metadata
labels
app mysql
name mysql
namespace monitor
spec
selector
matchLabels
app mysql
template
metadata
labels
app mysql
spec
containers
image mysql5.7
name mysql
env
name MYSQL_ROOT_PASSWORD
valueFrom
secretKeyRef
name mysql-root-password
key password
# 如果你不想使用secret对象保存mysql登录密码,可以直接使用下面的方式指定,简单粗暴未尝不可
#value: "123456"
ports
containerPort3306
volumeMounts
name mysqlvolume
mountPath /var/lib/mysql
volumes
name mysqlvolume
# 使用pvc
persistentVolumeClaim
claimName mysql-pvc
---
#定义mysql的Service
apiVersion v1
kind Service
metadata
labels
app svc-mysql
name svc-mysql
namespace monitor
spec
selector
app mysql
type ClusterIP
ports
port3306
protocol TCP
targetPort3306
PrometheusAlert默认使用sqlite3作为后端自定义模板的存储,这种方式适合于单机部署,满足绝大部分生产场景使用。
考虑到部分企业对于服务的高可用要求较高,同时也为了让PrometheusAlert更易于横向扩展,用户可以更改PrometheusAlert的默认存储为mysql。
推荐使用mysql 5.7及以上版本。
创建数据库
xxxxxxxxxx
# 获取 mysql pod
kubectl get pod -n monitor|grep mysql
# 进入 mysql pod
kubectl exec -it mysql-6785bdcf-wsxhn -n monitor /bin/bash
# 在 mysql pod 容器内执行
# 登录 mysql
mysql -uroot -p
# 创建数据库 prometheusalert
CREATE DATABASE prometheusalert CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
获取 prometheusalert.sql
xxxxxxxxxx
# 获取pod
kubectl get pod -n monitor|grep prometheus
# 进入pod
kubectl exec -it prometheus-alert-center-5d7dfb8c99-h78z4 -n monitor /bin/sh
# 拷贝文件
kubectl cp monitor/prometheus-alert-center-5d7dfb8c99-l48gw:/app/db/prometheusalert.sql /mnt/data-s3-fs/prometheusalert-mysql/data/prometheusalert.sql
导入sql
利用Navicat或命令行将db目录中的 prometheusalert.sql 导入数据库prometheusalert:
xxxxxxxxxx
# 进入 mysql pod
kubectl exec -it mysql-6785bdcf-wsxhn -n monitor /bin/bash
# 在 mysql pod 容器内执行
# 切换到 mysql 数据目录下
cd /var/lib/mysql
# 登录 mysql
mysql -uroot -p
use prometheusalert
source prometheusalert.sql
模版内容:
xxxxxxxxxx
{{ $var := .externalURL}}{{ range $k,$v:=.alerts }}{{if eq $v.status "resolved"}}[PROMETHEUS-恢复信息]({{$v.generatorURL}})
> **[{{$v.labels.alertname}}]({{$var}})**✅
> <font color="info">告警级别:</font> {{$v.labels.severity}}
> <font color="info">开始时间:</font> {{GetCSTtime $v.startsAt}}
> <font color="info">结束时间:</font> {{GetCSTtime $v.endsAt}}
> <font color="info">命名空间:</font> {{$v.labels.namespace}}
> <font color="info">实例名称:</font> {{$v.labels.pod}}
> <font color="info">实例地址:</font> {{$v.labels.instance}}
> <font color="info">**{{$v.annotations.description}}**</font>{{else}}[PROMETHEUS-告警信息]({{$v.generatorURL}})
> **[{{$v.labels.alertname}}]({{$var}})**🔥
> <font color="#FF0000">告警级别:</font> {{$v.labels.severity}}
> <font color="#FF0000">开始时间:</font> {{GetCSTtime $v.startsAt}}
> <font color="#FF0000">命名空间:</font> {{$v.labels.namespace}}
> <font color="#FF0000">实例名称:</font> {{$v.labels.pod}}
> <font color="#FF0000">实例地址:</font> {{$v.labels.instance}}
> <font color="#FF0000">**{{$v.annotations.description}}**</font>{{end}}{{ end }}
{{ $urimsg:=""}}{{ range $key,$value:=.commonLabels }}{{$urimsg = print $urimsg $key "%3D%22" $value "%22%2C" }}{{end}}[✍点我屏蔽该告警](http://alertmanager.kubernets.cn/#/silences/new?filter=%7B{{SplitString $urimsg 0 -3}}%7D)
模板内容:
xxxxxxxxxx
{{ $var := .externalURL}}{{ range $k,$v:=.alerts }}{{if eq $v.status "resolved"}}[PROMETHEUS-恢复信息]({{$v.generatorURL}})
> **[{{$v.labels.alertname}}]({{$var}})**✅
> <font color="info">告警级别:</font> {{$v.labels.severity}}
> <font color="info">当前状态:</font> **<font color="#67C23A">已恢复</font>**
> <font color="info">开始时间:</font> {{GetCSTtime $v.startsAt}}
> <font color="info">结束时间:</font> {{GetCSTtime $v.endsAt}}
> <font color="info">实例地址:</font> {{$v.labels.instance}}
> <font color="info">**{{$v.annotations.description}}**</font>{{else}}[PROMETHEUS-告警信息]({{$v.generatorURL}})
> **[{{$v.labels.alertname}}]({{$var}})**🔥
> <font color="#FF0000">告警级别:</font> {{$v.labels.severity}}
> <font color="#FF0000">当前状态:</font> **<font color="#E6A23C">需要处理</font>**
> <font color="#FF0000">开始时间:</font> {{GetCSTtime $v.startsAt}}
> <font color="#FF0000">实例地址:</font> {{$v.labels.instance}}
> <font color="#FF0000">**{{$v.annotations.description}}**</font>{{end}}{{ end }}
{{ $urimsg:=""}}{{ range $key,$value:=.commonLabels }}{{$urimsg = print $urimsg $key "%3D%22" $value "%22%2C" }}{{end}}[✍点我屏蔽该告警](http://alertmanager.kubernets.cn/#/silences/new?filter=%7B{{SplitString $urimsg 0 -3}}%7D)
告警管理 --> 告警测试 --> 企业微信 --> 企业微信查看测试消息;
如果一个小伙伴下有很多机器资源,如何正则匹配?
更新alertmanager配置,将所有的告警均指向告警分发平台
xxxxxxxxxx
apiVersion v1
kind ConfigMap
metadata
name alertmanager-config
namespace monitor
data
alertmanager.yml -
global
resolve_timeout 1m
smtp_smarthost'smtp.exmail.qq.com:465' # 邮箱服务器的SMTP主机配置
smtp_from'zhdya@zhdya.cn' # 发送邮件主题
smtp_auth_username'zhdya@zhdya.cn' # 登录用户名
smtp_auth_password'yfXBXXXXX3DwYTjn' # 此处的auth password是邮箱的第三方登录授权密码,而非用户密码
smtp_require_tls false # 有些邮箱需要开启此配置,这里使用的是企微邮箱,仅做测试,不需要开启此功能。
templates
'/etc/alertmanager/*.tmpl'
route
group_by'env''instance''type''group''job''alertname''cluster'
group_wait 10s
group_interval 2m
repeat_interval 10m
receiver'webhook'
receivers
name'webhook'
webhook_configs
url'http://prometheus-alert-center.monitor.svc:8080/prometheusalert?type=wx&tpl=prometheus-wx&wxurqq.com/cgi-bin/webhook/send?key=71c0a6f0-43a0-4ecf-b8c9-52aff88f3b68&at=ZhangDaDan,ZHDYA'
send_resolvedtrue
inhibit_rules
source_match
severity'critical'
target_match
severity'warning'
equal'alertname' 'dev' 'instance'
wechat.tmpl -
"wechat.default.message" define
- if gt (len .Alerts.Firing) 0 -
- range $index $alert := .Alerts -
- if eq $index 0
========= 监控报警 =========
告警状态: .Status
告警级别: .Labels.severity
告警类型: $alert.Labels.alertname
故障主机 $alert.Labels.instance
告警主题 $alert.Annotations.summary
告警详情 $alert.Annotations.message $alert.Annotations.description ;
触发阀值: .Annotations.value
故障时间 ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05"
========= = end = =========
- end
- end
- end
- if gt (len .Alerts.Resolved) 0 -
- range $index $alert := .Alerts -
- if eq $index 0
========= 告警恢复 =========
告警类型: .Labels.alertname
告警状态: .Status
告警主题 $alert.Annotations.summary
告警详情 $alert.Annotations.message $alert.Annotations.description ;
故障时间 ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05"
恢复时间 ($alert.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05"
- if gt (len $alert.Labels.instance) 0
实例信息 $alert.Labels.instance
- end
========= = end = =========
- end
- end
- end
- end
email.tmpl -
"email.from" xxx.com end define
"email.to" xxx.com end define
"email.to.html" define
- if gt (len .Alerts.Firing) 0 -
range .Alerts
========= 监控报警 =========<br>
告警程序 prometheus_alert <br>
告警级别 .Labels.severity <br>
告警类型 .Labels.alertname <br>
告警主机 .Labels.instance <br>
告警主题 .Annotations.summary <br>
告警详情 .Annotations.description <br>
触发时间 .StartsAt.Format "2006-01-02 15:04:05" <br>
========= = end = =========<br>
end end -
- if gt (len .Alerts.Resolved) 0 -
range .Alerts
========= 告警恢复 =========<br>
告警程序 prometheus_alert <br>
告警级别 .Labels.severity <br>
告警类型 .Labels.alertname <br>
告警主机 .Labels.instance <br>
告警主题 .Annotations.summary <br>
告警详情 .Annotations.description <br>
触发时间 .StartsAt.Format "2006-01-02 15:04:05" <br>
恢复时间 .EndsAt.Format "2006-01-02 15:04:05" <br>
========= = end = =========<br>
end end -
- end
接口说明:
xxxxxxxxxx
receivers
name'webhook'
webhook_configs
url'http://prometheus-alert-center.monitor.svc:8080/prometheusalert?type=wx&tpl=prometheus-wx&wxurqq.com/cgi-bin/webhook/send?key=71c0a6f0-43a0-4ecf-b8c9-52aff88f3b68&at=ZhangDaDan,ZHDYA'
## 接口说明:
/prometheusalert #自定义模版接口,可通过Dashboard自定义模版后,支持任意WebHook接入
type=?:指定消息转发的目标类型,如钉钉、企业微信、飞书等;该参数为必选参数
目前支持的值:
dd 钉钉
wx 企业微信
workwechat 企业微信应用
fs 飞书
webhook WebHook
txdx 腾讯云短信
txdh 腾讯云电话
alydx 阿里云短信
alydh 阿里云电话
hwdx 华为云短信
bddx 百度云短信
rlydh 容联云电话
7moordx 七陌短信
7moordh 七陌语音电话
email Email
tg Telegram
rl 百度Hi(如流)
tpl=? 指定消息所使用的模版,如prometheus-dd(Prometheus针对钉钉的模板);模版可以去PrometheusAlert 页面的模版管理-->自定义模板页面查看或新建;该参数为必选参数
ddurl=?:指定PrometheusAlert发送消息的钉钉机器人地址,如需要多个地址可以通过,分割,该参数需要配合type=dd的模版使用;该参数为可选参数,如未填写,则默认从app.conf中获取默认配置
wxurl=?:指定PrometheusAlert发送消息的企业微信机器人地址,如需要多个地址可以通过,分割,该参数需要配合type=wx的模版使用;该参数为可选参数,如未填写,则默认从app.conf中获取默认配置
fsurl=?:指定PrometheusAlert发送消息的飞书机器人地址,如需要多个地址可以通过,分割,该参数需要配合type=fs的模版使用;该参数为可选参数,如未填写,则默认从app.conf中获取默认配置
phone=?:指定PrometheusAlert发送消息的手机号,如需要多个号码可以通过,分割,该参数需要配合type=txdx | hwdx | bddx | alydx | txdh | alydh | rlydh | 7moordx | 7moordh的模版使用;该参数为可选参数,如未填写,则默认从app.conf中获取默认配置
email=?:指定PrometheusAlert发送消息的email地址,如需要多个email可以通过,分割,该参数需要配合type=email的模版使用;该参数为可选参数,如未填写,则默认从app.conf中获取默认配置
groupid=?:指定PrometheusAlert发送消息的groupid,该参数需要配合type=rl的模版使用;该参数为可选参数,如未填写,则默认从app.conf中获取默认配置
webhook=?:指定PrometheusAlert发送消息的webhook,该参数需要配合type=webhook的模版使用;该参数为可选参数
at=?:钉钉机器人、企业微信机器人开启@某人的功能,如需添加多个@目标,用,号分割即可。此处需注意:钉钉@使用的是手机号码,企业微信机器人@使用的是用户帐号。;该参数为可选参数
rr=?:该参数为开启随机轮询,目前仅针对ddurl,fsurl,wxurl有效,默认情况下如果上述Url配置的是多个地址,则多个地址全部发送,如开启该选项,则从多个地址中随机取一个地址发送,主要是为了避免消息发送频率过高导致触发部分机器人拦截消息。;该参数为可选参数
split=?:该参数仅针对Prometheus告警消息有效,作用是将Prometheus分组消息拆分成单条发送。默认开启,如果Prometheus一次告警附带的同分组的告警消息条数过多,可能会导致告警消息体过大。如需关闭请在url中加入split=false;该参数为可选参数
注意:此参数如设置为split=false,则PrometheusAlert web页面的路由和告警记录等功能将自动关闭,请谨慎。
热加载alertmanager服务:
xxxxxxxxxx
$ curl -XPOST http://alertmanager.kubernets.cn/-/reload
验证所有的告警是否发送到指定的群组:
xxxxxxxxxx
## 默认标签走默认路由
$ curl -XPOST -H 'Content-Type: application/json' http://alertmanager.kubernets.cn/api/v1/alerts -d '[{"labels":{"hostname":"zhdya"},"annotations":{"summary":"This is a test alert"}}]'
验证指定标签告警到指定的群组:
xxxxxxxxxx
## 默认将告警分发到指定的告警组,并也需要在DEVOPS群组中展示
$ curl -XPOST -H 'Content-Type: application/json' http://alertmanager.kubernets.cn/api/v1/alerts -d '[{"labels":{"hostname":"hello"},"annotations":{"summary":"This is a test alert"}}]'