如何快速實(shí)現(xiàn)Prometheus告警聚合
上篇回顧
上篇文章我們主要對(duì)告警排班進(jìn)行了闡述,具體實(shí)現(xiàn)思路可以添加下方二維碼一起來(lái)聊一聊。當(dāng)然我們針對(duì)告警排班并沒(méi)有做到通用,針對(duì)這種情況后期會(huì)輸出一個(gè)可通用demo。當(dāng)我們?cè)谑褂酶婢瘯r(shí)經(jīng)常會(huì)遇到告警洪流的問(wèn)題,所以我們針對(duì)此類問(wèn)題特此做一了個(gè)告警聚合來(lái)盡可能的避免改問(wèn)題的出現(xiàn)
告警聚合
我們看一下GPT針對(duì)告警聚合給出的解釋
在 Prometheus 中,告警聚合是指將多個(gè)相關(guān)的告警事件合并為單個(gè)聚合告警。當(dāng)存在大量具有相同或相似問(wèn)題的告警時(shí),告警聚合可以幫助減少噪聲,并提供更清晰、更有可讀性的告警信息。
通過(guò)告警聚合,可以將多個(gè)相關(guān)的告警事件合并為一個(gè)聚合告警,并在其中提供概要和摘要信息。這樣,當(dāng)出現(xiàn)大規(guī)模故障或問(wèn)題時(shí),可以避免大量重復(fù)的單獨(dú)告警,而是以更簡(jiǎn)潔的方式提供關(guān)鍵信息。
告警聚合通?;诠蚕順?biāo)簽(例如,相同的實(shí)例、相同的任務(wù)等)來(lái)確定哪些告警應(yīng)該被聚合。在 Prometheus 的配置文件中,可以使用 group_by 關(guān)鍵字來(lái)定義告警聚合規(guī)則。
案例介紹
基于告警認(rèn)領(lǐng)功能實(shí)現(xiàn)代碼的基礎(chǔ)上進(jìn)行稍加修改(代碼可以添加下方二維碼獲取),依舊使用gin、gorm是實(shí)現(xiàn)針對(duì)告警名稱的聚合,結(jié)合template簡(jiǎn)單展示告警詳情列表
環(huán)境概述
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master-50.57 Ready control-plane,master 96d v1.20.5
k8s-node-50.58 Ready <none> 96d v1.20.5
k8s-node-50.59 Ready <none> 96d v1.20.5
# kubectl get pod -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-main-0 2/2 Running 0 8d
alertmanager-main-1 2/2 Running 0 8d
alertmanager-main-2 2/2 Running 0 8d
blackbox-exporter-55c457d5fb-5m7ql 3/3 Running 0 8d
grafana-9df57cdc4-gpzsq 1/1 Running 0 8d
kube-state-metrics-56dbb74497-gpkn9 3/3 Running 0 8d
node-exporter-4wl6d 2/2 Running 0 8d
node-exporter-b4595 2/2 Running 0 8d
node-exporter-g4l99 2/2 Running 0 8d
prometheus-adapter-59df95d9f5-tnt4w 1/1 Running 0 8d
prometheus-adapter-59df95d9f5-xhz5v 1/1 Running 0 8d
prometheus-k8s-0 2/2 Running 1 8d
prometheus-k8s-1 2/2 Running 1 10m
prometheus-operator-c46b8b7c9-mg9cv 2/2 Running 0 8d
- golang版本:1.17.10
- gin版本:1.9.0
- gorm版本:1.25.1
快速開(kāi)始
- 釘釘機(jī)器人創(chuàng)建
這里就不做過(guò)多的說(shuō)明了,詳細(xì)請(qǐng)看告警認(rèn)領(lǐng)功能實(shí)現(xiàn)章節(jié)
- 創(chuàng)建template模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>告警詳情</title>
</head>
<body>
<table id="tfhover" class="tftable">
{{ if gt (len .slice) 0 }}
<tr>
<th >告警序號(hào)</th>
<th>告警名稱</th>
<th>告警實(shí)例</th>
<th>告警時(shí)間</th>
<th>告警詳情</th>
</tr>
{{ range $index, $value := .slice }}
<tr>
<td>{{ $value.ID }}</td>
<td>{{ $value.AlertName }}</td>
<td>{{ $value.Instance }}</td>
<td>{{ $value.CreatedAt }}</td>
<td>{{ $value.AlertInfo }}</td>
</tr>
{{ end }}
{{ else }}
<tr>
<td colspan="3">No data available</td>
</tr>
{{ end }}
</table>
</body>
</html>
<style type="text/css">
table.tftable {font-size:12px;color:#333333;width:100%;border-width: 1px;border-color: #729ea5;border-collapse: collapse;}
table.tftable th {font-size:12px;background-color:#acc8cc;border-width: 1px;padding: 8px;border-style: solid;border-color: #729ea5;text-align:left;}
table.tftable tr {background-color:#d4e3e5;}
table.tftable td {font-size:12px;border-width: 1px;padding: 8px;border-style: solid;border-color: #729ea5;}
</style>
<script type="text/javascript">
window.onload=function(){
var tfrow = document.getElementById('tfhover').rows.length;
var tbRow=[];
for (var i=1;i<tfrow;i++) {
tbRow[i]=document.getElementById('tfhover').rows[i];
tbRow[i].onmouseover = function(){
this.style.backgroundColor = '#ffffff';
};
tbRow[i].onmouseout = function() {
this.style.backgroundColor = '#d4e3e5';
};
}
};
</script>
這里只是簡(jiǎn)單的展示了告警詳情,小伙伴也可以自定義該template
核心代碼
- 聚合實(shí)例
func (pa *prometheusAlert) AddPrometheusAlert(paMsg model.Alerts) (err error) {
var alertInfo model.PrometheusAlert
var (
uids []string
instance []string
claimUsers string
title string
)
for _, alert := range paMsg.Alerts {
alertInfo.UID = utils.EntryMd5([]string{alert.Labels.AlertName, alert.Labels.Pod, alert.Labels.Namespace,
alert.Labels.Severity, alert.StartsAt.String()})
alertInfo.AlertName = alert.Labels.AlertName
alertInfo.Instance = alert.Labels.Instance
alertInfo.Server = alert.Labels.Server
alertInfo.Severity = alert.Labels.Severity
alertInfo.AlertInfo = alert.Annotations.Description
alertInfo.Pod = alert.Labels.Pod
alertInfo.Pod = alert.Labels.Container
alertInfo.Namespace = alert.Labels.Namespace
_, uid := db.PrometheusAlert.AddPrometheusAlert(alertInfo)
uids = append(uids, uid)
alertMsg, _ := db.PrometheusAlert.SelectPrometheusAlert(alertInfo.UID)
instance = append(instance, alertMsg.Instance)
}
if len(instance) >= 2 {
instance = instance[:2]
instance = append(instance, "\n\n<font color=\"#02b340\">實(shí)例過(guò)多請(qǐng)點(diǎn)擊詳情查看</font>")
}
data, title := template.DingGroupAlert(paMsg.Alerts[0].Labels.AlertName, paMsg.Alerts[0].Annotations.Description, strings.Join(instance, ","))
data += fmt.Sprintf("### [查看詳情](dingtalk://dingtalkclient/page/link?url=%s&pc_slide=true&title=%s)",
utils.URLEncode(viper.GetString("groupAlert.url")+"?uid="+strings.Join(uids, ",")), "")
_ = DingSend.SendDing(viper.GetString("dingTalk.hook"), data, title, utils.StringToSlice(claimUsers))
return nil
}
- 告警列表
func (pa *prometheusAlert) SelectPrometheusAlertList(uids string) (data []*model.PrometheusAlert, err error) {
for _, uid := range strings.Split(uids, ",") {
dataOne, _ := db.PrometheusAlert.SelectPrometheusAlert(uid)
data = append(data, dataOne)
}
return data, nil
}
- 加載template
func (pa *prometheusAlert) PrometheusAlertList(ctx *gin.Context) {
uids, _ := ctx.GetQuery("uid")
slice, _ := service.PrometheusAlert.SelectPrometheusAlertList(uids)
ctx.HTML(200, "index.html", gin.H{
"slice": slice,
})
}
觸發(fā)告警
告警信息的展示僅僅展示了部分內(nèi)容,可以按照各自的需求進(jìn)行展示
查看詳情
告警詳情僅僅展示了部分內(nèi)容,可以根據(jù)數(shù)據(jù)庫(kù)字段按需展示。這里也可以跟告警認(rèn)領(lǐng)功能結(jié)合使用。