【发布时间】:2026-01-13 21:25:01
【问题描述】:
我已经开始广泛使用 Amazon EC2,为了控制成本,我在下班前手动关闭实例,并在我进来时将它们打开。有时我忘记关闭它们。亚马逊仪表板中是否有机制(或任何其他方式)可以在下午 6 点自动关闭实例并在早上 6 点启动它们?如果有任何可用的 API,我很乐意编写脚本或程序。如果您已经编写了一些代码,如果您可以分享,那就太好了。
【问题讨论】:
标签: amazon-web-services amazon-ec2
我已经开始广泛使用 Amazon EC2,为了控制成本,我在下班前手动关闭实例,并在我进来时将它们打开。有时我忘记关闭它们。亚马逊仪表板中是否有机制(或任何其他方式)可以在下午 6 点自动关闭实例并在早上 6 点启动它们?如果有任何可用的 API,我很乐意编写脚本或程序。如果您已经编写了一些代码,如果您可以分享,那就太好了。
【问题讨论】:
标签: amazon-web-services amazon-ec2
有两种解决方案。
AWS Data Pipeline - 您可以像cron 一样安排实例启动/停止。每次启动/停止将花费您一小时的 t1.micro 实例
AWS Lambda - 定义一个在预定义时间触发的 lambda 函数。您的 lambda 函数可以启动/停止实例。您的成本将非常低或 0 美元
在迁移到 Lambda 之前,我使用了 Data Pipeline 很长时间。数据管道非常简单。只需粘贴 AWS CLI 命令即可停止和启动实例。 Lambda 参与度更高。
【讨论】:
我实际上碰巧有一个为此运行的 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 运行。
请注意 这个脚本对我来说很好用,但绝对有可能让它更干净、更简单。还有比这更好的方法。 (我写的很匆忙,所以我确定我有一些不必要的代码行)我希望它能让你知道如何开始:)
【讨论】:
如果您的用例允许终止和重新启动,您可以考虑在 Auto Scaling 组中使用 Scheduled Scaling。 AWS 最近在管理控制台 UI 中添加了用于管理调度规则的工具。
但我不相信 Auto Scaling 将涵盖启动和停止同一个实例,保留状态。
【讨论】:
您无需编写任何脚本即可实现此目的,只需使用 AWS 控制台 API。这是 AutoScaling 与 Scheduled Scaling 的完美用例。步骤:
每天早上扩大规模
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) 终止。
【讨论】:
您能否从一个简单的解决方案开始,例如 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
【讨论】:
scheduled event 使用 AWS Lambda 绝对简单。可以找到完整的代码脚本here
例如,启动 EC2 实例
import boto3 def lambda_handler(event, context): client = boto3.client('ec2') response = client.start_instances( InstanceIds=[ 'i-xxxxxx', 'i-xxxxxx', ] ) print response
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "ec2:StartInstances" ], "Resource": [ "arn:aws:logs:*:*:*", "arn:aws:ec2:*:*:*" ] } ] }
点击创建 lambda 函数并添加事件源(CloudWatch 事件 - 计划)
最后,测试你的函数,看看它是否正常工作
【讨论】: