-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Description
When using ec2.VpcNetwork the defaults are to create NAT gateways. I originally scoped this down to just creating a single NAT gateway for my public subnet, and a month later was slogged with a $90 AWS bill, with almost all of that cost attributed to the NAT gateway.
So today I decided to try and rework it to remove the NAT gateway (since my app really doesn't need it anyway). Tried removing the key, but that uses the defaults (and makes more), so I tried setting the key to 0. Example config:
const vpc = new ec2.VpcNetwork(this, 'Tokenized-VPC', {
natGateways: 0,
// natGatewayPlacement: {subnetName: 'Public'},
subnetConfiguration: [
{
cidrMask: 26,
name: 'Public',
subnetType: ec2.SubnetType.Public,
},
{
name: 'Application',
subnetType: ec2.SubnetType.Private,
},
],
defaultInstanceTenancy: ec2.DefaultInstanceTenancy.Default,
});
When I ran cdk diff, I got a number of errors back
Exactly one of [NetworkInterfaceId, VpcPeeringConnectionId, GatewayId, EgressOnlyInternetGatewayId, InstanceId, NatGatewayId] must be specified and not empty
1/9 | 8:27:39 am | UPDATE_FAILED | AWS::EC2::Route | Foo-VPC/ApplicationSubnet2/DefaultRoute (FooVPCApplicationSubnet2DefaultRoute2325F2C6) Exactly one of [NetworkInterfaceId, VpcPeeringConnectionId, GatewayId, EgressOnlyInternetGatewayId, InstanceId, NatGatewayId] must be specified and not empty
VpcPrivateSubnet.addDefaultRouteToNAT (/foo/bar/deploy/aws-ec2/node_modules/@aws-cdk/aws-ec2/lib/vpc.js:259:9)
\_ VpcPrivateSubnet.addDefaultNatRouteEntry (/foo/bar/deploy/aws-ec2/node_modules/@aws-cdk/aws-ec2/lib/vpc.js:316:14)
\_ VpcNetwork.privateSubnets.forEach /foo/bar/deploy/aws-ec2/node_modules/@aws-cdk/aws-ec2/lib/vpc.js:127:31)
\_ Array.forEach (<anonymous>)
\_ new VpcNetwork (/foo/bar/deploy/aws-ec2/node_modules/@aws-cdk/aws-ec2/lib/vpc.js:120:33)
\_ new TokenizedEC2Stack (/foo/bar/deploy/aws-ec2/bin/tokenized.js:15:21)
\_ Object.<anonymous> (/foo/bar/deploy/aws-ec2/bin/tokenized.js:243:1)
\_ Module._compile (internal/modules/cjs/loader.js:689:30)
\_ Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
\_ Module.load (internal/modules/cjs/loader.js:599:32)
\_ tryModuleLoad (internal/modules/cjs/loader.js:538:12)
\_ Function.Module._load (internal/modules/cjs/loader.js:530:3)
\_ Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
\_ startup (internal/bootstrap/node.js:279:19)
\_ bootstrapNodeJSCore (internal/bootstrap/node.js:696:3)
This implies that there isn't good support currently for when NAT gateways is 0 (may need to improve checks around things there), and as best as I could tell skimming the docs, there isn't a great way to use VpcNetwork without a NAT gateway.
Presumably I can use the override methods to 'reach in' and patch those keys manually, probably setting GatewayId/EgressOnlyInternetGatewayId it will probably work, but I was wondering if there is currently a 'better' solution than that when:
- I have a public subnet that I just want to connect directly to the net (and control connections through security groups, etc)
- I have a private subnet that only requires egress
It may be that most people using CDK have requirements greater than mine and/or don't mind about the NAT gateway costs, but I feel like someone just playing around may be shockingly surprised at how much $$ the defaults end up costing them. Maybe some doco changes to call this out more explicitly? And/or an example that supports using methods other than the NAT gateway (eg. as mentioned above, or an example that shows how to set it up using the old way with a NAT instance so we can run it on a micro for tiny workloads without costing the world)