说明

Amazon CloudWatch是亚马逊云上的统一监控平台,实现对云上所有资源的监控。Amazon CloudWatch Alarm可以基于Amazon CloudWatch Metrics里面的指标,根据自定义的规则触发警报。通过集成Amazon SNS和Amazon Lambda,可以实现邮件、短信、企业微信、钉钉、飞书等多种方式的通知。

但是,Amazon CloudWatch Alarm仅会在警报从【正常】状态转变为【告警】状态时触发一次警报。此后,即使警报仍然处于【告警】状态,也不会有新的通知产生。

本文将介绍,如何基于无服务器函数编排工具Amazon Step Functions,在警报被触发后轮询警报状态,实现持续报警的效果,以强调警报的存在,确保您系统中的问题可以得到足够的重视。

架构图

本方案包含如下组件:

Amazon CloudWatch持续报警

组件说明:

(1)根据自己的需要,创建Amazon CloudWatch Alarm。

(2)Amazon CloudWatch Alarm会通过Amazon EventBridge,触发Amazon Step Functions工作流

(3)Amazon Step Functions工作流的具体内容见下文。工作流中会包含以下两个函数:

HandleAlarm:自定义的警报处理函数,用来实现通知逻辑。

CheckAlarm:下文会创建警报状态检查函数,用来判断是否继续发出通知。

部署流程

我们需要创建三个Lambda函数,一个状态机

创建Lambda函数 Alarm_FeiShu

创建一个Lambda函数,命名为Alarm_FeiShu报警函数,核心源码lambda_function.py,需要注意的是python运行时使用更高版本的Python3.9,如下:

Amazon CloudWatch持续报警

上传zip代码包:

Amazon CloudWatch持续报警

创建Lambda函数 CheckAlarm

创建一个Lambda函数,命名为CheckAlarm,使用Amazon SDK检测警报状态。使用Python 3.9作为runtime创建此函数,核心源码详见lambda_function.py

Amazon CloudWatch持续报警

此函数需要调用cloudwatch:DescribeAlarms API,所以需要为此函数所使用的IAM Role添加此权限。

# 角色命名
CheckAlarmRole
# 附加权限
CloudWatchReadOnlyAccess

Amazon CloudWatch持续报警

Amazon CloudWatch持续报警

此函数会自动从event参数中解析出警报的名称。最终返回值为OK/ALARM/INSUFFICIENT_DATA/ERROR中的一个。

创建Lambda函数 Alarm_FeiShu_Response

创建一个Lambda函数,命名为Alarm_FeiShu_Response报警恢复函数,核心源码lambda_function.py,需要注意的是python运行时使用更高版本的Python3.9

创建Amazon Step Functions

使用如下内容创建Step Functions工作流即状态机,详见Functions_state_machine.json

Amazon CloudWatch持续报警

需要把上述文档中的如下内容进行替换:

  • <AlarmHandler>: 响应警报的Lambda函数的ARNAlarm_FeiShuAlarm_FeiShu_Response。需要自行创建此函数,并在里面实现通知/处理逻辑。

  • <CheckAlarm>: 刚才创建的CheckAlarm函数的ARN

默认创建Step Functions,那么轮询周期为5分钟(300秒)。可以通过修改文档中的下述内容来修改轮询周期:

"Wait": {
      "Type": "Wait",
      "Seconds": 1800, // 修改这个值,单位为秒,这里修改为30分钟
      "Next": "CheckAlarm"
},

上述文档会创建如下状态机:

Amazon CloudWatch持续报警

当警报状态改变,触发此状态机时,会顺序执行下述操作:

(1)警报的状态是否是ALARM。如果不是,则调用Alarm_FeiShu_Response函数,最后跳转到Pass状态并结束状态机;

(2)调用Alarm_FeiShu函数,根据自定义的逻辑发出通知;

(3)进入Wait状态,等待一段时间;

(4)调用CheckAlarm函数,判断警报状态:

  • 如果函数返回OK,即警报已经恢复正常,则进入Pass 状态并结束状态机

  • 如果函数返回ALARM,即警报仍然在告警,则回到步骤1

  • 如果函数返回其他值,视为故障并进入Fail状态,结束状态机

此状态机的两个Lambda函数都在InputPath中引用了$$.Execution.Input变量,使它们即使被多次触发,或者在循环中被触发,也会有一致的输入值。

创建报警

我们需要创建cloudwatch报警规则,对应创建Amazon EventBridge --> 个规则,个规则中指定我们上面创建的状态机,以使它们之间可以联动起来。

配置CloudWatch警报

根据需求,创建CloudWatch警报。此方案会使用EventBridge触发Step Functions,所以它在创建的时候不需要配置任何通知。删除所有的通知,并直接点击Next。

Amazon CloudWatch持续报警

创建完毕后,复制EventBridge规则:

Amazon CloudWatch持续报警

配置EventBridge规则

创建EventBridge规则,目标为刚才创建的Step Functions状态机,规则配置步骤:

Amazon CloudWatch持续报警

建议:规则名字与报警名字保持一致

Amazon CloudWatch持续报警

说明示例事件-可选可不用填写

Amazon CloudWatch持续报警

说明输入事件JSON即为上面提到的EventBridge规则

Amazon CloudWatch持续报警
建议:执行角色使用创建新角色

至此,每当警报状态发生改变的时候,状态机就会被触发。如果警报的状态为【报警中】,状态机就会发出持续通知。

报警信息示例

Amazon CloudWatch持续报警

报警恢复示例

Amazon CloudWatch持续报警

补充状态机运行状态

当报警被触发后不到Wait规定的循环检查时间,该报警就恢复了,此时状态机运行逻辑如下:

Amazon CloudWatch持续报警

当报警被触发后,经过Wait规定的循环检查时间后报警恢复,此时状态机运行逻辑如下:

Amazon CloudWatch持续报警