boto3创建EFS挂载目标删除自定义Waiter提示不存在问题排查
错误根因
- 自定义waiter配置中的名称和调用时传入的名称不匹配:你在
waiter_config里定义的waiter键为MountTargetDeleted,但传入create_waiter_with_client的waiter_name值为TargetDeleted,二者不一致导致boto3找不到对应waiter。 - 现有逻辑中,你创建完waiter实例后没有调用
wait()方法执行等待操作,waiter没有实际生效。 - 原acceptor规则未覆盖挂载目标全部删除后
MountTargets列表为空的场景,会导致waiter永远等不到success状态。 - 删除挂载目标后直接调用EFS删除接口,没有等待异步删除完成,逻辑和你的设计预期不符。
修复后代码
import boto3 from botocore.waiter import WaiterModel from botocore.waiter import create_waiter_with_client client = boto3.client('efs') # 修正waiter名称和配置中一致 waiter_name = "MountTargetDeleted" waiter_config = { "version": 2, "waiters": { "MountTargetDeleted": { "delay": 30, "operation": "DescribeMountTargets", "maxAttempts": 90, "acceptors": [ # 新增:挂载目标列表为空说明全部删除完成 { "expected": True, "matcher": "path", "state": "success", "argument": "length(MountTargets) == `0`" }, { "expected": "deleted", "matcher": "pathAll", "state": "success", "argument": "MountTargets[].LifeCycleState" }, { "expected": "updating", "matcher": "pathAny", "state": "failure", "argument": "MountTargets[].LifeCycleState" }, { "expected": "creating", "matcher": "pathAny", "state": "failure", "argument": "MountTargets[].LifeCycleState" } ] } } } # 提前初始化waiter,无需在循环内重复创建 waiter_model = WaiterModel(waiter_config) mount_target_deleted_waiter = create_waiter_with_client(waiter_name, waiter_model, client) def lambda_handler(event, context): response = client.describe_file_systems() fs_list = response['FileSystems'] for fs_details in fs_list: fid = fs_details['FileSystemId'] tag_response = client.describe_tags(FileSystemId=fid) all_tags = tag_response['Tags'] if {'Key': 'Retain', 'Value': 'True'} not in all_tags: # 先查是否有挂载目标,避免先删EFS报错 mount_targets_resp = client.describe_mount_targets(FileSystemId=fid) mount_targets = mount_targets_resp['MountTargets'] # 先删所有挂载目标 for mt in mount_targets: client.delete_mount_target(MountTargetId=mt['MountTargetId']) # 等待所有挂载目标删除完成 if mount_targets: mount_target_deleted_waiter.wait(FileSystemId=fid) # 再删EFS try: client.delete_file_system(FileSystemId=fid) print(f"文件系统 {fid} 已删除") except Exception as e: print(f"删除文件系统 {fid} 失败: {str(e)}") else: print(f"文件系统 {fid} 设置了Retain=True标签,跳过删除")
额外优化说明
- 将waiter初始化移到handler外,避免每次函数执行/循环内重复创建实例,减少不必要开销
- 调整了异常处理逻辑,先检查挂载目标再执行删除,避免无意义的异常捕获
- 把原来的
pathAll失败匹配改成pathAny,只要有一个挂载目标处于异常状态就终止等待,符合实际场景预期
内容的提问来源于stack exchange,提问作者Kavya
相关产品推荐
相关产品推荐

