我们看到一些国内的 AWS 用户,在使用企业微信和钉钉作为内部工作沟通平台。他们希望将Amazon CloudWatch 接收到的监控、告警信息发送到企业微信和钉钉等即时通讯工具中,方便统一运维。 Amazon CloudWatch 能够直接以邮件、短信的形式发送告警通知,也可以与 AWS Lambda 结合,通过 Amazon Connect 以电话的形式发送告警通知。
在这篇文章中,我们将会介绍如何通过 Amazon SNS 和 AWS Lambda 来实现将 AWS CloudWatch 告警信息发送到微信和钉钉。
CloudWatch 与 SNS、Lambda 配合使用常见流程如下:以上架构中, Amazon CloudWatch 作为事件触发器,当它收到告警信息、定时任务、特定事件发生等事件时,它可以直接触发 AWS Lambda 来执行函数内容。业务将消息推送到 SNS ,由 SNS 来触发后续的操作。如: SNS 触发 AWS Lambda 执行、 SNS 发送邮件/短信通知等。
本方案中 CloudWatch 接收 EC2 运行指标并进行监控。当 EC2 指标超出设定阈值后,CloudWatch 触发告警事件,并将事件消息通过 SNS 发送到 Lambda 函数。Lambda函数执行用户自定义的代码,包括:解析告警消息并发送到企业微信、钉钉机器人、或者 Prometheus 等平台。
架构中 AWS 服务简介:
Amazon CloudWatch 可以用来收集 AWS 包括 EC2 、 RDS 、 EKS 等各种服务运行日志也可以收集用户应用程序日志,可以作为 AWS 上日志数据集散地。同时在 CloudWatch 上可以设置基于指标的告警、基于时间和事件的规则,它可以与 Amazon SNS 和 Lambda 等其他AWS服务进行使用。
AWS Lambda 是无服务器的函数计算服务。通过 AWS Lambda ,无需预置或管理服务器即可运行代码。借助 Lambda ,您几乎可以为任何类型的应用程序或后端服务运行代码,而且完全无需管理。您可以将您的代码设置为自动从其他 AWS 服务如: CloudWatch 、 SNS 等触发,或者直接从任何 Web 或移动应用程序调用。
Amazon SNS 是一项用于应用与应用之间以及应用与人之间通信的完全托管型消息收发服务。
3.创建完成后记录应用 Secret
企业微信告警流程
a) 获取 access_token ,参考微信官方说明文档
示例代码:
tokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
def get_token():
values = {'corpid': ''<corpid>'', 'corpsecret': '<'corpsecret'>'}
req = requests.post(tokenUrl, params=values)
data = json.loads(req.text)
return data["access_token"]
b) 缓存和刷新 access_token
c) 调用具体的业务接口
示例代码:
sendMsg = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
def send_msg(msg):
url = sendMsg + get_token()
print(url)
values = """{"touser" : "<成员ID列表>" ,
"msgtype":"text",
"agentid":"<企业应用ID>",
"text":{
"content": "发送的告警内容!"
},
"safe":"0"
}"""
requests.post(url, values)
配置 Lambda 环境变量
新建 corpid 和 corpsecret 环境变量,根据从企业微信获取的值填充。
为Lambda添加触发器:选择上一步创建的SNS作为触发器
新建函数文件lambda_function.py
,内容如下:
#from botocore.vendored import requests
import requests
import json
import os
tokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
corpid = os.getenv('corpid')
corpsecret = os.getenv('corpsecret')
def get_token():
values = {'corpid': corpid, 'corpsecret': corpsecret}
req = requests.post(tokenUrl, params=values)
data = json.loads(req.text)
return data["access_token"]
sendMsg = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
def send_msg(msg):
url = sendMsg + get_token()
print(url)
values = """{"touser" : "@all" ,
"msgtype":"text",
"agentid":"<微信应用agentid 替换>",
"text":{
"content": "%s"
},
"safe":"0"
}""" % msg
requests.post(url, values)
def lambda_handler(event, context):
Message = json.loads(event['Records'][0]['Sns']['Message'])
OldStateValue = Message['OldStateValue']
NewStateValue = Message['NewStateValue']
Timestamp = event['Records'][0]['Sns']['Timestamp']
NewStateReason = json.loads(event['Records'][0]['Sns']['Message'])['NewStateReason']
msg = "Alarm Details:\n"+"State Change:"+OldStateValue + " -> " + NewStateValue + "\n" \
"Timestamp:" + Timestamp +"\n" \
"Reason for State Change:" + NewStateReason
print(msg)
send_msg(msg)
本例中使用 python requests 库发送 post 请求,目前有两种办法实现:
python3 -m venv v-env
source v-env/bin/activate
pip install requests
deactivate
cd v-env/lib/python3.7/site-packages
zip -r9 ${OLDPWD}/function.zip .
cd $OLDPWD
zip -g function.zip lambda_function.py
选择要监控的 EC2 监控选项卡,创建警报。(下图是中国区控制台界面, AWS Global 控制台界面略有不同)
给 EC2 增加负载观察 CloudWatch 指标变化和告警情况
如上图所示, CPU 利用率已经超过设定阈值, CloudWatch 发出告警。
在 CloudWatch 日志组中查看 Lambda 日志
在接收告警信息的钉钉群中添加机器人,以下设置内容同钉钉官方说明:
按照以下步骤添加自定义钉钉机器人并获取 Webhook 地址。
5. 在机器人详情对话框单击添加。
6. 在添加机器人对话框中编辑机器人头像和名称,选中必要的安全设置(至少选择一 种),选中我已阅读并同意《自定义机器人服务及免责条款》。单击完成。
同上述配置企业微信告警 SNS 过程。
创建Lambda与上述配置企业微信过程基本相同,建议独立安装 requests 包并上传。 Lambda函数内容略有区别。创建钉钉告警 Lambda 环境变量和代码如下:
import requests
import json
def send_msg(msg):
token = '16a9f365c63bca077649fa06760b73123a9047e678a984926f433cdeec1292ab'
#token = os.getenv('token')
url = "https://oapi.dingtalk.com/robot/send?access_token="
url = url + token
headers = {'Content-Type': 'application/json'}
print(url)
values = """{
"msgtype":"text",
"text":{
"content": "%s"
}
}""" %msg
print(values)
request = requests.post(url, values,headers=headers)
return request.text
def lambda_handler(event, context):
Message = json.loads(event['Records'][0]['Sns']['Message'])
OldStateValue = Message['OldStateValue']
NewStateValue = Message['NewStateValue']
Timestamp = event['Records'][0]['Sns']['Timestamp']
NewStateReason = json.loads(event['Records'][0]['Sns']['Message'])['NewStateReason']
msg = "Alarm Details:\n"+"State Change:"+OldStateValue + " -> " + NewStateValue + "\n" \
"Timestamp:" + Timestamp +"\n" \
"Reason for State Change:" + NewStateReason
print(msg)
send_msg(msg)
测试方法同微信告警。给 EC2 增加负载(可以参考命令进行测试:for i in `seq 1 $(cat /proc/cpuinfo | grep “processor” | wc -l)`; do dd if=/dev/zero of=/dev/null & done),观察CloudWatch指标是否超过告警阈值。以下分别是钉钉告警 CloudWatch 日志和钉钉 app 接收到的告警信息示例。
Amazon CloudWatch 作为AWS平台上告警和监控信息的集散地,将它与 SNS 、 Lambda 配合,利用 AWS Lambda 函数计算服务灵活的特点,可以将 AWS 服务的监控和告警信息轻松发送到微信、钉钉、 Zabbix 等第三方系统,实现自定义监控告警。
本文转自AWS官方博客《企业微信、钉钉接收 Amazon CloudWatch 告警》