乔克视界 乔克视界
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档

乔克

云原生爱好者
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档
  • 运维

  • 监控

    • 告警平台开发
      • 逻辑梳理
      • 实现效果
      • 代码实现
    • 夜莺监控自定义告警模板
  • 开发

  • 安全

  • 随笔

  • 博客
  • 监控
乔克
2025-07-18
目录

告警平台开发

✍ 道路千万条,安全第一条。操作不规范,运维两行泪。

在《告警平台1.0》中,我们实现了告警平台,可以实现纳管通过AlertManager推送的告警信息,然后进行灵活的告警通知发送。

[[附件/images/b5f86befbd73b6e9bcfcd0d765ac7a60_MD5.jpeg|Open: Pasted image 20250313104009.png]] b5f86befbd73b6e9bcfcd0d765ac7a60 MD5

在这个基础上,我们可以实现对告警进行认领、屏蔽、关闭等操作,也能在移动端进行操作。

但是,这个方案现在只能被动的接受告警,对于告警规则还是需要到Prometheus中去配置,当告警规则较多的情况下,配置分类比较麻烦,所以在想:能不能在现有平台上增加规则配置监控功能?

所以,我又到老朋友《快猫Flashcat》上进行学习,它们除了有故障管理,也有告警管理,可以实现监控告警一体化。

[[附件/images/75c13e2f18664e38ee33dd91edf02d53_MD5.jpeg|Open: Pasted image 20250313104552.png]] 75c13e2f18664e38ee33dd91edf02d53 MD5

而且,它支持的数据源还比较多,如下:

[[附件/images/8edfc3b6a9cb70cdbd6915a515600fdf_MD5.jpeg|Open: Pasted image 20250313104825.png]] 8edfc3b6a9cb70cdbd6915a515600fdf MD5

当然,我不需要实现这么多,只要把常用的Prometheus和Elasticsearch实现即可。

# 逻辑梳理

相对来说,监控规则的实现逻辑还是比较清晰,如下:

[[附件/images/101eb7186f7155693832571b6d9f67a2_MD5.jpeg|Open: Pasted image 20250313105526.png]] 101eb7186f7155693832571b6d9f67a2 MD5

本质上就是后台系统周期性的在数据库(Prometheus、Elasticsearch)中通过规则进行查询,当异常条件满足后,就生成对应的告警事件,然后将告警事件分发到协作空间。

另外,为了提升告警事件的管理效率,避免频繁查询、更新数据库,当产生告警事件后,会将其存入Redis,告警事件更新会同步更新Redis中的数据。同时,后端会有一个常驻的携程,获取Redis中的告警事件,评估是否需要发送到协作空间。

# 实现效果

1、为了便于规则的管理,我们建立了分组,这里的分组没有和协作空间建立必然的联系,只是为了便于管理告警规则。

[[附件/images/b63c296f261edd2dbec2cca8f81049e2_MD5.jpeg|Open: Pasted image 20250313111222.png]] b63c296f261edd2dbec2cca8f81049e2 MD5

2、告警规则就会按组进行分类展示

[[附件/images/c21134bbe89fc3312c87cd07a185f854_MD5.jpeg|Open: Pasted image 20250313111328.png]] c21134bbe89fc3312c87cd07a185f854 MD5

3、创建规则,目前支持创建Prometheus和Elasticsearch规则。

(1)创建Prometheus规则

[[附件/images/8b75a21ccdbcc79962f875775f0b4cf4_MD5.jpeg|Open: Pasted image 20250313111549.png]] 8b75a21ccdbcc79962f875775f0b4cf4 MD5 [[附件/images/9486ff7a41c36f7d4c6eb80af4e90709_MD5.jpeg|Open: Pasted image 20250313111847.png]] 9486ff7a41c36f7d4c6eb80af4e90709 MD5 [[附件/images/a36008f8c0ea77e7b64723b09fa8a924_MD5.jpeg|Open: Pasted image 20250313111902.png]] a36008f8c0ea77e7b64723b09fa8a924 MD5 我们可以:

  • 为规则添加附加标签,比如为了按标签进行告警发送的时候添加biz=a的标签。
  • 定义具体的PromQL
  • 指定告警评估表达式,目前支持严重、警告、通知三个表达式
  • 可以配置告警持续时间,只有当告警事件超过持续时间,才会产生真正的告警事件
  • 可以配置通知详情,便于人员阅读
  • 可以配置通知渠道,将事件推送到某个协作空间

当告警产生后就会发送到对应的渠道,比如发送到企微的消息如下:

[[附件/images/91658d805f52cf6720c46db99cf2080f_MD5.jpeg|Open: Pasted image 20250313112623.png]] 91658d805f52cf6720c46db99cf2080f MD5

(2)创建Elasticsearch规则

[[附件/images/b2656d156a5020abdcfc1f3ac3e2c942_MD5.jpeg|Open: Pasted image 20250213164836.png]] b2656d156a5020abdcfc1f3ac3e2c942 MD5

主要配置的地方:

  • 指定数据源:需要配置告警的数据源地址
  • 指定索引:针对哪个索引做规则
  • 指定筛选字段:通过这些字段进行过滤日志
  • 指定标注字段:在发送告警通知的时候会将该部分发送到群里,便于运维开发提取关键信息

其中,添加标注是为了在展示需要的告警信息,比如: [[附件/images/e34cb228a7bbfbf7a13e8033bdf16c33_MD5.jpeg|Open: Pasted image 20250313113740.png]] e34cb228a7bbfbf7a13e8033bdf16c33 MD5

另外,分组评估用户将告警信息进行分组发送,触发条件用于判断是不是发送告警通知。

当告警事件产生,就会发送一条告警通知,如下:

[[附件/images/127784aeff809c18bd745b1312c55cc3_MD5.jpeg|Open: Pasted image 20250313134147.png]] 127784aeff809c18bd745b1312c55cc3 MD5

日志监控的告警逻辑也比较简单,如下:

[[附件/images/9f435be2c6bad62140927d1c6f9ce8f4_MD5.jpeg|Open: Pasted image 20250313135644.png]] 9f435be2c6bad62140927d1c6f9ce8f4 MD5

# 代码实现

1、对于Prometheus监控规则,定时从Prometheus时序数据库中查询值,然后和配置的策略进行比较,如果满足要求则产生告警事件。

// 从时序数据库中查询数据
resQuery, err = cli.(global.PrometheusProvider).Query(rule.PrometheusConfig.PromQL)

// 然后将值进行比较
for _, v: = range resQuery {
    for _, ruleExpr: = range rule.PrometheusConfig.Rules {
        // 去除空格
        cleanedExpr: = strings.ReplaceAll(ruleExpr.Expr, " ", "")
        re: = regexp.MustCompile(`([^\d]+)(\d+)`)
        matches: = re.FindStringSubmatch(cleanedExpr)
        if len(matches) < 2 {
            continue
        }
        t,
        _: = strconv.ParseFloat(matches[2], 64)

        option: = alarmCenter.EvalCondition {
            Operator: matches[1],
            QueryValue: v.Value,
            ExpectedValue: t,
        }

        // 进行比较,当满足条件后生成事件
        if ok := alarmCenter.EvalCondition(option);ok{
	        event := alarmCenter.BuildAlertEvent(rule)
	        alarmCenter.SaveAlertEvent(event)
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

2、对于Elasticsearch监控规则,定时从Elasticsearch数据库中查询满足日志条数,当满足告警条件后生成告警事件。

// 从ES中查询值
curAt: = time.Now()
startsAt: = utils.ParserDuration(curAt, int(rule.ElasticsearchConfig.Scope), "m")
queryOptions: = provider.LogQueryOptions {
    ElasticSearch: provider.Elasticsearch {
        Index: rule.ElasticsearchConfig.Index,
        QueryFilter: rule.ElasticsearchConfig.Filter,
        Annotations: rule.ElasticsearchConfig.Annotations,
        GroupEval: rule.ElasticsearchConfig.GroupEval,
    },
    StartAt: utils.FormatTimeToUTC(startsAt.Unix()),
    EndAt: utils.FormatTimeToUTC(curAt.Unix()),
}
queryRes, count, err = cli.(global.ElasticsearchProvider).Query(queryOptions)

option := alarmCenter.EvalCondition {
    Operator: rule.ElasticsearchConfig.TriggerCondition.Operator,
    QueryValue: float64(count),
    ExpectedValue: rule.ElasticsearchConfig.TriggerCondition.ExpectedValue,
}
// 进行比较,当满足条件后生成事件
if ok := alarmCenter.EvalCondition(option);ok{
    event := alarmCenter.BuildAlertEvent(rule)
    alarmCenter.SaveAlertEvent(event)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

3、条件评估的代码如下

func EvalCondition(ec alarmCenter.EvalCondition) bool {
    // 使用 map 存储操作符对应的比较函数
    operatorMap := map[string]func(float64, float64) bool{
        ">":  func(a, b float64) bool { return a > b },
        ">=": func(a, b float64) bool { return a >= b },
        "<":  func(a, b float64) bool { return a < b },
        "<=": func(a, b float64) bool { return a <= b },
        "==": func(a, b float64) bool { return a == b },
        "=":  func(a, b float64) bool { return a == b },
        "!=": func(a, b float64) bool { return a != b },
    }

    // 查找并执行对应的比较函数
    if compareFunc, exists := operatorMap[ec.Operator]; exists {
        return compareFunc(ec.QueryValue, ec.ExpectedValue)
    }

    global.GVA_LOG.Error(fmt.Sprintf("无效的评估条件,%s:%s:%f", ec.Type, ec.Operator, ec.ExpectedValue))
    return false
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

告警通知的逻辑还是不变,当监听到告警事件后,进行对应的告警通知。

#监控
上次更新: 2025/07/18, 15:57:17
基于Kubernetes容器平台的容灾方案
夜莺监控自定义告警模板

← 基于Kubernetes容器平台的容灾方案 夜莺监控自定义告警模板→

最近更新
01
2025年,SRE在企业中可以做哪些事
07-18
02
SRE 如何提升自己在团队中的影响力
07-18
03
使用Go开发MCP服务
07-18
更多文章>
Theme by Vdoing | Copyright © 2019-2025 乔克 | MIT License | 渝ICP备20002153号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式