Hibernating EC2 实例响应 CloudWatch 警报
关键要点
当 EC2 实例闲置时,通常可以通过停止实例来降低相关成本,但对于某些实例而言,休眠是一种更好的选择。本文介绍了如何使用 CloudWatch 警报来监控实例的 CPU 使用率,以识别闲置实例并触发休眠。实现此解决方案需要配置 IAM 权限、创建 Lambda 函数,以及配置 EC2 实例和 EventBridge。本文由企业支持的技术账户经理 Jos Guay 撰写。
典型的降低运行 Amazon Elastic Compute Cloud (Amazon EC2) 实例相关成本的方案是停止闲置实例。但是,在某些情况下,停止闲置实例并不实用。例如,开发环境的实例准备和运行所需时间较长,每天都要重新执行这一步骤显得不必要。对于这些实例来说,休眠是一个更好的选择。
本文将探讨一种解决方案,利用监控实例 CPU 使用率的 Amazon CloudWatch 警报来查找闲置实例。当 CPU 使用率持续低于警报阈值时,警报进入 ALARM 状态,并触发事件来识别实例并进行休眠。
应用此解决方案后,实例不再产生计算成本,仅需承担存储成本针对任何 Amazon Elastic Block Store (Amazon EBS) 卷。
综述
要对 EC2 实例进行休眠,需满足一些 先决条件 并进行相应的准备。实例必须在首次启动时配置为可以休眠,启动后无法更改此配置。
触发实例休眠的一种方法是使用 AWS Lambda 函数。该 Lambda 函数需要配置特定的权限,并与 AWS 身份和访问管理服务 (IAM) 配合使用。要将此函数与检测闲置实例的警报连接,可以使用 Amazon EventBridge 总线。
以下是一个方案架构图。
图 1 解决方案架构
EC2 实例将指标发送到 CloudWatch。CloudWatch 警报检测到闲置实例并将事件发送到 EventBridge。EventBridge 触发 Lambda 函数。Lambda 函数评估执行角色权限。Lambda 函数识别实例并发送休眠信号。要实现此解决方案,请遵循以下步骤:
使用 IAM 配置权限创建 Lambda 函数配置 EC2 实例以将指标发送到 CloudWatch配置 EventBridgea 使用 IAM 配置权限
创建一个具有停止 EC2 实例权限的 IAM 角色。Lambda 函数作为其执行角色。IAM 角色还需要将日志保存到 CloudWatch 的权限。这对记录实例进入休眠状态时非常有用。
打开 IAM 控制台。在导航窗格中,选择 Policies策略。选择 Create policy创建策略。在 Select a service选择服务中,搜索并选择 CloudWatch Logs。在 Actions allowed允许的操作中,搜索“createlog”并选择 CreateLogStream 和 CreateLogGroup。进行同样的搜索,但查找“putlog”,并选择 PutLogEvents。在 Resources资源中,选择 All全部。选择 Add more permissions添加更多权限。在 Select a service选择服务中,选择 EC2。在 Actions allowed允许的操作中,搜索“stop”,并从结果中选择 StopInstances。在 Resources资源中,选择 Specific特定,并选择 Add Arn添加 ARN。在弹出窗口中选择 Resource in this account此账户中的资源,输入实例所在的 region区域和实例 ID。这将形成要监控的实例的 ARN。选择 Add ARNs添加 ARN。选择 Next下一步。将策略命名为 AllowHibernateEC2InstancePolicy允许休眠 EC2 实例策略。图 2 访问 EC2 实例和 CloudWatch 日志的 IAM 策略
图 3 查看 IAM 策略的 JSON 格式
在导航页面中选择 Roles角色。选择 Create role创建角色。对于 Trusted entity type信任实体类型,选择 AWS ServiceAWS 服务。对于 Use case用例,选择 Lambda。选择 Next下一步。在 Permissions policies权限策略列表中,搜索并选择 Allow HibernateEC2InstancePolicy。选择 Next下一步。将角色命名为 AllowHibernateEC2InstanceFromLambdaRole允许从 Lambda 休眠 EC2 实例角色。选择 Create role创建角色。图 4 执行 IAM 策略的 IAM 角色
b 创建 Lambda 函数
创建一个 Lambda 函数,用于使用来自 CloudWatch 警报的事件数据找到闲置实例的 ID 并进行休眠。事件数据将作为函数参数存在。
事件数据为 JSON 格式。以下是该数据的示例。
json{ version 0 id 77b0f9cfebe33893f60e1950d2b8ef26 detailtype CloudWatch Alarm State Change source awscloudwatch account ltaccountgt time 20230810T212758Z region useast1 resources [ arnawscloudwatchltregiongtltaccountgtalarmalarmname ] detail { alarmName alarmname state { value ALARM reason TEST timestamp 20230705T2127586590000 } previousState { value OK reason Unchecked Initial alarm creation timestamp 20230705T2113516580000 } configuration { metrics [ { id 26c493f3c2954454ff1970ce482dca64 metricStat { metric { namespace AWS/EC2 name CPUUtilization dimensions { InstanceId ltinstance idgt } } period 300 stat Average } returnData true } ] description Created from EC2 Console } }}
按照以下步骤创建 Lambda 函数。
打开 Lambda 控制台的 Functions page。选择 Create function创建函数。选择 Author from scratch从头开始创建。将函数命名为 HibernateEC2InstanceFunction。对于 Runtime运行时,选择 Python 310或最新 Python 版本。对于 Architecture架构,选择 arm64。展开 Change default execution role更改默认执行角色,选择 Use an existing role使用现有角色。从现有角色列表中选择 AllowHibernateEC2InstanceFromLambdaRole。选择页面底部的 Create function创建函数。
在 Lambda 函数页面向下滚动,查看底部的代码选项卡。将以下代码复制到 lambdafunctionpy 文件的编辑器中。
pythonimport boto3
def lambdahandler(event context) instancesToHibernate = [] region = getRegion(event) ec2Client = boto3client(ec2 regionname=region) id = getInstanceId(event)
if id is not None instancesToHibernateappend(id) ec2Clientstopinstances(InstanceIds=instancesToHibernate Hibernate=True) print(stopped instances str(instancesToHibernate) in region region)else print(No instance id found)
def getRegion(payload) if region in payload region = payload[region] return region
# default to N Virginiareturn useast1
def getInstanceId(payload) if detail in payload detail = payload[detail] if configuration in detail configuration = detail[configuration] if metrics in configuration if len(configuration[metrics]) gt 0 firstMetric = configuration[metrics][0] if metricStat in firstMetric metricStat = firstMetric[metricStat] if metric in metricStat metric = metricStat[metric] if dimensions in metric dimensions = metric[dimensions] if InstanceId in dimensions id = dimensions[InstanceId] return id
return None
图 5 Lambda 函数代码编辑器
该代码包含以下内容:
导入部分:导入函数使用的库。在我们的案例中是 boto3。主方法 lambdahandler 是执行入口点。当 Lambda 函数运行时会调用此方法。定义一个数组来存储进入休眠的实例的 ID。因为 stopinstances 方法需要数组作为参数而非单一值。使用事件数据找到要休眠的实例的 AWS 区域和实例 ID。初始化 Amazon EC2 客户端。如果找到实例 ID,则将其添加到实例数组中。调用 stopinstances 方法,将实例数组和 True 作为参数传入以指示进行休眠操作。c 配置 EC2 实例发送指标到 CloudWatch
在此场景中,一个闲置的 EC2 实例的 CPU 利用率在 15 分钟内低于 10。可以根据需要调整利用率百分比和/或时间段。为了启用警报跟踪,EC2 实例必须将 CPU 使用指标发送到 CloudWatch。
打开 Amazon EC2 控制台。在导航窗格中,选择 Instances实例。选择要监控的实例。查找 Alarm status警报状态列,点击加号添加新警报。图 6 从 EC2 控制台创建新的 CloudWatch 警报
在 Manage CloudWatch alarms管理 CloudWatch 警报页面,选择 Create an alarm创建警报。然后,关闭 Alarm action警报操作。如果希望在休眠实例时得到通知,可以使用 Alarm notification警报通知,否则请关闭。一元云·com官网登录入口图 7 CloudWatch 警报通知和操作设置
在警报阈值部分,选择:按 Average平均值分组样本。采样数据类型为 CPU utilizationCPU 利用率。警报条件为 less than (lt)小于。百分比为 10。连续时间段为 1。时间段为 15 Minute分钟。警报名称为 IdleEC2InstanceLessThan10PctCPUUtilization15Min。图 8 CloudWatch 警报阈值
点击页面底部的 Create创建。成功创建后,顶部会显示绿色横幅。在实例的警报状态列中选择相应内容,然后在弹出窗口中选择链接以查看新创建的 CloudWatch 警报详细信息。图 9 从 EC2 控制台访问 CloudWatch 警报
向下滚动查看警报详细信息并复制其 ARN,以便 EventBridge 规则使用。图 10 查找 CloudWatch 警报 ARN
d 配置 EventBridge 以处理来自 CloudWatch 的事件
当警报进入 ALARM 状态时,意味着检测到闲置的 EC2 实例。此时,EventBridge 会生成可以被消费并采取行动的事件。为此,EventBridge 使用规则。EventBridge 规则依赖于模式来识别事件并触发相应的操作。
打开 [Amazon EventBridge 控制台](https//signinawsamazoncom/signinredirecturi=https3A2F2Fuseast2consoleawsamazoncom2Fevents3FhashArgs3D252326isauthcode3Dtrue26region3Duseast226state3DhashArgsFromTBuseast28c4d9ae275629842ampclientid=arn3Aaws