如何在S3存储桶指定目录无对象时通过Lambda停止EC2实例
原因说明
你当前的Lambda代码没有对S3触发事件对应目录的剩余对象做校验,只要收到S3的删除事件通知就直接执行EC2停止逻辑,所以会出现删除dump/目录下任意文件就触发实例停止的问题。
前置配置调整
- 首先需要给Lambda的执行IAM角色新增S3的
ListBucket权限,否则代码无法枚举存储桶内的对象,参考权限策略片段如下:
{ "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::你的存储桶名称" }
替换后的Lambda代码
import boto3 region = 'us-west-1' instances = ['i-12345cb6de4f78g9h'] ec2 = boto3.client('ec2', region_name=region) s3 = boto3.client('s3') def lambda_handler(event, context): # 从事件中获取触发的S3桶名 bucket_name = event['Records'][0]['s3']['bucket']['name'] # 查询dump目录下是否还有对象,仅查1条即可判断是否为空,效率更高 resp = s3.list_objects_v2( Bucket=bucket_name, Prefix='dump/', MaxKeys=1 ) # 目录下无任何剩余对象时才执行停止操作 if resp['KeyCount'] == 0: ec2.stop_instances(InstanceIds=instances) print(f'stopped your instances: {str(instances)}') else: print(f'dump/目录仍有{resp["KeyCount"]}个对象,不执行停止操作')
注意事项
- 如果你使用的S3存储桶开启了版本控制,需要将
list_objects_v2替换为list_object_versions,同时校验是否还有未彻底删除的对象版本、删除标记存在,避免逻辑不生效 - 如果你需要固定校验指定存储桶,不需要从事件中动态获取桶名,也可以直接在代码中硬编码
bucket_name的值即可
内容的提问来源于stack exchange,提问作者Mr.Fresher
相关产品推荐
相关产品推荐

