使用CDK部署ECS镜像至已有ALB报错,需修改哪些配置?
问题:CDK使用已有ALB部署ECS Fargate服务报错
我尝试用CDK把ECS镜像部署到已有的Application Load Balancer(ALB)和VPC中,编写的代码如下:
// Reference existing ALB const alb = elbv2.ApplicationLoadBalancer.fromApplicationLoadBalancerAttributes( this, "ImportedALB", { securityGroupId: "sg-XXXXXXXX", loadBalancerArn: "arn:aws:elasticloadbalancing:us-east-1:XXXXXXX:listener/app/alb-appliance/XXXXX/XXXXX", } ); // Create higher level construct containing the Fargate service with a load balancer new ecspatterns.ApplicationLoadBalancedFargateService( this, "amazon-ecs-sample", { loadBalancer: alb, cluster: cluster, circuitBreaker: { rollback: true, }, memoryLimitMiB: 512, cpu: 256, assignPublicIp: false, desiredCount: 1, taskImageOptions: { image: image, containerPort: 80, logDriver: ecs.LogDrivers.awsLogs({ streamPrefix: id, logRetention: logs.RetentionDays.ONE_YEAR, }), }, } );
运行cdk diff命令时出现如下错误:
Error: Can only call addTargets() when using a constructed Load Balancer or an imported Load Balancer with specified vpc; construct a new TargetGroup and use addTargetGroup at ApplicationListener.addTargets (C:\Users\Documents\GitHub\cdk-workshop-ts\node_modules\aws-cdk-lib\aws-elasticloadbalancingv2\lib\alb\application-listener.js:1:5736) at new ApplicationLoadBalancedServiceBase (C:\Users\Documents\GitHub\cdk-workshop-ts\node_modules\aws-cdk-lib\aws-ecs-patterns\lib\base\application-load-balanced-service-base.js:1:3657) at new ApplicationLoadBalancedFargateService (C:\Users\Documents\GitHub\cdk-workshop-ts\node_modules\aws-cdk-lib\aws-ecs-patterns\lib\fargate\application-load-balanced-fargate-service.js:1:601) at new ECSServiceStack (C:\Users\Documents\GitHub\cdk-workshop-ts\lib\cdk-workshop-ts-stack.ts:43:5) at Object.<anonymous> (C:\Users\Documents\GitHub\cdk-workshop-ts\bin\cdk-workshop-ts.ts:7:1) at Module._compile (node:internal/modules/cjs/loader:1376:14) at Module.m._compile (C:\Users\Documents\GitHub\cdk-workshop-ts\node_modules\ts-node\src\index.ts:1618:23) at Module._extensions..js (node:internal/modules/cjs/loader:1435:10) at Object.require.extensions.<computed> [as .ts] (C:\Users \Documents\GitHub\cdk-workshop-ts\node_modules\ts-node\src\index.ts:1621:12)
请问需要修改哪些设置才能解决该报错?
解决方案
这个报错的核心原因是:ApplicationLoadBalancedFargateService这个高层构造在处理导入的已有ALB时,无法自动创建目标组和监听规则,必须手动完成这些关联操作,同时导入ALB时必须指定VPC参数。
具体修改分两步:
1. 修正ALB导入代码,补充VPC参数
导入已有ALB时,必须明确传入VPC信息(可以直接复用ECS集群的VPC),否则CDK无法确定资源的网络环境;同时要注意ALB的ARN必须是负载均衡器本身的ARN,不是监听器的ARN:
// Reference existing ALB with VPC specified const alb = elbv2.ApplicationLoadBalancer.fromApplicationLoadBalancerAttributes( this, "ImportedALB", { securityGroupId: "sg-XXXXXXXX", loadBalancerArn: "arn:aws:elasticloadbalancing:us-east-1:XXXXXXX:loadbalancer/app/alb-appliance/XXXXX", vpc: cluster.vpc, // 关键:补充VPC参数,用集群关联的VPC即可 } );
2. 放弃高层构造,手动搭建Fargate服务+目标组+监听规则
ApplicationLoadBalancedFargateService是封装好的快捷构造,对已有ALB的支持有限。更可靠的方式是用基础构造手动实现:
// 1. 创建Fargate任务定义 const taskDefinition = new ecs.FargateTaskDefinition(this, "TaskDef", { memoryLimitMiB: 512, cpu: 256, }); // 2. 添加容器到任务定义 taskDefinition.addContainer("AppContainer", { image: image, portMappings: [{ containerPort: 80 }], logging: ecs.LogDrivers.awsLogs({ streamPrefix: id, logRetention: logs.RetentionDays.ONE_YEAR, }), }); // 3. 创建Fargate服务 const fargateService = new ecs.FargateService(this, "FargateService", { cluster: cluster, taskDefinition: taskDefinition, circuitBreaker: { rollback: true }, assignPublicIp: false, desiredCount: 1, }); // 4. 创建Application目标组,关联Fargate服务 const targetGroup = new elbv2.ApplicationTargetGroup(this, "ECSTargetGroup", { vpc: cluster.vpc, targetType: elbv2.TargetType.IP, // Fargate任务用动态IP,必须选IP类型 port: 80, targets: [fargateService], }); // 5. 获取ALB的已有监听器(二选一) // 方式一:已知监听器ARN时直接导入 const listener = elbv2.ApplicationListener.fromApplicationListenerAttributes(this, "ImportedListener", { listenerArn: "arn:aws:elasticloadbalancing:us-east-1:XXXXXXX:listener/app/alb-appliance/XXXXX/XXXXX", securityGroup: alb.securityGroup, }); // 方式二:从ALB实例中获取已存在的监听器(比如默认80端口的监听器) // const listener = alb.listeners[0]; // 6. 给监听器添加路由规则,将流量转发到目标组 listener.addTargetGroups("ECSTargetGroupRule", { targetGroups: [targetGroup], conditions: [elbv2.ListenerCondition.pathPatterns(["/app/*"])], // 根据业务需求设置路由规则 priority: 10, });
关键说明:
- 目标组的
targetType必须设为IP,因为Fargate任务使用动态分配的IP地址,无法用INSTANCE类型关联。 - 监听器的路由规则(
conditions)可以根据实际业务调整,比如路径匹配、主机头匹配等。 - 如果ALB已有多个监听器,要确保选择正确的监听器进行规则添加。
内容的提问来源于stack exchange,提问作者Tom Henricksen
相关产品推荐
相关产品推荐

