如何使用SQS启动EC2实例并在实例内触发Python脚本的执行

3
我有一个Python脚本,可以将视频转换为一系列小型全景图。现在有一个S3存储桶,会上传视频(mp4格式),我需要这个文件在上传后立即发送到EC2实例。
流程如下:
1. 将视频文件上传到S3。 2. 这应该触发EC2实例的启动。 3. 执行后,我希望将文件复制到实例内特定目录中。 4. 然后,我想运行py文件(panorama.py),从目录中读取视频文件并对其进行处理,然后生成输出图像。 5. 需要将这些输出图像上传到新的存储桶或最初使用的同一存储桶。 6. 这之后实例应该终止。
目前我已经创建了一个Lambda函数,每当向该存储桶添加对象时就会被触发。它会存储文件名和路径。我曾阅读过,现在需要使用SQS队列,并将此名称和路径元数据传递到队列中,使用SQS触发实例。然后,我需要在实例中运行一个脚本,从SQS队列中提取元数据,然后使用它将文件(mp4)从存储桶复制到实例中。
我应该如何操作?
因为我是AWS的新手,所以不太了解SQS或如何传输元数据和自动触发实例等。
2个回答

2
您的措辞有点混乱。它说您想要“启动”一个实例(这表明该实例已经存在),但随后又说它想要“终止”一个实例(这将永久移除它)。我假设您实际上是想要“停止”实例以便再次使用。
您可以将一个 shell 脚本放在 /var/lib/cloud/scripts/per-boot/ 目录中。然后每次实例启动时都会执行此脚本
当实例处理完成后,它可以调用 sudo shutdown now -h 来关闭实例。(或者,它可以告诉 EC2 停止实例,但使用 shutdown 更容易。)
有关详细信息,请参见: Auto-Stop EC2 instances when they finish a task - DEV Community

这看起来很有趣且实用。不过,如果他正在使用队列,那么只有在队列为空时停止实例是否更好呢?另一个问题是,相较于使用MediaConvert,您认为这种文件处理解决方案怎么样? - ashraf minhaj

1
我尽力以最简洁的方式回答,下面有许多可以进一步改进的点。我认为以下仍然相当重要,因为你提到你是 AWS 的新手。
使用 AWS Lambda 和 Amazon S3
Amazon S3 可以在对象被创建或删除时向 Lambda 函数发送事件。您可以在桶上配置通知设置,并授予 Amazon S3 在函数的基于资源的权限策略上调用函数的权限。
当上传对象时,它将触发 lambda 函数。该函数使用 ec2 用户数据创建实例。
对于 ec2 实例,您需要通过使用"使用实例配置文件"来提供必要的权限进行下载和上传对象。
用户数据有一个脚本,完成工作流需要的其余部分。
  1. 下载s3对象,您可以在同一脚本中传递名称和s3 bucket名称
  2. 完成#1后,启动处理视频的panorama.py
  3. 在下一步中,您可以开始将对象上传到S3存储桶
  4. 最终终止实例可能有点棘手,您可以通过更改实例启动时关机行为来实现

或者 您可以使用以下方法来终止实例,但在这种情况下,您的ec2实例配置文件必须具有终止实例的访问权限。

ec2-terminate-instances $(curl -s http://169.254.169.254/latest/meta-data/instance-id)

你可以将上述步骤封装到 userdata 中的 shell 脚本中。
Lambda ec2 启动实例:
def launch_instance(EC2, config, user_data):

    ec2_response = EC2.run_instances(
        ImageId=config['ami'],  # ami-0123b531fc646552f
        InstanceType=config['instance_type'],
        KeyName=config['ssh_key_name'],
        MinCount=1,
        MaxCount=1,
        SecurityGroupIds=config['security_group_ids'],
        TagSpecifications=tag_specs,
        # UserData=base64.b64encode(user_data).decode("ascii")
        UserData=user_data
    )

    new_instance_resp = ec2_response['Instances'][0]
    instance_id = new_instance_resp['InstanceId']
    print(f"[DEBUG] Full ec2 instance response data for '{instance_id}': {new_instance_resp}")

    return (instance_id, new_instance_resp)

上传文件到S3 -> 启动EC2实例


我无法在控制台中编辑我的用户数据。尽管我的实例已停止,但在我的实例设置中没有“编辑用户数据”的选项。我该怎么办? - akshay acharya
我该如何将文件名和路径传递给用户数据文件?实例如何知道要下载什么?以及,从s3下载文件到实例内的本地目录的代码是什么?此外,我有一个现有的ec2实例,所以我可以直接调用它吗?我不需要创建新实例,因为程序和所有目录已经在此实例中。 - akshay acharya
基本上,我已经有一个现有的实例。我想在将文件复制到实例内部的本地目录后启动它并在其中运行 panorama.py。一旦处理完视频并生成输出,我就想停止实例。每次上传新视频到存储桶时都应重复此操作。 - akshay acharya
@akshayacharya 在你的 Lambda 中,当你启动实例时,可以将文件名和 S3 存储桶名称作为变量传递。要下载对象,可以使用 aws s3 cp 命令,上传也是同样的方式。如果你已经有一个实例,那么你只需要 启动实例,而不是创建新实例。 - samtoddler
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接