如何根据基于时间的计划启动和停止 AWS EC2 实例

Tim*_*Tim 19 amazon-ec2 amazon-web-services

是否有一种简单的方法可以在每天的给定时间启动和停止 AWS EC2 实例?这可以为我的开发和测试服务器节省大量资金。

Tim*_*Tim 19

更新

AWS 发布了一个名为“ Instance Scheduler ”的工具,包括从该页面链接的完整配置指南。它看起来是我在下面描述的 EC2 调度程序的增强,增加了一些功能,但本质上是一样的。

下面的指南仍然有效,但最好查看新安装的实例调度程序。

原帖

AWS 有一个名为EC2 Scheduler的工具,可让您非常灵活地控制启动和停止 EC2 实例。

该工具允许您在设置工具时定义默认开始和停止时间,您可以稍后更改。您可以选择控制哪些实例,您可以使用标签为每个实例指定不同的开始和停止时间。

虽然它是一个很棒的工具,但文档有点模糊和混乱。这就像文档是由编写工具并了解它的一切的工程师编写的,而不是由技术作家编写的。

注意:如果您有反馈或更正意见,我们将不胜感激。如果您有基于此的问题,请开始您自己的问题。

什么是 EC2 调度程序

此工具是一个 Lambda 函数,可与 Cloudwatch Events 和 DynamoDB 配合使用。它使用 Cloudformation 模板进行部署,该模板还设置了必要的 IAM 角色和策略。您可以在此处阅读有关该架构的信息

AWS EC2 调度程序架构

部署

首先转到此页面并单击“启动解决方案”。现在直接链接在这里,但它可能会改变。

在控制台顶部选择您希望资源部署到的区域。该脚本控制任何区域的 EC2 实例,但它在一个区域运行。

标记 EC2 实例

此处的文档中对此进行了介绍,但这并不像它想象的那么简单。

您可以通过标记您的实例来控制启动和停止哪些实例。

最简单的情况要求您根据计划标记要启动和停止的每个 EC2 实例。为此,请在控制台中找到您的 EC2 实例,单击标签并创建此标签

调度程序的 EC2 实例标记

要启用复制和粘贴:

  • 键:调度程序:ec2-startstop
  • 值:真

如果您希望以不同的时间表启动和停止特定实例,您可以将附加信息附加到标签键和值。例如,如果您希望实例在 UTC 时间 1500 点开始并在星期二、星期四和星期五的 2400 点停止,请输入以下内容。

键:scheduler:ec2-startstop:late 值:1500;2400;utc;tue,thu,fri

请注意,“late”一词可以是任何字符串,“late”没有特殊含义。

您可以使用此工具将 UTC 转换为您的本地时间。

您可以使用标签编辑器批量处理标签实例。这可以让您更轻松地设置批量标记,这对于为开发、测试和生产设置不同的设置非常有用。我怀疑你会在生产中使用它。

CloudFormation 参数

当您运行 CloudFormation 模板时,您必须输入大量参数。大多数你可以保留默认值。这是一些最重要的参数

  • 堆栈名称:随意称呼它。这就是它在 CloudFormation 中的名称。
  • 自定义标签名称:这是您针对 EC2 实例放置的标签的“密钥”。除非有充分的理由或需要多次安装,否则将其保留为默认值。
  • 默认启动/停止时间:启动和停止实例的默认 UTC 时间
  • DynamoDB:设置存储在 DynamoDB 中。您可以更改表名等。因为 DynamoDB 免费套餐不会过期,所以大多数人不太可能被收费。
  • (第二个屏幕)权限 - 这是一个红鲱鱼,请参阅下面的部分。将其保留为默认值,并在您尝试设置 EC2 调度程序时以管理员身份运行。
  • 通知选项:我发现设置 SNS 通知很有用,这样我就可以验证它是否有效。我没有花时间研究如何禁用它们,我只是将其删除,重新运行 Cloudformation 模板以重新安装。

权限、策略和角色

CloudFormation 模板的权限/IAM 角色部分是一个红鲱鱼 - 即它在很大程度上无关紧要。它仅指定用于运行 CloudFormation 脚本的角色,它与创建的资源或运行 lambda 函数时使用的角色没有区别。回想起来,这是显而易见的,但是当我开始时,这对我来说并不明显。

您运行此脚本的任何角色都会在 IAM 中创建相同的角色和内联权限。Lambda 函数使用脚本创建的“ec2 调度程序角色”运行。

我在下面列出了我的政策,以防它们对任何人有帮助。

CloudWatch 事件和指标

如果您想查看来自 Lambda 函数的日志,请进入 Cloudwatch Events。日志记录非常好。还有指标,因此您可以查看它的运行时间、运行时间等。

额外的

lambda 函数的代码可在Github 上找到

政策

这些通常不是必需的,但可能适用于某些人,因此我会将它们包括在内。

IAM 角色政策

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "iam:CreateRole",
                "iam:GetRole",
                "iam:PassRole",
                "iam:PutRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:DeleteRole",
                "dynamodb:*",
                "lambda:*",
                "SNS:Publish",
                "events:*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "S3:GetObject",
            "Resource": [
                "arn:aws:s3:::solutions-us-west-2",
                "arn:aws:s3:::solutions-us-west-2/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StopInstances",
                "ec2:StartInstances"
            ],
            "Resource": [
                "arn:aws:ec2:us-west-2:123456789012:instance/i-0d112345Ab6789012"
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

IAM 角色的信任策略

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "lambda.amazonaws.com",
          "cloudformation.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

  • 令人难以置信的是,他们喜欢把事情复杂化…… (2认同)

net*_*fed 13

如果您只想启动和停止实例,这里有另一种使用 Lambda 服务的方法。它假设您要控制特定的实例 ID。您可以通过添加更多以逗号分隔的 id 来控制多个实例。(例如:“i-3453453”、“i-45656745”)。您可以在 AWS 控制台实例部分中找到您的实例的 ID。

在 Lambda 控制台中

  1. 打开 AWS Lambda 控制台,然后选择创建函数。
  2. 从头开始选择作者。
  3. 为您的函数输入一个名称,例如“StopEC2Instances”。
  4. 对于运行时,选择 Python 2.7
  5. 展开角色下拉菜单,然后选择创建自定义角色。这会在浏览器中打开一个新选项卡或窗口。
  6. 在 IAM 角色下拉菜单中,选择创建新的 IAM 角色,然后输入角色名称,例如“lambda_start_stop_ec2”。
  7. 选择查看策略文档、编辑,然后在提示阅读文档时选择确定。将政策中的所有文本替换为:

下面的代码

{
  "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": "*"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)
  1. 选择允许完成角色创建并返回 AWS Lambda 控制台。
  2. 要停止您的实例,请将函数代码编辑器中的所有文本替换为以下内容:

下面的代码

import boto3
region = ' eu-west-1'
instances = ['i-0dd344443184503fa']

def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name=region)
    ec2.stop_instances(InstanceIds=instances)
    print 'stopped your instances: ' + str(instances)
Run Code Online (Sandbox Code Playgroud)

请记住用您自己的值替换区域和实例值。

  1. 从运行时下拉菜单中,选择 Python2.7。
  2. 在基本设置中,为功能超时输入 10 秒。
  3. 选择保存。
  4. 重复所有步骤以创建另一个将启动您的实例的函数,然后使用此 python 脚本启动它:

下面的代码

import boto3
region = 'eu-west-1'
instances = [' i-0dd344443184503fa']

def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name=region)
    ec2.start_instances(InstanceIds=instances)
    print 'started your instances: ' + str(instances)
Run Code Online (Sandbox Code Playgroud)

安排功能

在这里,您将创建一个 CloudWatch 事件,它将在晚上触发您的 Lambda 函数

  1. 打开 Amazon CloudWatch 控制台。
  2. 选择事件,然后选择创建规则。
  3. 在事件源下选择计划。
  4. 输入告诉 Lambda 何时停止实例的时间间隔或 cron 表达式。有关正确语法的详细信息,请参阅规则的计划表达式语法。

注意:Cron 表达式以 UTC 计算。请务必根据您的首选时区调整表达式。下面是一个示例,它将在每天格林威治标准时间/UTC 时间 08:00 运行该函数):

0 08 * * ? *
Run Code Online (Sandbox Code Playgroud)
  1. 选择添加目标,然后选择 Lambda 函数。
  2. 对于函数,选择停止您的实例的 Lambda 函数。
  3. 选择配置详细信息。
  4. 在提供的字段中输入以下信息: 对于名称,输入一个有意义的名称,例如“StopEC2Instances”。对于描述,添加有意义的描述,例如“每天晚上停止 EC2 实例”。对于状态,选择已启用。
  5. 选择创建规则。

要在早上重新启动您的实例,请重复这些步骤并使用您首选的开始时间。如果您想在函数失败时发送邮件消息,您可以设置 SNS 主题并在 Lmbda 函数创建窗口中的调试下配置该消息的发送。

所有这些的来源都可以在这里找到:AWS 文档

  • 漂亮的答案,但有点过时了。这是最新的,非常相似:https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/ (2认同)

小智 6

实现相同目标的更简单方法是使用 AWS EventBridge 规则。

转到 Amazon EventBridge > 规则

  1. 创建新规则并将规则类型选择为Schedule

  2. 为实例关闭计划提供 cron 表达式。例如。计划任务(30 17 * * ? *)

  3. 对于Target1,选择:

    • 目标类型“AWS 服务”
    • 目标“AWS StopInstances API 调用”,并且
    • 提供要按计划关闭的实例 ID 。
    • 最后,选择为此特定资源创建新角色
  4. 查看计划和实例详细信息并完成规则创建。

您可以使用上面提到的方法(使用 lambda)再次启动同一个实例。

  • 这是事实,在问题提出五年后:) AWS 一直在发展和变化,因此旧的答案并不总是最好的。 (2认同)