zabbix之报警发送填坑

368 查看

通常zabbix告警主要可以通过三种方式

1. 自带的直接调用消息接口服务
2. 执行自定义脚本发送消息
3. 通过send remote commend 的方式通过执行脚本发送

2和3的本质都只通过zabbix的action去调用执行服务器上的脚本来发送,报警信息通过在执行脚本后带参数传进去。
这个流程很容易跑通, 也非常的简单可靠。 但是,规模稍大报警量一多,问题立马就显现出来了。

* 报警阻塞,发送效率低下
    * 这种情况下, 报警是根据用户一个个用户发送。 也就是说, 如果这个报警有十个收件人,那要分到触发十次发送脚本来实现发送。
    * 并且这个发送还是线性的不是多线程的, 要等上一个发送完了, 再接着发送下一个。报警稍微多一点或者收件人稍微多一点, 这个报警的延迟就很大了。

* 风暴控制 
    * 网络抖动是个大坑, 通过proxy的可以通过依赖来实现一定的风暴控制, 但是直接通过服务器监控的就很难做了

    * 一旦风暴, 很难退出。 如果sever到某个直连的idc 间网络一抖动, 触发大量报警,只能等action 执行完

* action 维护麻烦, 这种模式下, 报警匹配发送给谁有 action来决定,有多少种组合就会有多少个action, 会导致 action的数量很多维护起来相当麻烦
* 报警配置维度单一: 例如 业务dba 仅只想接受业务相关报警, 不想接受机器层面的报警, 看似简单的需求配置起来会很麻烦甚至难以实现
* 报警信息单一: 比如要给报警内容里加上一个负责人,方便escalation后直接联系直接负责人都挺麻烦。

为了解决以上问题, 我设计了smail 1.0来解决

smail 有规则解析和风暴控制两个模块组成

规则引擎:
    *  规则引擎直接定了一个规则语法, 主要实现支持从 设备名字和触发器名字两个维度来匹配报警, 对于符合匹配规则的报警则发给对应规则的收件人, 匹配规则支持正则:
    * 匹配规则支持正则表达式
    * 判断故障级别, 根据级别确认发送短信微信还是邮件
风暴控制:

    * 风暴控制通过报警发送数量计数,对单位时间内发送数量超过一定数量则触发风暴控制, 停止发送报警。

效果:

1. 极大的简化了报警配置, 仅配置了两个action。 规则引擎直接使用yaml 配置文件和正则配置方法, 对于 python栈的维护人来非常顺手。
2. 发送效率提高,对于一个报警, 无论发送人数多少, 都只需要触发执行一次脚本。
3. 报警的可追溯,日志详细的记录了报警的发送情况
4. 同时,对报警也加入了更多的信息, 更加方便接受者判断

这时报警邮件就变成了这个样子

可是依旧存在的问题:

1.  发送效率依旧不高, 通过 os.fork  action 依旧要等执行完后再执行下一个未能实现异步。
2.  通过简单计数的风暴控制机制基本没用

2.0 版:
主要以解决发送效果为目标。 主要是引入异步任务队列来实现发送的异步,分离action 触发脚本加快 action的执行速度。

实际动手过程中发现, 如果要引入mp或者 celery这样的 task queue会新增两个damon,这样反而增加了复杂度。

后面直接使用了下图这样的简单粗暴的方法来实现

triggers action 执行的脚本直接插入的zabbix mysql (单独建了一张表);然后通过crontab定时读取(一分钟)mysql获取报警。
风暴控制通过判断这一分钟里的报警同类的条数来判断

效果:

1. 极大的提高了action的执行效率, 实际应用过程中, 即使出现报警风暴, 发送依旧没有什么问题。
2. 因为action的执行效率的提高, 风暴控制有了一定的效果。

TODO:

1. 报警信息跟cmdb里的信息关系, 实现无配置或者少量配置
2. 更有效的风暴控制方式