EventBridge提取instanceId作为目标值及Lambda执行SSM代码求助
方案解答
你当前的实现逻辑是完全可行的,核心思路就是通过Lambda作为中间层,从Auto Scaling事件中提取目标实例ID,再精准调用SSM RunCommand下发指令,完全避免了按标签匹配导致的批量触发问题。下面给你补充优化后的代码以及必要的配置要求:
一、优化后的Lambda代码(兼容AWS SDK v2,适配Node.js 14.x及更早Runtime)
你原有代码缺少错误捕获和参数校验,优化版本如下:
'use strict' const ssm = new (require('aws-sdk/clients/ssm'))() exports.handler = async (event) => { // 先校验事件中是否存在实例ID,避免异常事件触发报错 if (!event?.detail?.EC2InstanceId) { console.error('无效事件:未获取到EC2实例ID', JSON.stringify(event)) return { statusCode: 400, body: "缺少必要参数EC2InstanceId" } } const instanceId = event.detail.EC2InstanceId const params = { DocumentName: "AWS-RunShellScript", InstanceIds: [ instanceId ], TimeoutSeconds: 30, Parameters: { commands: ["/path/to/my/ec2/script.sh"], workingDirectory: ["/tmp"], // 建议指定有效工作目录,避免权限问题 executionTimeout: ["30"] // 可根据脚本执行时长调整 } }; try { const data = await ssm.sendCommand(params).promise() console.log('命令下发成功,Command ID:', data.Command.CommandId) return { statusCode: 200, body: `Run Command已下发至实例${instanceId},Command ID:${data.Command.CommandId}` }; } catch (err) { console.error('命令下发失败:', err) return { statusCode: 500, body: `命令下发失败:${err.message}` } } }
如果你使用的是Node.js 18.x及以上版本的Lambda Runtime,默认预装AWS SDK v3,需要使用v3版本的SDK写法,代码如下:
import { SSMClient, SendCommandCommand } from "@aws-sdk/client-ssm"; const ssmClient = new SSMClient({ region: process.env.AWS_REGION }); export const handler = async (event) => { if (!event?.detail?.EC2InstanceId) { console.error('无效事件:未获取到EC2实例ID', JSON.stringify(event)) return { statusCode: 400, body: "缺少必要参数EC2InstanceId" } } const instanceId = event.detail.EC2InstanceId const params = { DocumentName: "AWS-RunShellScript", InstanceIds: [ instanceId ], TimeoutSeconds: 30, Parameters: { commands: ["/path/to/my/ec2/script.sh"], workingDirectory: ["/tmp"], executionTimeout: ["30"] } }; try { const command = new SendCommandCommand(params); const data = await ssmClient.send(command); console.log('命令下发成功,Command ID:', data.Command.CommandId) return { statusCode: 200, body: `Run Command已下发至实例${instanceId},Command ID:${data.Command.CommandId}` }; } catch (err) { console.error('命令下发失败:', err) return { statusCode: 500, body: `命令下发失败:${err.message}` } } };
二、必须配置的权限要求
Lambda执行角色权限
需要给Lambda关联的IAM执行角色添加以下权限策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ssm:SendCommand", "Resource": [ "arn:aws:ec2:*:*:instance/*", "arn:aws:ssm:*:*:document/AWS-RunShellScript" ] } ] }
如果需要限制只能给指定实例或者指定自动扩缩容组的实例下发命令,可以自行调整Resource的匹配规则缩小权限范围。
EC2实例侧要求
- 实例必须预装SSM Agent(Amazon Linux 2/2023默认预装,其他系统需要手动安装)
- 实例关联的IAM实例配置文件必须包含
AmazonSSMManagedInstanceCore托管策略 - 实例网络可以访问SSM服务端点(公网访问或者配置VPC端点均可)
三、验证方式
你可以直接在Lambda控制台的测试功能中,粘贴你提供的Auto Scaling事件样例,替换EC2InstanceId为你的实际实例ID进行测试,确认命令可以正常下发到指定实例。
内容的提问来源于stack exchange,提问作者Merricat
相关产品推荐
相关产品推荐

