CDK创建带经典负载均衡器的ASG时EC2访问异常、健康主机数为0
问题根因与修复方案
两个故障现象(经典负载均衡器后端健康主机数为0、EC2公网无法访问Web/Instance Connect连接失败)均由配置缺失导致,核心问题点和修复方式如下:
- 公网子网实例未分配公网IP:CDK中Auto Scaling Group在公网子网启动实例时,默认不会自动关联公网IP。没有公网IP的实例既无法响应公网发起的HTTP、SSH连接请求,也无法正常访问公网yum源,直接导致写在user data里的httpd安装脚本执行失败,Web服务根本没启动。
- 安全组默认规则未放通必要流量:CDK自动创建的CLB、EC2安全组默认不会放通CLB健康检查流量、SSH连接流量、公网HTTP访问流量,流量直接被安全组拦截。
- 代码逻辑顺序与健康检查配置不全:原代码先给CLB添加ASG目标、后配置监听器,顺序错误;同时健康检查仅指定端口,未明确检查路径和协议,容易出现检查异常。
修复后完整代码
Vpc vpc=new Vpc(this,"MyVPC"); // 配置CLB安全组,放通公网80端口入站 SecurityGroup clbSg = SecurityGroup.Builder.create(this,"ClbSg") .vpc(vpc) .allowAllOutbound(true) .build(); clbSg.addIngressRule(Peer.anyIpv4(), Port.tcp(80), "Allow public HTTP access"); // 配置EC2实例安全组 SecurityGroup instanceSg = SecurityGroup.Builder.create(this,"InstanceSg") .vpc(vpc) .allowAllOutbound(true) .build(); // 放通CLB来源的80端口流量,用于健康检查和请求转发 instanceSg.addIngressRule(Peer.securityGroupId(clbSg.getSecurityGroupId()), Port.tcp(80), "Allow HTTP from CLB"); // 放通22端口入站,支持Instance Connect连接 instanceSg.addIngressRule(Peer.anyIpv4(), Port.tcp(22), "Allow SSH for Instance Connect"); AutoScalingGroup asg = AutoScalingGroup.Builder.create(this,"AutoScalingGroup") .vpcSubnets(SubnetSelection.builder() .subnetType(SubnetType.PUBLIC) .build()) .vpc(vpc) .instanceType(InstanceType.of(InstanceClass.BURSTABLE2, InstanceSize.MICRO)) .machineImage(new AmazonLinuxImage()) .minCapacity(1) .desiredCapacity(5) .maxCapacity(10) .securityGroup(instanceSg) .associatePublicIpAddress(true) // *关键配置*:公网子网实例自动分配公网IP .build(); asg.addUserData("#!/bin/bash\n" + "# install httpd (Linux 2 version)\n" + "yum update -y\n" + "yum install -y httpd\n" + "systemctl start httpd\n" + "systemctl enable httpd\n" + "echo \"<h1>Hello World from $(hostname -f)</h1>\" > /var/www/html/index.html"); LoadBalancer loadbalancer=LoadBalancer.Builder.create(this,"ElasticLoadBalancer") .vpc(vpc) .internetFacing(true) .securityGroup(clbSg) .healthCheck(software.amazon.awscdk.services.elasticloadbalancing.HealthCheck.builder() .port(80) .path("/index.html") .healthyThresholdCount(2) .unhealthyThresholdCount(2) .interval(Duration.seconds(30)) .build()) .build(); // 先添加监听器,再绑定后端目标 loadbalancer.addListener(LoadBalancerListener.builder().externalPort(80).build()); loadbalancer.addTarget(asg);
部署后验证
- 部署完成后等待3-5分钟,等待ASG拉起新实例、user data脚本执行完成。建议手动终止旧的异常实例,让ASG自动启动新配置的实例,避免旧实例配置残留影响结果。
- 单实例验证:选中任意一台ASG创建的新实例,通过公网IP访问80端口,确认能正常返回Hello World页面;测试Instance Connect功能,确认可以正常连接实例。
- CLB验证:查看CLB目标实例健康状态,等待所有5台实例状态变为Healthy后,通过CLB的DNS名称访问,确认请求可以正常分发到后端实例。
内容的提问来源于stack exchange,提问作者smallConfluence
相关产品推荐
相关产品推荐

