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

如何使用CDK将Lambda部署至已有S3存储桶?

从Serverless框架迁移CDK:自定义S3桶部署Lambda代码的正确方式

你当前代码的核心问题

  1. 路径不匹配:BucketDeployment上传的代码包文件名是CDK自动生成的带哈希值格式(如asset.abc123.zip),但Lambda配置里硬写了serverless/hello.zip,实际部署时会找不到文件。
  2. 缺失依赖关系:CDK默认不会保证代码上传完成后再创建Lambda,可能出现Lambda先部署但S3中还没有代码包的情况。
  3. 手动指定文件名不可靠:硬写hello.zip会跳过CDK的资产版本控制机制,代码更新后可能因缓存问题无法触发Lambda版本更新。

CDK的自动上传机制及推荐实现

CDK没有像Serverless那样直接指定桶名一键上传的简化配置,但可以通过Asset类实现自动打包、上传到自定义桶,同时保留版本控制能力,是更符合CDK风格的实现方式:

推荐实现代码

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as dotenv from "dotenv";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as sqs from "aws-cdk-lib/aws-sqs";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as lambdaEventSources from "aws-cdk-lib/aws-lambda-event-sources";
import { Asset } from "aws-cdk-lib/aws-s3-assets";
import { convertDayOfWeekToCron } from "../utils/convertDay";

// 环境配置逻辑(保留原有逻辑)
const environment = process.env.NODE_ENV || "dev";
dotenv.config({ path: `.env.${environment}` });

export class AwsCdkEventsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // 导入已有的自定义S3桶
    const lambdaBucket = s3.Bucket.fromBucketName(
      this,
      "LambdaBucket",
      process.env.S3_BUCKET || "",
    );

    // 创建S3 Asset:自动打包lambda目录并上传到自定义桶
    const lambdaCodeAsset = new Asset(this, "LambdaCodeAsset", {
      path: "./lambda",
      bucket: lambdaBucket,
      keyPrefix: "scheduler-service",
      exclude: ["**/*.ts"],
    });

    // 定义Lambda函数,引用自定义桶中的Asset代码
    const helloWorldFunction = new lambda.Function(this, "HelloWorldFunction", {
      runtime: lambda.Runtime.NODEJS_20_X,
      // 直接使用Asset生成的S3对象键,无需手动指定文件名
      code: lambda.Code.fromBucket(lambdaBucket, lambdaCodeAsset.s3ObjectKey),
      handler: "hello.handler",
      environment: {
        STAGE: process.env.NODE_ENV || "dev",
      },
    });

    // SQS事件源配置(保留原有逻辑)
    const queueArn: string = process.env.SQS_ARN || "";
    const queue = sqs.Queue.fromQueueArn(this, "ImportQueue", queueArn);
    queue.grantConsumeMessages(helloWorldFunction);
    helloWorldFunction.addEventSource(
      new lambdaEventSources.SqsEventSource(queue),
    );
  }
}

关键改进点说明

  • 自动打包与版本控制:Asset类会自动将./lambda目录打包成带哈希值的zip包,代码更新时哈希值变化,会自动触发Lambda版本更新,避免缓存问题。
  • 依赖自动处理:CDK会自动识别lambdaCodeAsset与helloWorldFunction的依赖关系,确保代码先上传到S3,再创建/更新Lambda。
  • 简化配置:无需手动配置BucketDeployment,Asset已整合打包、上传逻辑,更贴合CDK的声明式编程风格。

备选方案:基于BucketDeployment的修正

如果坚持使用BucketDeployment,需要修正路径和依赖关系:

// 保留BucketDeployment配置
const lambdaCodeAsset = new s3Deploy.BucketDeployment(
  this,
  "LambdaCodeAssetDeployment",
  {
    sources: [s3Deploy.Source.asset("./lambda", { exclude: ["**/*.ts"] })],
    destinationBucket: lambdaBucket,
    destinationKeyPrefix: "scheduler-service",
  },
);

// 创建Lambda时引用正确的文件路径,并添加依赖
const helloWorldFunction = new lambda.Function(this, "HelloWorldFunction", {
  runtime: lambda.Runtime.NODEJS_20_X,
  code: lambda.Code.fromBucket(lambdaBucket, lambdaCodeAsset.sourceAsset?.s3ObjectKey || ""),
  handler: "hello.handler",
  environment: {
    STAGE: process.env.NODE_ENV || "dev",
  },
});
// 强制Lambda等待代码上传完成
helloWorldFunction.node.addDependency(lambdaCodeAsset);

但这种方式不如Asset方案简洁,推荐优先使用Asset实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 23:48:15