The Gist: In this post I discuss saving money (I’m saving $336/year) by replacing a NAT Gateway with a NAT Instance.
If you are a ‘tinkerer’ like me, you eventually wind-up over at AWS to play with some of their “blocks”. What I mean is, AWS tech can be thought of as Lego blocks: you can stack them in ways to craft a solution. Also, usually there is more than one way to bring about a result. This a big reason why I’m a fan of the service and tool offerings of AWS. If you have an idea for a new product or a money saving way to accomplishing the same, it is possible to try something without a lot of cost. This is particularly true with their free-tier and serverless offerings. On an earlier post: New Way to Run WordPress on AWS Fargate, I discuss how I wanted to circumvent using an “always on” server for this site that – I estimate – does not draw enough traffic to warrant the full on-demand price. I wanted to take the cost savings one step further by eliminating the NAT Gateway and replacing it with a NAT Instance.
The image above depicts the initial setup with AWS. This setup makes it easy to get started. Computing resources that you place in these subnets will have internet access without doing anything special on your part: the NACLs and Security Groups are setup to allow all traffic. That’s both good (get started easily) and bad (as resources are not adequately protected).
So, What Can You Do To Tighten Things Up?
One of the ways you can protect your computing resources is to place them in PRIVATE subnets*. This means that the internet cannot reach your resource and no resource in that subnet will be able to access the internet either. This is all well and good if your computing resources do not need internet access. Usually some level of internet access is required. So how can you access the internet but shut out the internet from connecting to your resources? This is where NAT Gateways come in: they allow resources in a private subnet to connect to services outside of you VPC while preventing external services from initiating connections with said resources. NAT Gateways are managed services, meaning you do not have to worry about its availability, scalability, or failures. For this service in the US East Ohio region you are charged:
- about a nickel ($0.045) per hour each hour it is provisioned
- about a nickel ($0.045) for each Gigabyte of data processed
- Data Transfer charges**
This translates into $32.40/month just for its availability. Who says a nickel doesn’t grow quickly? You are paying for an always on and always available service that you do not have to maintain, which is significant given the right circumstances. But what if you are just kicking the tires on some idea and do not need its bandwidth capabilities or its built-in fault tolerance just yet? Or, have development and QA environments that are not used 24×7 and will likely experience much lower data transfer rates?
Enter the NAT Instance
This is essentially an EC2 server playing the role of a NAT Gateway. There is no automatic failover and as with any EC2 resource you provision, you have to manage the instance yourself. You must also consider network performance of the instance. The hourly on-demand rate for a very small EC2 instance (t2.nano with .5GiB of memory) in the US East Ohio region is $0.0058 or $4.18/month for “always on”. You’ll pay more for larger and higher performing instances. You can always shut these down when you don’t need them and pay nothing – you cannot do this with NAT Gateways. For development and test environments or even pseudo-production needs like mine (where I want “always on” availability but do not need the level service as provided by a NAT Gateway) I think this is viable alternative.
$4 vs $32. ~$28/month savings
On an annual basis excluding (data transfers) you’ll save about $336 – how’s that for saving money? So needless to say I was eager to give this a go. So this is what I did:
- Provisioned a small EC2 instance: t2.nano running Linux in a public subnet
- ran 2 commands on the instance:
sysctl -w net.ipv4.ip_forward=1
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
- From the EC2 console, disable Source/Destination checks on the instance
- on the route table for the private subnet, route internet traffic (0.0.0.0/0) to the the instance
What Just Happened?
Once the EC2 instance is setup, the commands that are run basically turn the instance into a router, translating or substituting its public IP address for the source’s private IP address of your resource. The instance is acting as the originator of the request. When the response comes in, the instance will send it to the actual originator. Conceptually, this is called Network Address Translation (NAT).
Disabling Source/Destination check is required because, per AWS, every instance must be the source or destination of any traffic it sends or receives. NATs are handling traffic for other resources.
Finally, each private subnet must have a route out to the internet. This is done via route tables and in this case, traffic headed that way is routed to the NAT instance. The NAT instance sits in the public subnet and has access to the internet via the Internet Gateway.
All in all, I’m happy with the results and I experienced the cost savings immediately. So what’s the problem? Well, I consider the use case for this site (and anything else I’m developing so far) to be pseudo-production. Which means I want always-on, but don’t need it. Call it what it is: I want to do it on the cheap. (There, I said it.) Another aspect of “production” is having the ability to quickly replace a resource when it fails. You get this automatically with a NAT Gateway. So, this whole thing can be improved with the help of EC2 Auto Scaling Groups or ASGs, which have the ability to monitor resources and replace them automatically when they fail. Something that is not hard to do and will post details about this soon.
Props to Luk van den Borne and his post for the idea.
* Subnets are considered public when they have access to the internet and private when they don’t.
** Data Transfer charges are a separate study unto itself. Regardless of services used, bear in mind that you are usually charged for transferring data out and across availability zones and regions. There are no transfer charges within AZs or into AWS.