前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Prometheus-Operator:告警认领功能实现

Prometheus-Operator:告警认领功能实现

作者头像
用户1107783
发布2023-09-11 11:18:01
4830
发布2023-09-11 11:18:01
举报
文章被收录于专栏:云原生运维社区
上篇回顾

上篇文章我们主要是针对告警路由进行了讲解,告警路由使用无疑是非常方便的,但是缺少一些告警处理人相关提醒,所以我们本篇文章讲解一下告警认领的功能实现

prometheus架构图

通过上图我们可以发现,告警主要是Alertmanager组件管理,所以我们需要提供一个hook接收Alertmanager的告警信息,然后对告警数据进行处理,以达到我们实现告警认领的目的

案例介绍

使用gin+gorm、来实现一个hook,使得我们可以处理Alertmanager发送过来的告警数据,钉钉outgoing机制传递用户ID,使用钉钉dtmd来自动实现回复功能

环境概述

代码语言:javascript
复制
# 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

快速开始

  1. 钉钉机器人创建

登录钉钉后台创建机器人

本篇文章机器人名称为:test

  1. 钉钉群聊添加机器人

核心代码

  1. 数据库字段设计
代码语言:javascript
复制
type PrometheusAlert struct {
 ID             uint           `gorm:"primarykey" json:"id" form:"id"`
 CreatedAt      time.Time      `gorm:"column:creation_time" json:"created_at" form:"created_at"`
 UpdatedAt      time.Time      `gorm:"column:update_time" json:"updated_at" form:"updated_at"`
 DeletedAt      gorm.DeletedAt `gorm:"column:delete_time;index" json:"deleted_at" form:"deleted_at"`
 AlertName      string         `gorm:"comment: '告警名称';size:500;not null" json:"alert_name" form:"alert_name"`
 Instance       string         `gorm:"comment: '告警实例';size:500" json:"instance" form:"instance"`
 Server         string         `gorm:"comment: '告警环境';size:64" json:"server" form:"server"`
 Severity       string         `gorm:"comment: '告警级别';size:64" json:"severity" form:"severity"`
 AlertInfo      string         `gorm:"comment: '告警详情';size:500" json:"alert_info" form:"alert_info"`
 IsAlert        bool           `gorm:"comment: '是否告警';size:1;default:1" json:"is_alert" form:"is_alert"`
 FirstAlertTime time.Time      `gorm:"comment: '第一次告警时间'" json:"first_alert_time" form:"first_alert_time"`
 EndAlertTime   time.Time      `gorm:"comment: '结束告警时间'" json:"end_alert_time" form:"end_alert_time"`
 IsClaim        bool           `gorm:"comment: '是否认领';size:1;default:0" json:"is_claim" form:"is_claim"`
 Pod            string         `gorm:"comment: 'pod名称';size:255" json:"pod" form:"pod"`
 Container      string         `gorm:"comment: '容器名称';size:255" json:"container" form:"container"`
 Namespace      string         `gorm:"comment: '名称空间';size:255" json:"namespace" form:"namespace"`
 ClaimUsers     string         `gorm:"comment: '认领人';size:500" json:"claim_users" form:"claim_users"`
 UID            string         `gorm:"comment: '告警UID';size:500;not null;unique" json:"uid" form:"uid"`
}

主要说一下UID字段含义,主要功能是对每一条告警增加一个UID,用于区分是否为同一条告警记录,进而绑定认领人,这里的UID使用md5的方式加密告警字段

  1. 钉钉机器人回调事件
代码语言:javascript
复制
func (cbd *callBackDing) CallBack(ctx *gin.Context) {
 var dingBody = new(model.DingTalkCallBackBody)
 err := check.ParamsCheck(ctx, &dingBody)
 if err != nil {
  response.ReturnContext(ctx).Failed("fail", err)
  return
 }
 err = service.PrometheusAlert.UpdatePrometheusAlertClaimUsers(dingBody.SenderStaffId, dingBody.Text.Content)
 if err != nil {
  response.ReturnContext(ctx).Failed("fail", err)
  return
 }
 response.ReturnContext(ctx).Successful("success", err)
}

func (pa *prometheusAlert) UpdatePrometheusAlertClaimUsers(userID, uid string) (err error) {
 uid = strings.TrimSpace(uid)
 data, err := db.PrometheusAlert.SelectPrometheusAlert(uid)
 if err != nil {
  return err
 }
 if strings.Contains(data.ClaimUsers, userID) {
  //已经存在该用户了
  common.TPLogger.Info("已经存在该用户了")
  return nil
 }
 userIDs := utils.StringToSlice(data.ClaimUsers)
 userIDs = append(userIDs, fmt.Sprintf("\"%s\"", userID))
 fmt.Println("此时用户ID,", userIDs)
 err = db.PrometheusAlert.UpdatePrometheusAlertClaimUsers(fmt.Sprintf("%s", userIDs), uid)
 if err != nil {
  common.TPLogger.Error("更新认领人失败", err)
  return err
 }
 common.TPLogger.Info("更新认领人成功")
 return nil
}

这里主要功能为接受钉钉的回调事件,并提取userid,发送内容(该内容不用输入,我们使用dtmd功能实现)

  1. 钉钉回调body
代码语言:javascript
复制
{
    "conversationId": "cidkxS5Uphxg1sdgXkltSWi/A==", # 加密的会话ID
    "atUsers": [  # 被@人的信息   dingtalkId:加密的发送者ID   staffId:当前企业内部群中员工userid值。
        {
            "dingtalkId": "$:LWCP_v1:$+av1jFT6ZUh9e10G0DuOSS9MrDOOSiz/"
        }
    ],
    "chatbotCorpId": "xxxxxxxxxxxxxxxxxxxx",  # 加密的机器人所在的企业corpId。
    "chatbotUserId": "xxxxxxxxxxxxxxxxxxxxxxxxx", # 加密的机器人ID。
    "msgId": "xxxxxxxxxxxxxxxxxxxxxxxx",  # 加密的消息ID
    "senderNick": "张行雷",  # 发送者昵称
    "isAdmin": false,  # 是否为管理员
    "senderStaffId": "xxxxxxxxxxxxxxxxxxxxxxxxx",  # 企业内部群中@该机器人的成员userid。
    "sessionWebhookExpiredTime": 1664276341892,  # 当前会话的Webhook地址过期时间 单位ms
    "createAt": 1664270941724,  # 消息时间戳,单位ms
    "senderCorpId": "xxxxxxxxxxxxxxxxxxxxxxxxx",  # 企业内部群有的发送者当前群的企业corpId。
    "conversationType": "2", # 单聊还是群聊 1:单聊  2:群聊
    "senderId": "xxxxxxxxxxxxxxxxxxxxxxxxx",  # 加密的发送者ID
    "conversationTitle": "自动回复机器人调试",   # 群聊时才有的会话标题
    "isInAtList": true, # 是否再@列表中
    "sessionWebhook": "https://oapi.dingtalk.com/robot/sendBySession?session=xxxxxxxxxxxxxxxxxxxxxxxxx",  # 该钉钉机器人的webhook地址
    "text": {
        "content": " 123"  # 消息文本
    },
    "robotCode": "xxxxxxxxxxxxxxxxxxxxxxxxx",
    "msgtype": "text"  # 目前只支持text,消息类型
}

配置Alertmanager

代码语言:javascript
复制
# cat alertmanager-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  labels:
    alertmanager: main
    app.kubernetes.io/component: alert-router
    app.kubernetes.io/name: alertmanager
    app.kubernetes.io/part-of: kube-prometheus
    app.kubernetes.io/version: 0.21.0
  name: alertmanager-main
  namespace: monitoring
stringData:
  alertmanager.yaml: |-
    ## Alertmanager 配置文件
    global:
      resolve_timeout: 1m  # 该参数定义了当Alertmanager持续多长时间未接收到告警后标记告警状态为resolved(已解决)
    # 路由分组
    route:
      receiver: devops  # 默认的接收器名称
      group_wait: 30s # 在组内等待所配置的时间,如果同组内,30秒内出现相同报警,在一个组内发送报警。
      group_interval: 1m # 如果组内内容不变化,合并为一条警报信息,5m后发送。
      repeat_interval: 1m # 发送报警间隔,如果指定时间内没有修复,则重新发送报警。
      group_by: [alertname,instance]  # 报警分组
    # 接收器指定发送人以及发送渠道
    receivers:
    - name: devops
      webhook_configs:
      - url: http://192.168.10.70:8899/api/v1/prometheus/alert
        send_resolved: true
type: Opaque

#  kubectl   apply   -f   alertmanager-secret.yaml

这里的http://192.168.10.70:8899/api/v1/prometheus/alert是我们项目接受告警的地址

触发告警

当我们点击告警认领按钮时会自定艾特机器人,并发送一个消息(消息内容可以自定义,但是需要包含UID,主要是为了区分认领的是那一条告警)

说明:该UID是用告警名称告警级别告警时间告警pod告警名称空间进行md5加密而成的字符串

认领后再次告警

当然认领可以支持多人认领

认领后告警恢复
无人认领告警恢复

告警代码领取方式,可以添加下方二维码

总结

告警认领功能到此已经添加完成,当然其中还有一些地方不够完善的,例如告警静默,告警指派、告警升级等功能,如果有需要后期会慢慢完善。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-08-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云原生运维圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • prometheus架构图
  • 案例介绍
  • 环境概述
  • 快速开始
    • 核心代码
      • 配置Alertmanager
        • 触发告警
          • 认领后再次告警
          • 认领后告警恢复
          • 无人认领告警恢复
      • 总结
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档