You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lambda调用SSM文档遇Invalid Instance ID错误排查与解决

解决Lambda调用SSM Run Command时的InvalidInstanceId错误

问题背景

我在实现Auto Scaling实例终止的自动化流程时踩了坑:设计的流程是实例终止→生命周期钩子→CloudWatch事件→Lambda→SSM Run Command,Lambda在测试环境(调用运行中的实例)能正常工作,但在真实终止流程中触发后,却抛出了InvalidInstanceId错误。

Lambda函数代码如下:

const AWS = require('aws-sdk');
const ssm = new AWS.SSM();
const SSM_DOCUMENT_NAME = process.env.SSM_DOCUMENT_NAME;
AWS.config.update({region: 'ap-south-1'});
const sendCommand = (instance_id) => {
  var params = {
    DocumentName: SSM_DOCUMENT_NAME,
    InstanceIds: [instance_id],
    TimeoutSeconds: 300
  };
  console.log("before call:"+params.InstanceIds);
  return ssm.sendCommand(params).promise();
}
exports.handler = async (event) => {
  console.log('event ', JSON.stringify(event));
  try {
    const instance_id = event.detail.EC2InstanceId;
    console.log("processing autoscaling event for "+instance_id);
    await sendCommand(instance_id);
    console.log('sent command');
  } catch (error) {
    throw error;
  }
}

触发时的错误日志:

Invoke Error
{
"errorType": "InvalidInstanceId",
"errorMessage": null,
"code": "InvalidInstanceId",
"message": null,
"time": "2020-06-19T09:43:10.348Z",
"requestId": "150decf1-be1d-407f-9a86-a4f986c04807",
"statusCode": 400,
"retryable": false,
"retryDelay": 20.23844834854607,
"stack": [
"InvalidInstanceId: null",
" at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:51:27)",
" at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)",
" at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)",
" at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)",
" at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)",
" at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)",
" at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10",
" at Request. (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)",
" at Request. (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)",
" at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18)"
]
}

问题根源分析

  1. 实例生命周期与SSM托管状态不匹配:当实例进入termination:wait状态后,会立刻从Systems Manager的托管实例列表中移除,此时Lambda触发SSM命令时,SSM已经找不到该实例ID,自然抛出InvalidInstanceId错误——就算把生命周期等待时间拉到600秒也没用,因为实例一旦进入终止流程,SSM的注册状态会直接失效。
  2. 测试场景完全不符合真实流程:之前的测试是针对运行中的实例,但手动终止实例根本不会触发生命周期钩子!只有当Auto Scaling策略判定实例不健康(比如ELB健康检查失败)时,才会触发对应的生命周期钩子,这导致之前的测试完全无法复现真实问题。
  3. Lambda代码的小bug:代码里先创建了SSM实例,再更新AWS区域配置,这会导致区域配置不生效,虽然这次错误不是直接由此引发,但会影响整体稳定性。

解决方案

1. 调整生命周期钩子的触发时机

把生命周期钩子的触发事件调整到实例刚进入终止流程的早期阶段,确保在实例还没从SSM托管列表中移除时就执行SSM命令:

  • 在Auto Scaling Group的生命周期钩子配置中,选择InstanceTerminating作为触发事件,设置合理的等待时间(保证SSM命令能在实例被注销前执行完成)。
  • 确认CloudWatch Events规则能及时触发Lambda,不要有延迟。

2. 修正Lambda代码的区域配置顺序+增加实例校验

把AWS区域配置移到创建SSM实例之前,同时新增实例在SSM托管列表中的校验逻辑,避免无效调用:

const AWS = require('aws-sdk');
AWS.config.update({region: 'ap-south-1'}); // 先更新区域配置,再创建SSM实例
const ssm = new AWS.SSM();
const SSM_DOCUMENT_NAME = process.env.SSM_DOCUMENT_NAME;

const sendCommand = (instance_id) => {
  var params = {
    DocumentName: SSM_DOCUMENT_NAME,
    InstanceIds: [instance_id],
    TimeoutSeconds: 300
  };
  console.log("before call:"+params.InstanceIds);
  return ssm.sendCommand(params).promise();
}

exports.handler = async (event) => {
  console.log('event ', JSON.stringify(event));
  try {
    const instance_id = event.detail.EC2InstanceId;
    console.log("processing autoscaling event for "+instance_id);
    
    // 新增:提前验证实例是否在SSM托管列表中
    const instanceInfo = await ssm.describeInstanceInformation({
      InstanceInformationFilterList: [
        {
          key: 'InstanceIds',
          valueSet: [instance_id]
        }
      ]
    }).promise();
    
    if (instanceInfo.InstanceInformationList.length === 0) {
      console.error(`Instance ${instance_id} is not managed by SSM, skipping command`);
      return { statusCode: 200, body: 'Instance not found in SSM' };
    }
    
    await sendCommand(instance_id);
    console.log('sent command');
    return { statusCode: 200, body: 'Command sent successfully' };
  } catch (error) {
    console.error('Error executing command:', error);
    throw error;
  }
}

3. 用正确的方式测试流程

不要手动终止实例测试,而是模拟Auto Scaling的不健康实例场景(比如停止实例的SSM Agent,或者让ELB健康检查失败),触发Auto Scaling的终止流程,这样才能正确触发生命周期钩子。

4. 确保实例能被SSM正常管理

  • 确认实例上的SSM Agent已正确安装并运行,且实例拥有AmazonSSMManagedInstanceCore这个IAM权限策略。
  • 实例所在的VPC需要能访问SSM服务(可以通过VPC端点或公网访问),避免实例无法注册到SSM。

内容的提问来源于stack exchange,提问作者Shurmajee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 08:52:41