亚马逊AWS官方博客
通过 EventBridge+SNS+Lambda 实时捕获EMR集群的状态变化
摘要
Amazon EventBridge(以前名字为CloudWatch Events)是一种无服务器的事件总线,通过它可以实时获取运行在亚马逊云上的服务生成的事件,也支持集成用户自己的应用程序或软件即服务的事件,轻松的管理大规模的事件驱动程序,减少运营的复杂度和开销。
Amazon EMR是行业领先的云上大数据平台,支持使用多种开放源代码工具处理大量数据,如Spark、Hive、HBase、Flink、Hudi 和 Presto等。Amazon EMR 通过定义弹性伸缩策略可以自动(或人工)快速的在云上构建大规模的数据处理和分析平台。
通过结合EventBridge、消息主题(SNS),以及按事件调用触发的无服务器函数Lambda,可以实时捕获EMR集群的生命周期变化,如集群的创建和停止,扩容和缩容以及其他类型的集群状态变更等。
本文演示如何捕获EMR集群状态变更(我们以AWS的新加坡区域为例)并发送到当前常用的“企业微信”和“钉钉”手机客户端,其他AWS服务场景请酌情参考。
关键字
Amazon EventBridge,Amazon EMR,Amazon SNS,AWS Lambda,Amazon CloudWatch,CloudWatch Events,事件总线,无服务器计算,事件通知,企业微信,钉钉
架构设计
这是我们设计的EMR实时状态获取架构图,从图上可以看出,当EMR发生状态变更时(如启动集群,停止集群,对集群进行扩缩容操作等),系统会产生事件(此处我们称呼它为告警),事件消息送到SNS主题后会触发我们准备好的Lambda无服务器函数,从而解析JSON格式的消息内容并发送给“企业微信”和“钉钉”手机客户端(客户也可以基于公司内部的聊天工具进行集成,或者定义下一步的操作,从而实现基于事件的自动化告警处理和运维等,关于这一块,本博客暂不做延展说明)。
图例:实时状态获取架构图
EventBridge配置
定义SNS主题
登录AWS控制台,选择新加坡区域(注意后续操作都是在同一个区域),打开SNS的控制台(点击这里),然后选择创建主题,选择类型为“标准”,输入名字为“emr-status-change”(建议选择望文生义的名字),其他全部默认,如下所示:
图例:SNS主题定义
定义EvengBridge触发动作
打开CloudWatch的控制台(点击这里),选择左侧菜单的“事件”下面的“规则”,然后在右边的窗口中选择“创建规则”,如下图所示:
图例:创建EventBridge规则
在创建规则页面,服务名称选择“EMR”,事件类型选择“所有事件”,然后选择“添加目标”,选择“SNS主题”并选中刚才创建的主题“emr-status-change”,然后点击右下角的“配置详细信息”,如下图所示:
图例:规则详细定义
我们把规则也取名为“emr-status-change”并保存即可。
图例:创建并保存规则
企业微信和钉钉配置
企业微信的应用配置
登录企业微信控制台以后,在顶层菜单的“我的企业”页面中的“企业信息”中获得企业ID(记录下来)。
在顶层菜单的“应用管理”页面中的“应用”中,选择“自建”里面的“机器人”后面的“创建应用”,然后选择一个应用的图片,设置应用名称(例如此处为awsemr),然后选择可见范围(这是选择哪些人或者哪个群组可以看到的作用域),然后点击“创建应用”,如下所示:
图例:创建企业微信应用
创建好应用以后,会出现对应的AgentId(记录下来)和Secret(记录下来),如下图所示:
图例:成功创建应用
要往企业微信发送消息,需要三个参数,分别是(我们已经在上面步骤分别获得):
- 企业ID:例如“aQ6eb12349f“,对应Lambda环境变量wx_ent
- AgentId:例如“1000002”,对应Lambda环境变量wx_ak
- Secret:例如“G_1b56789Cw123456789be”,对应Lambda环境变量wx_sk
钉钉的Webhook配置
因为安全的原因(官方说法),配置钉钉群机器人必须使用电脑版的钉钉,所以登录电脑版钉钉以后,创建钉钉群(用手机客户端也可以,此过程略,例如创建后的群名为awsemr),然后点击群右上角的“设置”,然后点击“智能群助手”,如下图所示:
图例:智能群助手管理
图例:添加群机器人
在弹出的页面中继续选择“添加机器人”,然后选择“自定义”(通过Webhook接入自定义服务),系统会出现机器人详情提醒,点击“添加”,机器人配置如下:
- 名字:群通知,这个会显示在群聊里面的名称
- 安全设置:此处我们使用关键字(消息里面带关键字才能正确发送),因为我们的提醒消息都会带上日期和时间,例如今年是2021年,所以肯定会有202
图例:添加群机器人详细配置
在接下来的页面中会出现一个Webhook调用的URL,点击“复制”,类似如下
https://oapi.dingtalk.com/robot/send?access_token=54b12345678907f5875a1234567890330d601234567890241039a93ec5915e52
后面我们设置环境变量的时候将用到这一串,对应Lambda环境变量dd_sk
54b12345678907f5875a1234567890330d601234567890241039a93ec5915e52
图例:获得对应Webhook地址
Lambda配置
如果前面的配置跟我们的文档完全一致的情况下,可以直接不做任何修改的部署Lambda代码即可(主要代码文件“lambda_function.py”,基于Python 3.7实现的,如果有别的需求,例如打印更多日志到CloudWatch,可以直接修改此文件的代码即可)。
创建Lambda函数
打开Lambda的控制台(点击这里),选择“创建函数”,类型选择“从头开始创作”,名称为“emr-status-change”,运行时选择“Python 3.7”(作者是基于这个版本开发的),如下图所示:
图例:创建Lambda函数
配置Lambda环境变量
创建好函数以后,点击“配置”选项页,然后选择“环境变量”,我们需要定义6个环境变量,分别如下(注意大小写):
名称 | 值 | 说明 |
dd_flag | Y | Y表示发送钉钉消息,其他不发送 |
dd_sk | 钉钉的webhook的url串 | “access_token=”后面的部分 |
wx_flag | Y | Y表示发送微信消息,其他不发送 |
wx_ak | 企业微信的AgentId | 如1000002 |
wx_sk | 企业微信的Secret | |
wx_ent | 企业微信的企业ID |
图例:Lambda环境变量配置
配置Lambda触发
打开Lambda的“函数概述”页面,点击左边的“添加触发器”,类型选择“SNS”,具体的主题选择之前创建的“emr-status-change”,添加后如下图所示:
图例:Lambda触发配置
配置Lambda代码
打开Lambda的“代码”页面,选择“上传自”,然后选择Amazon S3位置,如下图所示:
图例:选择直接从S3上传代码
其中代码的详细地址如下(也可以手工下载此文件,然后从本地上传):
https://s3-ap-southeast-1.amazonaws.com/files.bwcx.me/eventbridge/emr/function.zip
图例:输入代码位置保存代码
保存过程会自动部署,如果没有报错,表示部署成功。
测试验证
打开EMR的控制台(点击这里),部署一个最小的EMR集群(如就1个Master节点的)即可(过程略)。
正确返回
因为我们配置了所有的EMR事件都通知,所以很快我们的手机客户端就可以收到类似如下的消息提醒(集群状态由STARTING-> RUNNING->WAITING):
图例:正常提醒(左边企业微信,右边钉钉)
错误诊断
如果启动集群过程中并没有收到对应的提醒,请首先确认对应的环境变量是否配置正确,然后我们可以打开CloudWatch控制台(点击这里),选择左侧的菜单“日志”下面的“日志组”,然后找到对应Lambda函数名的日志组(例如此处为“emr-status-change”),即可看到对应的日志流,如下所示(Lambda运行出错日志以及我们在代码里面的print日志都会输出在这里):
图例:Lambda日志流
如果有Lambda运行异常(例如发送消息给企业微信出错,或者解析JSON数据格式异常),会有错误提醒(如下图所示的日志表示一切运行正常):
图例:详细的Lambda日志
扩展
经过上面的文档指引和动手实验,我们基于EMR集群的生命周期管理(如集群创建,停止,集群扩缩,缩容等)都会有对应提醒,其实只需要修改文件“lambda_function.py”里面对应的解析的JSON文件的内容,这个流程可以复制到别的场景,例如EC2的相关操作。
如在我们的EventBridge(CloudWatch规则)里面配置ec2-status-change的类型为如下三种即可实现EC2的“启动”,“停止”,“终止”的提醒,客户在实际场景中可以根据三种不同的告警内容实现更多的自动化的运维动作(注意解析的JSON的格式的不同,在下图的左下角的“显示示例事件”里面有JSON提醒的样例供程序开发和调试使用。
图例:扩展到EC2的场景
细心的读者可能会发现,其实我们在配置规则的时候可以直接送到Lambda,为什么还要加入SNS呢,其实这是一个消息扇出的选项,通过SNS可以把一个消息发送给N个接收者,例如邮件,队列,或更多的Lambda函数等。
熟悉了这一套操作流程后,期待我们的读者能够在更多的场景使用上这些功能(不一定必须得是企业微信和钉钉的提醒,也可以是更多API层面的对接和自动化运维等对接)。