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

升级Lambda至Python3.9后CloudFormation自定义资源响应异常排查

问题原因及解决办法

你遇到的错误核心是:Python 3.9及以上版本的AWS Lambda运行时不再默认内置cfn-response模块。

在Python 3.6的Lambda运行时中,AWS默认把cfn-response模块放在了运行环境的搜索路径里,所以你的代码能直接导入并调用它发送响应给CloudFormation。但升级到3.9后,这个模块被移除了,代码执行时会触发ModuleNotFoundError,导致函数中断,根本没机会向CloudFormation发送响应,最终出现“未收到自定义资源响应”的错误提示。

两种可行的修复方案

方案1:手动嵌入cfn-response模块代码

cfn-response本质是一个轻量的Python脚本,你可以直接把官方提供的源码复制到你的Lambda函数代码中,不用依赖内置模块。源码如下:

import json
import urllib3

SUCCESS = "SUCCESS"
FAILED = "FAILED"

http = urllib3.PoolManager()

def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False):
    responseUrl = event['ResponseURL']

    responseBody = {
        'Status' : responseStatus,
        'Reason' : 'See the details in CloudWatch Log Stream: ' + context.log_stream_name,
        'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
        'StackId' : event['StackId'],
        'RequestId' : event['RequestId'],
        'LogicalResourceId' : event['LogicalResourceId'],
        'NoEcho' : noEcho,
        'Data' : responseData
    }

    json_responseBody = json.dumps(responseBody)

    headers = {
        'content-type' : '',
        'content-length' : str(len(json_responseBody))
    }

    try:
        response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
        print("Status code:", response.status)
    except Exception as e:
        print("send(..) failed executing http.request(..):", e)

把这段代码放在你的Lambda函数开头,之后就可以像之前一样调用send()方法发送响应了。

方案2:改用boto3直接调用CloudFormation API

放弃依赖cfn-response,直接用boto3调用CloudFormation的send_response接口,这种方式更稳定,也不依赖Lambda运行时的内置模块。示例代码:

import boto3
import json

def lambda_handler(event, context):
    # 构造响应内容
    response_data = {
        # 这里可以放你需要返回给CloudFormation的自定义数据
    }

    cf_client = boto3.client('cloudformation')
    try:
        # 发送成功响应
        cf_client.send_response(
            StackName=event['StackId'],
            RequestId=event['RequestId'],
            LogicalResourceId=event['LogicalResourceId'],
            Status='SUCCESS',
            Reason='资源处理完成',
            PhysicalResourceId=context.log_stream_name,
            Data=response_data
        )
    except Exception as e:
        # 发送失败响应
        cf_client.send_response(
            StackName=event['StackId'],
            RequestId=event['RequestId'],
            LogicalResourceId=event['LogicalResourceId'],
            Status='FAILED',
            Reason=f'处理失败:{str(e)}',
            PhysicalResourceId=context.log_stream_name,
            Data={}
        )

验证建议

修复后可以先在Lambda控制台测试函数,模拟CloudFormation的自定义资源请求事件,查看函数日志确认是否成功发送响应,再重新部署CloudFormation模板。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 12:50:19