AWS CloudFormation部署Lambda遇S3 NoSuchKey错误及相关技术疑问
问题与解答:AWS CloudFormation部署Lambda时S3 NoSuchKey错误
问题背景
我尝试通过AWS CloudFormation创建S3桶,并向其中上传JavaScript代码,以下是我的CloudFormation脚本:
MyLambdaFunction: Type: AWS::Lambda::Function Properties: Description: > Lambda function to call a Docker image FunctionName: !Sub - '${TheEnv}-${TheAppNameForResources}-v1' - TheEnv: !Ref Environment TheAppNameForResources: !Ref AppNameForResources EphemeralStorage: Size: 10240 Code: S3Bucket: !Ref MyS3Bucket S3Key: "lambda-code.zip" Runtime: nodejs20.x Handler: index.handler Role: !GetAtt MyLambdaExecutionRole.Arn MyLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub - "${TheAppNameForResources}-${TheEnvName}-lambda-execution-role" - TheAppNameForResources: !Ref AppNameForResources TheEnvName: !Ref Environment AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: ['sts:AssumeRole'] Policies: - PolicyName: !Sub - "${TheAppNameForResources}-${TheEnvName}-lambda-execution-role-policy" - TheAppNameForResources: !Ref AppNameForResources TheEnvName: !Ref Environment PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - 'logs:CreateLogGroup' - 'logs:CreateLogStream' - 'logs:PutLogEvents' Resource: "*" MyS3Bucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub - '${TheEnv}-${TheAppNameForResources}-${TheBucketRegion}' - TheEnv: !Ref Environment TheAppNameForResources: !Ref AppNameForResources TheBucketRegion: !Ref AWS::Region
当我的CodePipeline运行时,出现以下错误:
资源处理程序返回消息:"获取对象时出错。S3错误代码:NoSuchKey。S3错误消息:指定的键不存在。(服务:Lambda,状态码:400,请求ID:6a1d0144-97ce-413a-8efe-94572ace7980)" (请求令牌:47866741-293b-8590-b5e8-508d9945265b,处理程序错误代码:InvalidRequest)
我的疑问:
- 向S3上传代码时,是否需要手动将文件压缩为ZIP包并手动上传?还是CloudFormation会自动完成此操作?
- 创建Lambda资源时,何时需要指定S3Key属性?该属性是否为必填项?
- 如果第一个问题的答案是需要手动操作,那么我是否无法在同一个CloudFormation模板中包含所有相关的S3资源?因为如果S3桶中没有ZIP包,MyLambdaFunction资源创建会失败。理想情况下,我是否需要先单独创建S3桶,上传ZIP包后再部署其余资源?
解答
1. ZIP包的处理方式
CloudFormation不会自动压缩代码并上传到S3。你需要自行将Lambda代码文件(如index.js等)打包成ZIP包,再上传到指定的S3桶。如果用CodePipeline部署模板,通常要在Pipeline中添加构建阶段(比如用CodeBuild),先完成代码打包,再上传到目标S3桶,最后执行CloudFormation部署。
2. S3Key的使用场景与必填性
当你通过S3存储Lambda代码时,S3Key是必填属性——它对应S3桶中代码ZIP包的对象键(即文件名称/路径)。Lambda代码配置有两种方式:
- 用S3存储代码:必须同时指定
S3Bucket和S3Key(若ZIP包有版本,还可添加S3ObjectVersion)。 - 内嵌代码到模板:使用
ZipFile属性(适合代码量小的场景,比如简单脚本),这种情况无需任何S3相关属性。
3. 同一模板部署S3桶与Lambda的解决方案
不需要拆分模板分两次部署,有几种可行方案:
- 调整CodePipeline阶段顺序:先执行CloudFormation创建S3桶,接着用CodeBuild把代码ZIP包上传到该桶,最后再执行CloudFormation部署Lambda(此时S3桶已存在代码包)。
- 使用自定义资源:编写Lambda自定义资源,在模板部署过程中自动完成代码打包并上传到新建的S3桶,适合复杂场景,但需要额外配置权限和代码。
- 内嵌代码(小体量场景):如果Lambda代码较短,直接用
ZipFile把代码写在模板里,无需依赖S3桶,示例如下:Code: ZipFile: | exports.handler = async (event) => { return { statusCode: 200, body: JSON.stringify('Hello from Lambda!'), }; };
内容的提问来源于stack exchange,提问作者Ram
相关产品推荐
相关产品推荐

