如何使用 Lambda 按固定间隔停止和启动 Amazon EC2 实例?

上次更新日期:2022 年 1 月 13 日

我想通过自动停止和启动 EC2 实例来减少 Amazon Elastic Compute Cloud (Amazon EC2) 使用量。我该如何使用 AWS Lambda 和 Amazon EventBridge 来做到这一点?

简短描述

注意:以下是一个简单的解决方案。若要获得更强大的解决方案,请使用 AWS Instance Scheduler。有关更多信息,请参阅自动启动和停止 AWS 实例

要使用 Lambda 按固定间隔停止和启动 Amazon EC2 实例,请执行以下操作:

1.    为 Lambda 函数创建自定义 AWS Identity and Access Management (IAM) 策略和执行角色。

2.    创建停止和启动 EC2 实例的 Lambda 函数。

3.    测试 Lambda 函数。

4.    创建按计划触发函数的 EventBridge 规则
注意:您还可以创建触发 AWS 账户中发生的事件的规则

解决方法

注意:如果在完成以下步骤后,在启动错误时收到客户端错误,请参阅当我启动带有加密卷的实例时,实例立即停止,并出现“client error on launch(启动时出现客户端错误)”的错误

获取要停止和启动的 EC2 实例的 ID。然后,请按照以下步骤执行操作。

为 Lambda 函数创建 IAM policy 和执行角色

1.    使用 JSON 策略编辑器创建 IAM 策略。复制下列 JSON 策略文档,并粘贴到策略编辑器中:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Start*",
        "ec2:Stop*"
      ],
      "Resource": "*"
    }
  ]
}

2.    为 Lambda 创建 IAM 角色

重要提示:将权限策略附加到 Lambda 时,请确保选择您刚刚创建的 IAM policy。

创建停止和启动 EC2 实例的 Lambda 函数

1.    在 Lambda 控制台中,选择创建函数

2.    选择 Author from scratch(从头开始创作)

3.    在基本信息下,添加以下内容:
函数名称中,输入一个名称,并将其识别为用于停止 EC2 实例的函数。例如,"StopEC2Instances"。
对于 Runtime(运行时),选择 Python 3.9
权限下,展开更改原定设置执行角色
执行角色下,选择使用现有角色
现有角色下,选择所创建的 IAM 角色。

4.    选择创建函数

5.    在 Code(代码)、Code source(源代码)下,将下列代码复制并粘贴到代码编辑器中的编辑器窗格中(lambda_function)。此代码将停止您识别的 EC2 实例。

示例函数代码 – 停止 EC2 实例

import boto3
region = 'us-west-1'
instances = ['i-12345cb6de4f78g9h', 'i-08ce9b2d7eccf6d26']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.stop_instances(InstanceIds=instances)
    print('stopped your instances: ' + str(instances))

重要提示:对于 region (区域),用实例所在的 AWS 区域替换“us-west-1”。对于 instances (实例),将示例 EC2 实例 ID 替换为要停止和启动的特定实例的 ID。

6.    选择 Deploy(部署)。

7.    在 Configuration(配置)选项卡中,选择 General configuration(常规配置),Edit(编辑)。将 Timeout(超时)设为 10 秒,然后选择 Save(保存)。

注意:根据您的使用案例需要配置 Lambda 函数设置。例如,如果要停止和启动多个实例,可能需要不同的 Timeout(超时)和 Memory(内存)值。

8.    重复步骤 1-7 以创建另一个函数。以不同的方式执行以下操作,以使此函数启动 EC2 实例:

在步骤 3 中,输入一个 Function name (函数名称),请不要与之前的函数名称重复。例如,“StartEC2Instances”。
在步骤 5 中,将以下代码复制并粘贴到代码编辑器的编辑器窗格中(lambda_function):

示例函数代码 – 启动 EC2 实例

import boto3
region = 'us-west-1'
instances = ['i-12345cb6de4f78g9h', 'i-08ce9b2d7eccf6d26']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.start_instances(InstanceIds=instances)
    print('started your instances: ' + str(instances))

重要提示:对于 region (区域)instances (实例),请使用与代码中用于停止 EC2 实例的值相同的值。

测试 Lambda 函数

1.    在 Lambda 控制台中,选择函数

2.    选择您创建的函数之一。

3.    选择 Code(代码)选项卡。

4.    在 Code source(代码源)部分中,选择 Test(测试)。

5.    在配置测试事件对话框中,选择创建新测试事件

6.    输入 Event name(事件名称)。 然后,选择 Create (创建)

注意:不需要为测试事件更改 JSON 代码,因为函数不使用它。

7.    选择 Test(测试)以运行该函数。

8.    对创建的另一个函数重复步骤 1-6。

提示:您可以在测试前后检查 EC2 实例的状态,以确认函数是否按预期工作。

创建触发 Lambda 函数的 EventBridge 规则

1.    打开 Eventbridge 控制台

2.    选择创建规则

3.    输入规则的 Name(名称),例如“StopEC2Instances”。可选择输入 Description(描述)。

4.    在 Define pattern(定义模式)中,选择 Schedule(计划)。

5.    执行以下任意一项操作:

固定频率为中,输入以分钟、小时或天为单位的时间间隔。
Cron 表达式中,输入一个指示 Lambda 何时停止实例的表达式。有关表达式语法的信息,请参阅规则的计划表达式
注意
:Cron 表达式使用 UTC 进行计算。确保针对您的首选时区调整表达式。

6.    在选择目标中,从目标下拉菜单中选择 Lambda 函数

7.    对于函数,选择停止您的 EC2 实例的函数。

8.    向下滚动并选择创建

9.    重复步骤 1-8 以创建启动 EC2 实例的规则。以不同的方式执行以下操作:

输入规则的名称,例如 "StartEC2Instances"。
(可选)输入 Description (描述),例如“每天早上 7 点启动 EC2 实例。”
在步骤 5 中,在 Cron 表达式中,输入一个指示 Lambda 何时启动实例的表达式。
在步骤 7 中,对于 Function(函数),选择启动您的 EC2 实例的函数。