【问题标题】:Managing Amazon EC2 instances管理 Amazon EC2 实例
【发布时间】:2026-01-13 21:25:01
【问题描述】:

我已经开始广泛使用 Amazon EC2,为了控制成本,我在下班前手动关闭实例,并在我进来时将它们打开。有时我忘记关闭它们。亚马逊仪表板中是否有机制(或任何其他方式)可以在下午 6 点自动关闭实例并在早上 6 点启动它们?如果有任何可用的 API,我很乐意编写脚本或程序。如果您已经编写了一些代码,如果您可以分享,那就太好了。

【问题讨论】:

    标签: amazon-web-services amazon-ec2


    【解决方案1】:

    有两种解决方案。

    AWS Data Pipeline - 您可以像cron 一样安排实例启动/停止。每次启动/停止将花费您一小时的 t1.micro 实例

    AWS Lambda - 定义一个在预定义时间触发的 lambda 函数。您的 lambda 函数可以启动/停止实例。您的成本将非常低或 0 美元

    在迁移到 Lambda 之前,我使用了 Data Pipeline 很长时间。数据管道非常简单。只需粘贴 AWS CLI 命令即可停止和启动实例。 Lambda 参与度更高。

    【讨论】:

    • 谢谢,我一定会试试 AWS Data Pipeline
    【解决方案2】:

    我实际上碰巧有一个为此运行的 cron 作业。我将在此处放置我的“启动实例”代码(供您入门参考)

    #!/usr/bin/python
    
    import boto.ec2
    import boto
    import boto.regioninfo
    import time
    import sys
    import boto.ec2.connection
    from boto.ec2 import EC2Connection
    from boto.regioninfo import RegionInfo
    from boto import ec2
    from boto import regioninfo
    
    ec2_region = ec2.get_region(aws_access_key_id='QWERTACCESSKEY', aws_secret_access_key='QWERTSECRETKEY', region_name='ap-southeast-2')
    conn = boto.ec2.connection.EC2Connection(aws_access_key_id='QWERTACCESSKEY', aws_secret_access_key='QWERTSECRETKEY', region=ec2_region)
    
    instance1 = conn.get_only_instances(instance_ids=['i-xxxxxxx1'])
    instance2 = conn.get_only_instances(instance_ids=['i-xxxxxxx2'])
    instance3 = conn.get_only_instances(instance_ids=['i-xxxxxxx3'])
    instance4 = conn.get_only_instances(instance_ids=['i-xxxxxxx4'])
    
    def inst():  # updates states of instances
            instance1[0].update()
            instance2[0].update()
            instance3[0].update()
            instance4[0].update()
    
    def startservers():
            inst()
            if instance1[0].state in 'stopped':
                instance1[0].start()
            if instance2[0].state in 'stopped':
                instance2[0].start()
            if instance3[0].state in 'stopped':
                instance3[0].start()
            if instance4[0].state in 'stopped':
                instance4[0].start()
    
    def check(): # a double check to make sure the servers are down
        inst()
        while instance1[0].state in 'stopped' or instance2[0].state in 'stopped' or instance3[0].state in 'stopped' or instance4[0].state in 'stopped':
            startservers()
            time.sleep(30)
    
    startservers()
    time.sleep(60)
    check()
    

    这是我的定时任务

    31 8 * * 1-5 python /home/user/startaws
    

    从周一到周五上午 8:31 运行。

    请注意 这个脚本对我来说很好用,但绝对有可能让它更干净、更简单。还有比这更好的方法。 (我写的很匆忙,所以我确定我有一些不必要的代码行)我希望它能让你知道如何开始:)

    【讨论】:

    • 谢谢!澄清一下,你在哪里运行脚本?
    • 我在 ubuntu 服务器(不是 aws 的一部分)上运行脚本,这就是为什么我有很多东西要导入等等,但如果你只是关闭一些实例并让其他实例运行。你可以在一个 ec2 实例上运行它,你会发现有一个内置的 API 适合你,所以你的脚本看起来会更干净。 docs.aws.amazon.com/cli/latest/userguide/… 这个文件例如。希望有帮助:)
    • 感谢您的澄清和其他链接。这正是我一直在寻找的。​​span>
    • 我们正在运行一个类似的脚本。它具有读取特殊标签并使用标签内容来决定实例是否应该在那个时候启动的功能。
    【解决方案3】:

    如果您的用例允许终止和重新启动,您可以考虑在 Auto Scaling 组中使用 Scheduled Scaling。 AWS 最近在管理控制台 UI 中添加了用于管理调度规则的工具。

    但我不相信 Auto Scaling 将涵盖启动和停止同一个实例,保留状态。

    【讨论】:

    • 不幸的是,我无法终止并重新启动,所以这对我不起作用。我会密切关注计划的扩展,看看他们是否会在未来增加对这个功能的支持。无论如何,谢谢!
    【解决方案4】:

    您无需编写任何脚本即可实现此目的,只需使用 AWS 控制台 API。这是 AutoScaling 与 Scheduled Scaling 的完美用例。步骤:

    1. 创建一个新的自动缩放组create a new autoscaling group。示例组:MY_AUTOSCALING_GROUP1
    2. 在您的情况下,您需要创建 2 个新的定期计划 create new schedule。示例:

    每天早上扩大规模

    aws 自动缩放 put-scheduled-update-group-action --scheduled-action-name scaleup-schedule --auto-scaling-group-name MY_AUTOSCALING_GROUP1 --recurrence "0 6 * * *" --desired-capacity 5

    每天晚上缩小规模

    aws 自动缩放 put-scheduled-update-group-action --scheduled-action-name scaledown-schedule --auto-scaling-group-name MY_AUTOSCALING_GROUP1 --recurrence "0 18 * * *" --desired-capacity 0

    通过将上述计划的操作应用于您的自动扩展组,每天早上 (6 AM) 将启动 5 个 EC2 实例并在晚上 (6 PM) 终止。

    【讨论】:

      【解决方案5】:

      您能否从一个简单的解决方案开始,例如 cron 作业和 AWS CLI?

      start.sh

      # some preparations
      # ...
      $(aws ec2 start-instances --instance-ids $LIST_OF_IDS)
      $(aws ec2 wait instance-running --instance-ids $LIST_OF_IDS)
      

      stop.sh

      # some preparations
      # ...
      $(aws ec2 stop-instances --instance-ids $LIST_OF_IDS)
      $(aws ec2 wait instance-stopped --instance-ids $LIST_OF_IDS)
      

      然后 crontab -e 并添加类似

      * 6 * * 1,2,3,4,5 start.sh
      * 18 * * 1,2,3,4,5 stop.sh
      

      【讨论】:

      • 这是否意味着我必须从另一个 EC2 实例运行此脚本,还是可以从我的 Mac 运行它?
      【解决方案6】:

      scheduled event 使用 AWS Lambda 绝对简单。可以找到完整的代码脚本here

      例如,启动 EC2 实例

      1. AWS Console,配置一个lambda函数
      2. 将以下代码复制到“Edit code inline”
      import boto3
      
      def lambda_handler(event, context):
          client = boto3.client('ec2')
          response = client.start_instances(
              InstanceIds=[
                  'i-xxxxxx',
                  'i-xxxxxx',
              ]
          )
          print response
      
      1. 赋予它基本的执行角色
      {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "logs:CreateLogGroup",
              "logs:CreateLogStream",
              "logs:PutLogEvents",
              "ec2:StartInstances"
            ],
            "Resource": [
              "arn:aws:logs:*:*:*",
              "arn:aws:ec2:*:*:*"
            ]
          }
        ]
      }
      
      1. 点击创建 lambda 函数并添加事件源(CloudWatch 事件 - 计划)

      2. 最后,测试你的函数,看看它是否正常工作

      【讨论】:

      • 这听起来很简单。我试试看