从AWS React应用触发EC2的Ansible Playbook遇阻,求SSM文档配置帮助
解决方案:在AWS生态内通过React触发EC2上的Ansible Playbook
嗨,我来帮你理清在AWS生态里实现这个需求的正确路径,先从你当前的SSM Document问题说起哈!
1. 先修正你的SSM Document
你的EC2实例看起来是Linux系统(路径用的是/echo_configure/Config),但你用了aws:runPowerShellScript——这是给Windows实例用的!另外,SSM的每个mainSteps是独立的执行会话,第一个步骤里的cd不会影响第二个步骤的工作目录,所以第二个步骤根本找不到你的playbook。
修正后的SSM Document应该用aws:runShellScript,并且用绝对路径直接执行playbook(或者把命令合并成一行):
{ "schemaVersion": "2.2", "description": "Execute Ansible Playbook for device configuration", "parameters": { "PlaybookFullPath": { "type": "String", "description": "Absolute path to your Ansible playbook", "default": "/echo_configure/Config/apply.yml" } }, "mainSteps": [ { "action": "aws:runShellScript", "name": "runAnsiblePlaybook", "inputs": { "runCommand": [ "ansible-playbook {{ PlaybookFullPath }}" ] } } ] }
为什么这么改?
aws:runShellScript是Linux实例的正确动作类型- 用绝对路径调用playbook,避免了切换目录的问题,更可靠
- 增加了参数
PlaybookFullPath,以后如果换playbook路径不用改Document
2. 整体实现流程(AWS生态内)
要从React应用触发这个SSM命令,绝对不能直接在前端调用AWS SSM API(会暴露你的AWS凭证,非常不安全),正确的架构是:
React按钮 → API Gateway → Lambda函数 → SSM SendCommand → EC2执行Ansible Playbook
步骤分解:
(1) 确保EC2实例满足SSM管理条件
- 实例已经安装并运行SSM Agent:Linux实例默认自带,Windows需要手动安装
- 实例关联了IAM角色,包含
AmazonSSMManagedInstanceCore权限策略(让SSM能管理这个实例) - 手动测试在EC2上运行
ansible-playbook /echo_configure/Config/apply.yml,确保playbook本身能正常执行
(2) 创建Lambda函数作为中间层
Lambda需要有调用SSMSendCommand的权限,所以给Lambda的IAM角色添加如下权限策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ssm:SendCommand", "Resource": [ "arn:aws:ssm:你的区域:你的账号:document/你的SSM Document名称", "arn:aws:ec2:你的区域:你的账号:instance/目标EC2实例ID" ] }, { "Effect": "Allow", "Action": "ssm:GetCommandInvocation", "Resource": "*" } ] }
Lambda的代码示例(用Node.js):
const { SSMClient, SendCommandCommand } = require("@aws-sdk/client-ssm"); const client = new SSMClient({ region: "你的AWS区域" }); exports.handler = async (event) => { const params = { DocumentName: "你的SSM Document名称", InstanceIds: ["目标EC2实例ID"], // 或者用Targets按标签筛选实例 Parameters: { PlaybookFullPath: ["/echo_configure/Config/apply.yml"] } }; try { const command = new SendCommandCommand(params); const response = await client.send(command); return { statusCode: 200, body: JSON.stringify({ commandId: response.Command.CommandId, message: "Command sent successfully" }) }; } catch (error) { return { statusCode: 500, body: JSON.stringify({ error: error.message }) }; } };
(3) 配置API Gateway
- 创建一个REST API,添加POST方法,集成到刚才的Lambda函数
- 启用CORS,允许你的React应用域名访问这个API
(4) React应用触发命令
在React的按钮点击事件里,调用API Gateway的接口:
const triggerPlaybook = async () => { try { const response = await fetch("你的API Gateway URL", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({}) // 如果需要传参数给playbook,可以在这里添加 }); const data = await response.json(); console.log("Command sent:", data); // 可以进一步轮询获取命令执行状态 } catch (error) { console.error("Error triggering playbook:", error); } };
3. 进阶优化
- 获取执行状态:可以在Lambda里添加
GetCommandInvocation的调用,或者前端轮询另一个Lambda接口,获取命令的执行结果(成功/失败/输出日志) - 动态传递参数:如果需要给Ansible Playbook传设备信息,可以在SSM Document里增加参数,Lambda从API Gateway获取参数后传递给SSM,Playbook通过
extra_vars接收 - 实例筛选:如果有多个EC2实例,可以用
Targets参数按标签筛选,比如[{Key: "tag:DeviceType", Values: ["你的设备类型"]}]
内容的提问来源于stack exchange,提问作者IAmTazlan
相关产品推荐
相关产品推荐

