我想按需启动一个 EC2 实例,并在它空闲一段时间(例如 >= 1 小时没有网络活动)时将其关闭,但我无法判断在 AWS 中执行此操作的标准方式是什么样的,因为 AWS 不支持局域网唤醒。
我打算运行的服务将需要持久的网络连接,例如 ssh。
我追求的用户体验是这样的:
- 如果在用户尝试连接时服务已启动,则用户可以立即访问该服务。
- 如果用户尝试连接时服务已关闭,则用户将收到“服务正在启动”回复(并且连接已关闭)。用户在几分钟后重试并成功连接(如果重试过早,则再次收到“正在启动”消息)。在最后一个用户断开连接后,服务最多可保持一小时的正常运行。
我这样做的动机主要是节省成本。需求将非常难以预测(因此预定实例并不合适),每天的活动时间可能少于 12 小时,并且用户愿意等待几分钟才能启动服务。而且我不想被锁定在 1 年以上的预留实例定价期限内。
我也对如何实现这一目标进行了一些大胆的尝试,并希望得到有关这些尝试的合理性/合理性的反馈:
- 使用自动扩展组将服务从 0 个实例“扩展”到最多 1 个实例。但如果没有正在运行的实例,我不知道如何发出“服务正在启动”回复。
- 当服务关闭时运行 t2.micro 实例,其唯一目的是捕获连接尝试,发出“启动”回复,触发启动实际服务实例,然后停止。当服务实例因不活动而关闭时,需要重新启动 t2.micro 实例。
谢谢!
答案1
Lambda 的工作原理与此类似,但它会让用户在启动应用程序时等待。但在 Lambda 中,您无需管理实例 - 一切都在后台完成。
我还会检查您是否可以做一些涉及 Lambda 和 Route53 故障转移检查的事情,这样如果实例关闭,用户就会访问 Lambda,如果实例启动,用户就会访问该实例。不过,如果 Lambda 需要特定的 Host 标头,这可能行不通。
或者再次使用 R53 故障转移来运行预留实例 t2.nano 来做“等候室”,然后在启动后代理或重定向到另一个实例。
答案2
您可以做这样的事情,而无需使用其他服务:
import boto3
import json
def lambda_handler(event, context):
ec2 = boto3.resource('ec2')
instance = ec2.Instance(event['instance_id'])
if instance.state['Code'] == 16:
# Instance is running, do what you want
elif instance.state['Code'] == 80:
# Instance is stopped, start it
instance.start()
return { 'status': 'instance-unavailable' }
else
# Instance is in another state
在这种情况下,instance_id
通过参数接收,但当然,您可以对其进行硬编码。