I'm going to have a number of EC2 instances in an Elastic Beanstalk autoscaling group in a default subnet in a VPC. The app on these EC2 instances needs to connect to a third party service who uses an IP address whitelist to allow access. So I need one or more static IP addresses that I can give to this service provider so they can be added to the whitelist. My understanding is that the only way to get a static IP is to get an Elastic IP address. And I can only associate the Elastic IP with one EC2 instance at a time - I can't associate it with my whole subnet or internet gateway (is this correct?). So do I need an Elastic IP for each EC2 instance, so each instance can be separately whitelisted? How would that work if the autoscaling adds another instance? Should I have one EC2 instance with an Elastic IP, and route all the outgoing traffic via that instance? If so, does that instance need to be solely for this purpose or can it be one of the instances that's running my app?
You need a NAT. This configuration is commonly used to support private subnets in VPC, there's quite a detailed guide here. Once your VPC is configured to use the NAT instance all the outbound traffic will be attributed to the EIP of the NAT instance.
If so, does that instance need to be solely for this purpose or can it be one of the instances that's running my app?
Technically you probably could, but it's not a good idea:
- It's good security to have roles isolated.
- You want your application servers to have similar or identical load profiles. If one instance has an extra 10% load because of the NAT then you'll have to scale up prematurely when you hit the limits of that instance. This will get worse as the NAT gets busier as more instances get added to your cluster.
- You want your application servers to be identical and ephemeral so you can tear them down and/or replace them whenever there's an issue or you need to scale. Having one application server which is different to the rest would be a major headache.
You might be able to get away with it if your instances are containerised but it's still probably not a great idea.
Also keep in mind that your NAT instance could be a single point of failure, so you may want to think about redundancy.
I understand this is an old thread - for someone who has a similar use-case now, AWS nat-gateway would be a better solution.
I don't have enough reputation to comment on the above answers, but I wanted to add some information you will need to know if using a NAT gateway to achieve this. When you create a NAT gateway, you select a subnet and an elastic IP address.
At first, I just added the NAT gateway to the same subnet that my elastic load balancer and EC2 instances were on. Then, you have to add the NAT gateway to your route table. I added the NAT gateway as the target for the IP of my external database server that I was trying to contact. This resulted in the applications hosted in my elastic beanstalk timing out. This is because they were trying to connect to that external database through the NAT. They reached the NAT, and then the NAT tried to reach out to my server over the internet, and looked it up in the route table for the subnet it was on, which was pointing back at itself, creating a loop.
The solution is, before you create your NAT gateway, create a new subnet just for the NAT so that the NAT has it's own subnet and route table. In the NAT's route table, point all traffic to the internet gateway. In your main route table, point your external IP to the NAT. Then, when your EC2 instances try to connect to your external IP, they will look them up in the main route table (or whatever route table you have defined for the subnets your instances are in), and find the NAT. Then, your NAT will look up that IP in it's own route table, and find the internet.