Believe it or not, VPC does not provide native NAT functionality. Hopefully, someday, we’ll get a NAT equivalent to IGW. Until then, NAT functionality is implemented through an EC2 NAT instance, usually running Linux.
“NAT Instance: An EC2 instance that provides Port Address Translation for non-EIP instances to access the Internet via the Internet Gateway.”
“Instances without EIPs can route their traffic through a NAT instance to access the Internet. These instances use the EIP of the NAT instance to traverse the Internet. The NAT instance allows outbound communication but doesn’t enable machines on the Internet to initiate a connection to the privately addressed machines using NAT..” –(AWS VPC FAQ)
NAT instances must be located on a ‘public’ VPC subnet, which is one that routes all internet traffic through an IGW.
Smaller instances have a greater chance of being negatively impacted by resource contention, which includes network throughput. Should your applications transfer large amounts of data, better performance could be achieved by increasing the size of your NAT gateways(s).
Egress filtering is often a consideration. It would be wise to pre-allocate VPC EIPS for NAT early, at least 1 for each AWS region you might ever need!. Imagine the horror of failing to us-west-2 for DR only to discover that none of your partners will talk to you!
When associating a VPC subnet with a NAT instance, it is important that you match availability zones! For example, if your vpc configuration spans 4 availability zones in us-east-1, your VPC route tables might look like:
subnet-id (subnet-zone) private-subnet nat-instance-id (nat-zone)
subnet-abcdefg (us-east-1a) 172.16.0.100 -> i-abcdefg (us-east-1a)
subnet-abcdefh (us-east-1b) 172.16.0.101 -> i-abcdefh (us-east-1b)
subnet-abcdefi (us-east-1c) 172.16.0.102 -> i-abcdefi (us-east-1c)
subnet-abcdefj (us-east-1d) 172.16.0.103 -> i-abcdefj (us-east-1d)
The purpose here is to isolate failure, if AWS is having problems in us-east-1a you don’t want to risk impacting us-east-1b by associating it with i-abcdefg .
Launch an instance from the official AWS NAT AMI, or roll your own.
Attach an EIP.
Update the operating system
Disable source/dest check
Update VPC route tables
Updating a subnet route table via AWS console
Navigate: VPC->Route Tables.
Select the subnet you’d like to NAT
Disassociate subnet from IGW (0.0.0.0/0 -> igw xyz)
Associate subnet with NAT instance id, preferably without crossing availability zones
Test from a host located on the subnet in question
High availability is not a native feature of the AWS NAT AMI.
You’ll need to implement that yourself.
Utilize autoscaling for high availability. Create an autoscaling group for each NAT instance. Set min, max and desired hosts to 1, such that an instance failure will cause a rebuild of the nat instance. Your boot process will need to attach an EIP, or better, a floating ENI which is already associated with your subnet route tables.
Update your routing tables to direct traffic to a healthy NAT instance, possibly in another zone.
For failover, your nat instances might share a network adapter, such that moving the eni to another host will seamlessly redirect internet connectivity without the need to update any route tables.