Skip to content

VPC: allow configuring NAT instances instead of gateways (and a 0 NAT gateways bug) #1305

@0xdevalias

Description

@0xdevalias

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)

Metadata

Metadata

Assignees

Labels

@aws-cdk/aws-ec2Related to Amazon Elastic Compute Cloud@aws-cdk/aws-ecs-patternsRelated to ecs-patterns librarydocs/generatedRelated to the generated API Reference documentationfeature-requestA feature should be added or improved.p0

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions