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

基于AWS CDK将Lambda迁移至ECS/EKS及差异咨询

Lambda冷启动迁移至ECS/EKS的CDK最小改动方案及核心差异

一、Lambda与ECS/EKS核心差异

  • 执行模型:Lambda是事件驱动的无服务器函数,按需启动执行,完成后销毁;ECS/EKS是容器集群,容器实例长期运行或按需缩放,支持持续服务和一次性任务。
  • 冷启动表现:Lambda存在冷启动(初始化运行时、加载代码/层),首次请求或闲置后重启会有延迟;ECS/EKS容器启动后持续运行,无冷启动延迟(新实例启动除外,可通过预缩放规避)。
  • 资源控制:Lambda资源(内存、CPU)绑定,配置选项有限;ECS/EKS可自定义容器CPU、内存、存储等资源,支持GPU等特殊硬件。
  • 部署方式:Lambda支持代码包、Docker镜像两种部署;ECS/EKS仅支持容器镜像,需管理集群、任务定义、服务等组件。
  • 事件触发:Lambda原生集成AWS全品类事件源(API Gateway、SQS、EventBridge等);ECS/EKS需借助中间组件(如EventBridge触发任务、API Gateway通过VpcLink对接服务)实现事件驱动。
  • 成本模型:Lambda按请求数+执行时间付费;ECS/EKS按实例/资源使用时长付费,Fargate模式按任务运行时长付费。

二、CDK最小代码改动迁移方案

由于现有代码已使用DockerImageFunction,可复用Docker镜像实现最小改动迁移,优先选择ECS Fargate(无服务器容器,无需管理EC2实例)。

1. 添加ECS依赖

在CDK代码顶部导入ECS相关模块:

import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as targets from 'aws-cdk-lib/aws-events-targets';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';

2. 复用Docker镜像创建ECS任务与服务

以amaServiceLambda为例,替换Lambda创建逻辑为ECS Fargate服务:

// 在AmaStack类中添加ECS服务属性
public readonly amaServiceEcsService: ecs.FargateService;

// 在constructor中创建ECS集群、任务定义与服务
const ecsCluster = new ecs.Cluster(this, `AmaEcsCluster-${props.stage}`, {
  vpc: props.vpcStack.vpc,
  clusterName: `AmaEcsCluster-${props.stage}`,
});

// 复用Lambda的IAM托管策略
const managedPolicies = [
  ManagedPolicy.fromAwsManagedPolicyName('AWSLambdaExecute'),
  ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLambdaInsightsExecutionRolePolicy'),
  ManagedPolicy.fromAwsManagedPolicyName('AmazonBedrockFullAccess'),
  ManagedPolicy.fromAwsManagedPolicyName('AmazonS3FullAccess'),
];

// 创建ECS任务角色(复用Lambda权限)
const amaTaskRole = new Role(this, `AmaServiceTaskRole-${props.stage}`, {
  roleName: `AmaServiceTaskRole-${props.stage}`,
  assumedBy: new ServicePrincipal('ecs-tasks.amazonaws.com'),
  managedPolicies: managedPolicies,
});

// 创建Fargate任务定义
const amaTaskDefinition = new ecs.FargateTaskDefinition(this, `AmaServiceTaskDef-${props.stage}`, {
  memoryLimitMiB: 2048, // 对应Lambda的内存配置
  cpu: 1024,
  taskRole: amaTaskRole,
  executionRole: amaTaskRole, // 复用同一角色简化配置
});

// 添加容器,复用Lambda使用的Docker镜像
amaTaskDefinition.addContainer(`AmaServiceContainer-${props.stage}`, {
  image: ecs.ContainerImage.fromAsset('path/to/your/docker/context'), // 或使用ECR镜像ARN
  environment: {
    // 完全复用Lambda的环境变量
    BUCKET_PREFIX: AMA.BUCKET_PREFIX,
    MODEL: AMA.MODEL,
    EMBEDDING: AMA.EMBEDDING,
    LANGCHAIN_TRACING_V2: 'true',
    LANGCHAIN_ENDPOINT: props.langchainEndpoint,
    LANGCHAIN_API_KEY: props.langchainApiKey,
    LANGCHAIN_PROJECT: `AMA-${props.stage}`,
    STAGE_NAME: props.stage,
    BUCKET_PREFIX: getCommonBucketName(props.accountId, props.stage),
    LLM_TOP_P: '0.2',
    OPENAI_API_KEY: openAIKey.unsafeUnwrap(),
    LLM_TEMPERATURE: '0.2',
    RETRIEVER_K: '3',
    ...commonEnvironmentVariables,
  },
  logging: ecs.LogDriver.awsLogs({ streamPrefix: `AmaService-${props.stage}` }),
  portMappings: [{ containerPort: 8080 }], // 容器暴露端口,用于API Gateway对接
});

// 创建Fargate服务
this.amaServiceEcsService = new ecs.FargateService(this, `AmaServiceEcsService-${props.stage}`, {
  cluster: ecsCluster,
  taskDefinition: amaTaskDefinition,
  desiredCount: 1,
  assignPublicIp: false,
  vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
});

// 授权容器访问Secret(复用Lambda的授权逻辑)
openAISecret.grantRead(amaTaskRole);

3. 修改API Gateway集成

将LambdaIntegration替换为ECS服务集成,通过VpcLink对接私有子网中的ECS服务:

// 创建VpcLink对接ECS服务
const vpcLink = new apigateway.VpcLink(this, `AmaServiceVpcLink-${props.stage}`, {
  targets: [this.amaServiceEcsService],
});

// 替换原有Lambda集成
this.configureMethodOnResource(AMAFeedbackResource, Methods.POST, new apigateway.HttpIntegration(
  `http://${this.amaServiceEcsService.loadBalancer.loadBalancerDnsName}/feedback`,
  { vpcLink: vpcLink }
));

注:若使用ALB模式的ECS服务(ecsPatterns.ApplicationLoadBalancedFargateService),可直接用ALB域名作为集成地址。

4. 迁移定时触发的Lambda(如embeddingPollingLambda)

用EventBridge直接触发ECS一次性任务,替代Lambda:

// 创建定时任务的ECS任务定义
const embeddingPollingTaskDef = new ecs.FargateTaskDefinition(this, `EmbeddingPollingTaskDef-${props.stage}`, {
  memoryLimitMiB: 1024,
  cpu: 512,
  taskRole: new Role(this, `EmbeddingPollingTaskRole-${props.stage}`, {
    roleName: `EmbeddingPollingTaskRole-${props.stage}`,
    assumedBy: new ServicePrincipal('ecs-tasks.amazonaws.com'),
    managedPolicies: managedPolicies,
  }),
});

embeddingPollingTaskDef.addContainer(`EmbeddingPollingContainer-${props.stage}`, {
  image: ecs.ContainerImage.fromAsset('path/to/your/docker/context'),
  environment: {
    ...commonEnvironmentVariables,
    EMBEDDING_LOG_QUEUE: this.embeddingLogQueue.queueUrl,
  },
  logging: ecs.LogDriver.awsLogs({ streamPrefix: `EmbeddingPolling-${props.stage}` }),
});

// 修改EventBridge规则目标为ECS任务
const rule = new Rule(this, `EventBridge-${EventBridgeRules.AMA_LOG_POLLING}`, {
  description: `Rule to trigger embedding polling task every ${EMBEDDING_LOG_POLLING_INTERVAL} minutes`,
  schedule: Schedule.rate(EMBEDDING_LOG_POLLING_INTERVAL),
});

if (ACTIVE_EMBEDDING_LOG_STACKS.find(stack => stack.accountId === props.accountId && stack.stageName === props.stage)) {
  rule.addTarget(new targets.EcsTask({
    cluster: ecsCluster,
    taskDefinition: embeddingPollingTaskDef,
    taskCount: 1,
    subnetSelection: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
  }));
}

5. 最小改动关键策略

  • 复用Docker镜像:直接使用Lambda的Docker镜像,无需修改业务代码(一次性任务无需改为Web服务)。
  • 复用权限与环境变量:复制Lambda的IAM策略、环境变量到ECS任务,避免重新配置权限。
  • 逐步迁移:优先迁移冷启动严重的核心Lambda,其余Lambda保留,逐步替换,降低风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:18:10