适用于中小型企业自研的监控告警通知系统(附源码)

背景

监控告警是运维包括开发的杀手锏,目前存在太多的告警通知方式,微信,邮件,短信,甚至机器人等等。那么我们如何把想要的通知快速而准确的通过这些渠道发送呢?今天就分享一个整合这些渠道的通知系统。
(注:本人不是开发出身,所以这个系统是我闲暇时刻自学编写的,可能代码质量和规范上不如真正的开发,但是这个系统也是我平时运维中用的比较多的告警通知手段。希望能帮助到大家,有任何问题的同学可以联系我,欢迎批评指正!)

文章导读

监控告警是运维包括开发的杀手锏,目前存在太多的告警通知方式,微信,邮件,短信,甚至机器人等等。那么我们如何把想要的通知快速而准确的通过这些渠道发送呢?今天就分享一个整合这些渠道的通知系统。

交流: 如果对该篇文章或者代码有任何疑问的同学,可以添加本人微信号:sicau_libin,欢迎随时交流!

常用的告警方式

就目前来说,我已经接触到大部分告警通知方式了,那么这些告警方式都有哪些优缺点呢?让我们来简单谈谈吧。

  • 邮件:他最基础的告警,简单,但是实时性并不是很高(比如我就很少看邮件)
  • 短信:短信算是一个比较常用的告警方式,实时性高。不过不免费,虽然也不是特别贵,另外一点当告警收敛做的不够好的时候可能会造成打扰休息。
  • 电话:这种是一个最高等级的通知方式,一般非常紧急的告警会采用这个,能够让人第一时间去介入问题的处理。
  • 企业微信:这个针对性比较强,适合用企业微信的公司,当然个人账号也是ok的。定制性和实时性都比较好,推荐使用。
  • 企业微信机器人:比较灵活,相对企业微信应用来说,我认为最大的优点就是比较好玩,我经常用机器人做一些定制化需求和定时任务通知等。
  • 钉钉机器人:针对性较强,跟企业微信机器人类似。

大家还有使用到哪些告警方式,欢迎交流!

如何设计一个告警系统

我们公司有专门一个监控告警团队在做这一块,我作为业务运维,平时可能就是使用上会多点,所以我的观点不一定准确,仅仅是我个人的一些看法和建议。

  • 告警实时性
  • 告警准确性
  • 告警可读性
  • 告警统一性
  • 告警追溯性
  • 告警定制型
  • 告警收敛(尤为重要)

告警实时性

  • 告警必备条件之一,实时性。我们不可能等故障已经发生了十分钟后,才收到告警,这样是毫无意义的,告警一定要在用户发现问题之前发到我们手上,并且能够让我们快速定位问题,解决问题。
  • 目前做的好的告警,已经实现了预警,就是还未发生告警,但是已经有告警的趋势,他会提前通知出来。
    举个简单的例子:我的磁盘使用率在持续增长,不过在前一个小时,这个增长速率变快,方差变大,那么这时候就要考虑是否是业务量级上涨,导致我的磁盘已经不满足需求,需要扩容。

    告警准确性

    这个比较好理解,出现告警一般是需要我们及时去处理的,那么就要求这个告警真实有效。
    举个例子:凌晨两点出现宕机告警,那么我们可能需要紧急来处理,如果这个告警是误报,那么这种就严重影响休息了。

    告警可读性

    简单来说,就是你发出来的告警能让人看懂,并且能够快速定位到问题点。
    举个例子,一条5xx告警,它需要体现哪些信息呢?
    答:告警标题,谁出错了,错误信息是什么,错误占比是多少,是在哪里出现错误了(那台机器上),什么时候告警,哪个接口告警了,更甚至是给出一些告警解决的建议等等。

    告警统一性

    这个统一性有几个方面,第一告警平台的统一性;第二告警方式的统一性。
  • 关于告警平台的统一性。一家公司一定要有一个统一告警平台。说简单点就是所有的告警必须由一个地方发出来。为什么说这点呢?因为就现状而言,三个人中,可能有三种不同的告警发送出路,你写一个脚本监控这个,他撸一个平台监控这个,告警满天飞,不仅湮灭了有效告警,还带来不小的成本开销。
  • 关于告警方式的统一性。一般来说,我们会给告警划分等级,不同等级的告警采用不同的方式,一般告警用微信邮件方式,紧急告警用短信方式,最高等级告警直接电话(比如我们公司的机器宕机就是通过电话方式告警的)。

    告警追溯性

    这个比较好理解,简单来说就是我能够在几天之后查到这个告警,虽然这个用监控系统来体现会更好,不过这个也是不可或缺的。

    告警定制性

    正如可读性中提到的5xx告警,我们其实还有很多很多的告警,那么我们需要定制不同的模板,但是现实肯定是有个别差异的,所以定制的存在是必须的。
    举个例子,我们的A服务跑在aws上,B服务跑在gcp上,我们就需要定制了。第一aws和gcp的监控数据是不同的,所以我们得到的数据指标不一定完全吻合,所以需要定制化监控项。第二gcp存在墙的问题,那么我们如何拿到监控数据以及把告警发回来,又是需要单独定制的。

    告警收敛

    这个为什么我标志成尤为重要呢,是因为我现在每天收到的告警有几千条,其中包括邮件、短信、企业微信应用、企业微信机器人等等。那么会带来一个非常严重的问题,我不知道该去处理哪个告警,甚至会覆盖掉我需要优先处理的告警。

讲解我撸的告警通知系统

注意:由于最近一些工作上的事情,其他方式我暂时没有太多时间撸,另外一个是短信和电话采用的三方应用不同,所实现的代码也不同,所以没办法做到统一,不过我后续会更新一版比较常用的短信和电话提供商代码。

项目介绍

这个告警通知系统我自己取名潘多拉,代码我已经做了脱敏放到 github 上了,告警通知,有需要的通知可以去获取(有不会使用的通知可以加我微信,我可以为你单独讲解一下)
下面是 tree :
filelist
通过 tree 可以很清晰明了的看到这个系统的简单性,不过对于重要公司其实已经够用了,或者你也可以定制自己的功能,尽管pr就好。

项目地址

  • GitHub
    1
    https://github.com/gsgs-libin/Pandora

    如何运行

    目前有两中方式可以运行该项目:
  • 直接运行
    依赖:需要你本地有python环境,装好gunicorn
    1
    2
    3
    4
    git clone https://github.com/gsgs-libin/Pandora.git
    cd Pandora
    pip install -r requirements.txt
    gunicorn NoticeSystem:app -c gunicorn.conf
  • 容器化运行
    依赖:本地需要装好docker或者k8s
    1
    2
    构建镜像:docker build -t pandora:dev-1.1.1-1 .
    运行容器:docker run --name pandora -p 5001:5001 pandora:dev-1.1.1-1

ps:系统默认暴露5001端口,可以自行修改NoticeSystem.py中的port参数

企业微信应用模块说明

要求:

  • 有企业微信账号
  • 创建一个企业微信应用
申请账号

企业微信账号使用微信账号申请,这个就不细说了,非常简单,一步一步点就好了。

创建企业微信应用

createapp

获取秘钥,修改下载的代码

修改代码文件中的./utils/secret.py:

1
2
3
4
5
6
7
8
9
QYWXAPPKEY = {
"WX_CORPID":"图1获取",
"APPSecret":{
"SREAlert":{
"appsec":"图2获取",
"agentid":"图2获取"
}
}
}

图1:
getqyid
图2:
getsecret

调用测试
1
curl 0.0.0.0:5001/send_qywx_app -H "HTTP_VERIFICATION_KEY:5hbfJTAo9SBOb" -X POST -d "{'AppName':'SREAlert','Content':'测试企业微信应用告警'}"

企业微信机器人模块说明

需求:

  • 企业微信客户端
  • 任意一个群聊
创建一个机器人

任意选择一个群聊,右键点击选择创建一个机器人,填写好机器人的名字就能创建一个测试机器人了。
create_qywx_robot

获取机器人秘钥

秘钥样例,我们只需要取地址对应key的值:

1
https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=**********
修改代码,填写key

修改文件utils/send_qywx_robot.py,填写上对应的key即可

1
2
3
4
RobotKeyList = {
"lb6test1":(('key','********************'),),
"lb6test2":(('key','********************'),),
}
测试调用
1
curl 0.0.0.0:5001/send_qywx_robot -H "HTTP_VERIFICATION_KEY:5hbfJTAo9SBOb" -X POST -d "{'RobotKey':'lb6test1','Content':'测试','MesgType':'markdown'}"

邮件模块说明

需求:

  • 任意邮箱
  • 得到smtp信息
注册邮箱

任意邮箱即可,我这边直接选择网易163的。

获取smtp信息

从这里可以获取到网易的smtp信息

修改代码,填写smtp信息

修改文件utils/secret.py,替换如下内容:

1
2
3
4
5
6
EMAILSEC = {
"EMAIL_SMTP_SERVER": "smtp.163.com:465",
"EMAIL_USER": "xx@163.com",
"EMAIL_PASSWORD": "******",
"EMAIL_SENDER": "xx@163.com"
}
运行测试
1
curl 0.0.0.0:5001/send_mail -H "HTTP_VERIFICATION_KEY:5hbfJTAo9SBOb" -X POST -d "{'ReceiverList':'a@gmail.com,b@163.com','Subject':'测试主题','Content':'测试邮件内容2'}"
关于邮件标题的修改

有点可以自定义标题,我们直接修改utils/send_mail.py文件:

1
2
3
4
5
6
7
8
9
10
11
12
def SendEmail(receiver_list,subject,content):
sender = EMAILSEC["EMAIL_SENDER"]
subject = subject
smtpserver = EMAILSEC["EMAIL_SMTP_SERVER"]
msg = MIMEText(content, 'html', 'utf-8')
msg['From'] = formataddr((str(Header('【Alert】XX运维告警系统', 'utf-8')), sender))
msg['Subject'] = Header(subject, 'utf-8')
msg['To'] = receiver_list # 字符串
smtp = smtplib.SMTP_SSL(smtpserver)
smtp.login(EMAILSEC["EMAIL_USER"], EMAILSEC["EMAIL_PASSWORD"])
smtp.sendmail(sender,receiver_list.split(','), msg.as_string())
smtp.quit()

告警效果图

邮件

mail

企业微信应用

qywxapp
qywxapp

企业微信机器人

qywxrobot