使用AWS CDK配置VPC:双公有子网单路由表异常排查
问题排查:CDK创建VPC时自动关联默认路由表的异常情况
尝试创建两个公有子网并关联至同一个路由表,特意将
subnetConfiguration设为空数组以避免自动创建子网和路由表,但当前CDK代码仍生成了两个关联默认路由表的公有子网。代码如下:
import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; export class DevVpcStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Create the VPC const vpc = new ec2.Vpc(this, 'DevVPC', { cidr: '10.0.0.0/16', subnetConfiguration: [], // Do not create any subnets automatically enableDnsHostnames: true, enableDnsSupport: true, }); // Create public subnets const publicSubnet1 = new ec2.CfnSubnet(this, 'PublicSubnet1', { vpcId: vpc.vpcId, cidrBlock: '10.0.1.0/24', availabilityZone: cdk.Stack.of(this).availabilityZones[0], mapPublicIpOnLaunch: true, }); const publicSubnet2 = new ec2.CfnSubnet(this, 'PublicSubnet2', { vpcId: vpc.vpcId, cidrBlock: '10.0.2.0/24', availabilityZone: cdk.Stack.of(this).availabilityZones[1], mapPublicIpOnLaunch: true, }); // Create a single route table const routeTable = new ec2.CfnRouteTable(this, 'PublicRouteTable', { vpcId: vpc.vpcId, }); // Associate the subnets with the route table new ec2.CfnSubnetRouteTableAssociation(this, 'PublicSubnet1RouteTableAssociation', { subnetId: publicSubnet1.ref, routeTableId: routeTable.ref, }); new ec2.CfnSubnetRouteTableAssociation(this, 'PublicSubnet2RouteTableAssociation', { subnetId: publicSubnet2.ref, routeTableId: routeTable.ref, }); } }
问题原因
- 所有AWS VPC默认都会生成一个默认路由表,当通过
CfnSubnet手动创建子网时,AWS会自动将子网关联到这个默认路由表,而非你手动创建的自定义路由表。你看到的“独立路由表”其实是VPC的默认路由表,并非CDK额外生成。 - 代码中缺少互联网网关及路由配置,即使子网关联了自定义路由表,也无法正常访问公网。
解决方案
方案1:使用CDK高层抽象(推荐)
改用CDK封装的高层API,简化操作并避免底层资源的默认行为冲突:
import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; export class DevVpcStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // 创建VPC,禁用自动子网创建 const vpc = new ec2.Vpc(this, 'DevVPC', { cidr: '10.0.0.0/16', subnetConfiguration: [], enableDnsHostnames: true, enableDnsSupport: true, natGateways: 0, // 公有子网无需NAT网关 maxAzs: 2, // 匹配子网使用的可用区数量 }); // 创建公有子网 const publicSubnet1 = new ec2.Subnet(this, 'PublicSubnet1', { vpcId: vpc.vpcId, cidrBlock: '10.0.1.0/24', availabilityZone: this.availabilityZones[0], mapPublicIpOnLaunch: true, }); const publicSubnet2 = new ec2.Subnet(this, 'PublicSubnet2', { vpcId: vpc.vpcId, cidrBlock: '10.0.2.0/24', availabilityZone: this.availabilityZones[1], mapPublicIpOnLaunch: true, }); // 创建公有路由表并添加互联网路由 const publicRouteTable = new ec2.RouteTable(this, 'PublicRouteTable', { vpc, }); // 添加互联网网关及路由 const igw = vpc.addInternetGateway('InternetGateway'); new ec2.Route(this, 'PublicInternetRoute', { routeTable: publicRouteTable, destinationCidrBlock: '0.0.0.0/0', gateway: igw, }); // 关联子网到公有路由表 publicSubnet1.addRouteTableAssociation('Subnet1RouteTableAssoc', publicRouteTable); publicSubnet2.addRouteTableAssociation('Subnet2RouteTableAssoc', publicRouteTable); } }
方案2:保留底层Cfn资源调整
如果坚持使用Cfn资源,需补充互联网网关配置,确保子网正确关联自定义路由表:
import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; export class DevVpcStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Create the VPC const vpc = new ec2.Vpc(this, 'DevVPC', { cidr: '10.0.0.0/16', subnetConfiguration: [], enableDnsHostnames: true, enableDnsSupport: true, }); // Create public subnets const publicSubnet1 = new ec2.CfnSubnet(this, 'PublicSubnet1', { vpcId: vpc.vpcId, cidrBlock: '10.0.1.0/24', availabilityZone: cdk.Stack.of(this).availabilityZones[0], mapPublicIpOnLaunch: true, }); const publicSubnet2 = new ec2.CfnSubnet(this, 'PublicSubnet2', { vpcId: vpc.vpcId, cidrBlock: '10.0.2.0/24', availabilityZone: cdk.Stack.of(this).availabilityZones[1], mapPublicIpOnLaunch: true, }); // 创建互联网网关并关联到VPC const internetGateway = new ec2.CfnInternetGateway(this, 'InternetGateway'); new ec2.CfnVPCGatewayAttachment(this, 'VpcIgwAttachment', { vpcId: vpc.vpcId, internetGatewayId: internetGateway.ref, }); // Create a single route table const routeTable = new ec2.CfnRouteTable(this, 'PublicRouteTable', { vpcId: vpc.vpcId, }); // 添加互联网路由到自定义路由表 new ec2.CfnRoute(this, 'PublicInternetRoute', { routeTableId: routeTable.ref, destinationCidrBlock: '0.0.0.0/0', gatewayId: internetGateway.ref, }); // Associate the subnets with the route table new ec2.CfnSubnetRouteTableAssociation(this, 'PublicSubnet1RouteTableAssociation', { subnetId: publicSubnet1.ref, routeTableId: routeTable.ref, }); new ec2.CfnSubnetRouteTableAssociation(this, 'PublicSubnet2RouteTableAssociation', { subnetId: publicSubnet2.ref, routeTableId: routeTable.ref, }); } }
注:AWS会自动将新子网关联到默认路由表,但手动创建的
CfnSubnetRouteTableAssociation会覆盖这个默认关联,最终子网会绑定到自定义路由表。
内容的提问来源于stack exchange,提问作者jkhan_prog
相关产品推荐
相关产品推荐

