监控 AWS 的 RDS 并通过企业微信来报警

引言

监控在云资源管理中占据了核心地位,它可以帮助我们实时追踪资源状态,从而快速发现并处理潜在的问题。本文将介绍如何利用 AWS CloudWatch 监控云数据库服务RDS,并通过企业微信发送报警通知,以达到高效运维的目的。

解决方案概述

本文所述的监控方案包含以下几个关键步骤:

  • 设定 CloudWatch 告警规则,用于监控 RDS 参数并定义报警条件。
  • 创建一个 SNS(Simple Notification Service)主题来接收 CloudWatch 的报警通知。
  • 开发一个 Lambda 函数,用于处理 SNS 的报警通知,并将其转发到企业微信。
  • 设置 SNS 主题触发的 Lambda 函数,以启用自动报警功能。

这里有个知识点需要了解,否则就会有困惑:RDS 的 event 是怎么到 CloudWatch 里去的呢?是这样的,RDS 基础的 Metrics 是会自动打到 CloudWatch 里去的。所以我们如果只是监控这些基础的 Metrics 的话是不用在 EventBridge 里再建规则把 RDS 的 event 打到 CloudWatch 里了。

开始之前:在企业微信中创建机器人并获取 Webhook Token

在设置 AWS CloudWatch 监控和报警之前,我们需要先在企业微信中创建一个机器人,并获取它的 Webhook Token,后续步骤中将会用到。以下是创建机器人的操作步骤:

  • 登录企业微信,并打开目标群聊。
  • 点击群聊信息页面内的“群机器人”选项,跟随提示操作,点击“添加”按钮。
  • 弹出页面中选择“新建”。
  • 在新界面中设定机器人的名称,并可选择一个头像。
  • 创建机器人后,系统会生成一个 Webhook URL,这个URL中包含了Token。
  • 复制这个 Webhook URL,注意妥善保存,后续配置中会用到。

配置完成后,记得将获取到的 Token 添加到 AWS Lambda 的环境变量 WX_TOKEN 中。

方案具体实施步骤

在获取了企业微信机器人的 Webhook Token 后,就可以开始设置我们的监控和报警系统了。该系统分为以下几个步骤:

设立 CloudWatch 报警规则

首先,我们需要在 CloudWatch 中为 RDS 创建告警规则。具体步骤(以 Metric: CPUUtilization 为例)如下:

  • 登录 AWS 管理控制台,进入 CloudWatch 服务。
  • 在左侧菜单中选择 “告警” > “所有告警”,然后点击 “创建告警”。
  • 选择要监控的 RDS 指标,例如 “CPUUtilization”(CPU 使用率)。
  • 设置告警阈值和条件,例如当 CPU 使用率超过 80% 时触发告警。
  • 选择 “通过 SNS 主题发送通知”,然后选择之前创建的 SNS 主题。
  • 设置告警名称和描述,然后点击 “创建告警”。

接下来,按照 AWS 官方关于监控的最佳实践 的说法,我们还需要继续监控如下几个 Metrics: DatabaseConnections, EBSByteBalance%, EBSIOBalance%, FreeableMemory, FreeLocalStorage, FreeStorageSpace, MaximumUsedTransactionIDs, ReadLatency, ReplicaLag, WriteLatency, DBLoad, AuroraVolumeBytesLeftTotal, AuroraBinlogReplicaLag, BlockedTransactions, BufferCacheHitRatio, EngineUptime, RollbackSegmentHistoryListLengthStorageNetworkThroughput,注意:这些 Metrics 不一定都同时都有的,没有的自然就跳过就好了。

创建 SNS topic

接下来,我们需要创建一个 SNS 主题,用于接收 CloudWatch 的告警消息。具体步骤如下:

  • 进入 SNS 服务,点击 “创建主题”。
  • 输入主题名称和显示名称,然后点击 “创建主题”。
  • 记下主题的 ARN(Amazon Resource Name),后面会用到。

编写 Lambda function

现在,我们来编写一个 Lambda 函数,用于解析 SNS 消息并发送到企业微信。以下是 Python 代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import json
import os
from http.client import HTTPSConnection

def lambda_handler(event, context):
qywx_robot_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key="
token = os.environ['WX_TOKEN']
send_url = qywx_robot_url + token
headers = {
'Content-Type': 'application/json'
}

context = ""
try:
message = json.loads(event['Records'][0]['Sns']['Message'])
print(message)

# 提取报警细节
AlarmName = message['AlarmName']
AlarmDescription = message['AlarmDescription']
AWSAccountId = message['AWSAccountId']
NewStateValue = message['NewStateValue']
NewStateReason = message['NewStateReason']
StateChangeTime = message['StateChangeTime']
Region = message['Region']

# 提取触发报警的指标信息
Trigger = message['Trigger']
Namespace = Trigger['Namespace']
MetricName = Trigger['MetricName']

# 构建报警详情
detail = f"Alarm Details:\n" \
f"- Alarm Name: {AlarmName}\n" \
f"- Alarm Description: {AlarmDescription}\n" \
f"- AWS Account ID: {AWSAccountId}\n" \
f"- Region: {Region}\n" \
f"- Namespace: {Namespace}\n" \
f"- Metric Name: {MetricName}\n" \
f"- New State: {NewStateValue}\n" \
f"- State Change Time: {StateChangeTime}\n" \
f"- Reason for State Change: {NewStateReason}"

title = '<font color=\"warning\">[AWS CloudWatch Alarm]</font>'

content = f"{title}\n\n{detail}"

except Exception as e:
print('CloudWatch 事件告警解析异常,请检查 Lambda 代码')
print(str(e))
content = "CloudWatch 事件告警解析异常,请检查 Lambda 代码\n" + str(e)

msg = {
"msgtype": 'markdown',
"markdown": {'content': content}
}

conn = HTTPSConnection("qyapi.weixin.qq.com")
conn.request("POST", "/cgi-bin/webhook/send?key=" + token, body=json.dumps(msg), headers=headers)
response = conn.getresponse()
print('已发送消息到企业微信')
return response.read().decode()

代码解释

在代码中,我们首先解析 SNS 消息,提取报警的各种细节,如报警名称、描述、账号 ID、区域、指标名称等。然后构建一个 Markdown 格式的消息内容,并通过企业微信的 Webhook 接口发送出去。

注意,你需要将代码中的 WX_TOKEN 替换为你自己的企业微信机器人 Token。

Lambda 函数的核心逻辑就是解析 SNS 消息,提取关键信息,然后构建企业微信消息并发送。通过使用 Markdown 格式,我们可以让消息内容更加美观和易读。

还有,为什么这里用 http.client 而不是更常用的 requests,那是因为前者是 Python 3.x 自带的模块而后者不是,所以用后者的话还需要单独再安装,这在 lambda 里就不能用直接在 web console 直接写代码这种方便明了的方式了,而是还需要在本地找个环境,把需要的包(requests)安装好,打成包,再上传上去。相对这要麻烦太多了。

将 SNS topic 与 Lambda function 绑定

最后一步,我们需要将 SNS topic 与 Lambda function 关联起来。这样,当 CloudWatch 触发告警时,就会自动通过 SNS 的 topic 内容驱动调用 Lambda fuction,进而发送消息到企业微信。

  • 进入 Lambda function 的详情页面,点击 “添加触发器”。
  • 选择 “SNS”,然后选择之前创建的 SNS topic。
  • 点击 “添加”,完成关联。
  • 至此,我们就完成了使用 CloudWatch 监控 RDS 并通过企业微信报警的整个方案。当 RDS 出现异常时,你就可以第一时间收到企业微信通知,及时处理问题了。

结语

通过本文,我们学习了如何使用 AWS CloudWatch 监控 RDS,并通过 SNS、Lambda 和企业微信实现报警功能。这个方案可以帮助我们及时发现和解决 RDS 的各种问题,提高系统的可用性和稳定性。