如何在AWS中自动停止未带os:linux标签的EC2实例?
实现Lambda自动关停未标记
os=linux的EC2实例 我懂你的痛点——找带特定标签的实例停掉很直接,但反过来筛选没有os标签或者**os标签值不是linux**的实例,过滤逻辑确实要绕一下。下面给你一套完整的可落地方案,用Python写Lambda代码,附IAM权限配置和触发方式,一步步来:
一、先给Lambda配置最小权限的IAM角色
Lambda需要权限去查询EC2实例状态和执行停止操作,别直接给全权限,搞个自定义政策更安全:
- 进入IAM控制台,创建新角色,选择
Lambda作为信任实体 - 给角色附加下面这个自定义政策(或者直接搜索托管政策
AmazonEC2ReadOnlyAccess+AmazonEC2StopInstances权限):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:StopInstances" ], "Resource": "*" } ] }
二、编写Lambda函数代码(Python 3.10+)
核心逻辑是:先拉取指定区域内所有运行中的EC2实例,逐一检查标签——要么没有os标签,要么标签值不是linux,符合条件的就批量停止。
import boto3 def lambda_handler(event, context): # 替换成你需要操作的AWS区域,比如'us-east-1' TARGET_REGION = 'your-target-region' ec2_client = boto3.client('ec2', region_name=TARGET_REGION) # 先筛选出所有处于运行状态的实例 running_instances = ec2_client.describe_instances( Filters=[{'Name': 'instance-state-name', 'Values': ['running']}] ) instances_to_stop = [] # 遍历每个实例,检查标签条件 for reservation in running_instances['Reservations']: for instance in reservation['Instances']: instance_id = instance['InstanceId'] has_valid_tag = False # 检查实例是否有标签,且包含os=linux(忽略大小写兼容) if 'Tags' in instance: for tag in instance['Tags']: if tag['Key'] == 'os' and tag['Value'].strip().lower() == 'linux': has_valid_tag = True break # 没有符合要求的标签,加入停止列表 if not has_valid_tag: instances_to_stop.append(instance_id) # 批量停止符合条件的实例 if instances_to_stop: print(f"即将停止实例: {instances_to_stop}") ec2_client.stop_instances(InstanceIds=instances_to_stop) return f"已触发停止操作,共{len(instances_to_stop)}个实例" else: print("没有需要停止的目标实例") return "无操作执行"
代码细节说明:
- 先过滤
running状态的实例,避免做无用功 - 标签判断加入了大小写兼容(比如
Linux或LINUX也会被判定为有效) - 批量调用停止接口,减少API请求次数,提升效率
三、测试Lambda函数
- 在Lambda控制台的「测试」选项卡,创建一个空测试事件(随便填个名称就行)
- 执行测试后,去CloudWatch日志里查看输出,确认筛选逻辑是否正确——测试阶段可以先把
stop_instances换成print,避免误停生产实例
四、设置自动触发(按需配置)
如果需要定期执行(比如每天凌晨清理):
- 进入Lambda函数的「触发器」选项卡,添加触发器
- 选择「EventBridge(CloudWatch Events)」,创建定时规则,比如用表达式
cron(0 0 * * ? *)(每天UTC时间0点执行)
踩坑提醒
- 确保Lambda角色的区域和目标EC2区域一致,跨区域的话可以修改代码支持多区域遍历
- 部分实例可能因状态锁(比如正在初始化)无法停止,可在代码中添加异常捕获,避免整个函数失败
内容的提问来源于stack exchange,提问作者knocknock
相关产品推荐
相关产品推荐

