Accessing the Internet and other AWS Resources in your VPC from AWS LambdaTweet
Allowing inbound and outbound Traffic for your Amazon AWS Lambda code
AWS Lambda is a great service from Amazon that can be used for a lot of things. It is the key to a Server Less architecture/application but it can also be useful to develop monitoring applications (or functions, actually) for your own services.
Truth be told, whatever is your use case, it is highly probable that you need to access the Internet or other AWS Resources (like RDS) to fully accomplish your tasks. In the first days, you couldn't easily do this, but since Feb 2016 Amazon made publicly available this new feature.
In this article we're going to see what is needed to access both public and private IP addresses from within your Lambda functions. This is essentially giving your Lambdas access to one of your VPCs.
Configuring your Amazon AWS Lambda with a VPC
This part is actually pretty easy. In your AWS Console for Lambda click in one of your functions, and then go to the Configuration tab, and then click in Advanced Settings.
You will notice that you can select a VPC, one or more Subnets and one Security Group. We will see some details about how to create these later, but for now, the trick here is to select ONLY Private Subnets (in case you need to access Internet resources, otherwise any subnet will do as long as your other AWS resources reside in the same VPC as your Lambdas).
Create a VPC for your Amazon AWS Lambda
If you already have a VPC, you can use it. Otherwise, if you prefer to create a new one (fair enough), go to the VPC Section of your AWS Console, and click Create VPC. Fill in a name and the tenancy type (usually "Default"), and the key here is the CIDR block to choose.
The CIDR block should specify a network big enough to contain your public and private subnets. Your Lambdas will be deployed to use only private subnets, while the public subnet will have a NAT Gateway that will provide internet access.
As an example, the CIDR block for our new VPC could be 192.168.0.0/16, reserving the 3rd octet to distinguish different subnets inside that VPC.
Create a Private Subnet in your Amazon AWS VPC
A private subnet is a subnet that has a routing table with a default route that goes through a NAT instance or a gateway.
Our Lambdas need to be deployed in a private subnet in order to access Internet resources, otherwise they just won't be able to do it. If you only need to access resources inside the same VPC, any subnet will do the trick.
Let's create our private subnet then. Go to the Subnet Section of your AWS Console and click Create Subnet, choose a name and the VPC we just created (look it up by its name or id).
Pick a CIDR block that is covered by the VPC CIDR block. In our case we can use something like 192.168.20.0/24 (see how we have "split" our /16 network now, into one /24 subnet).
Create a Public Subnet in your AWS VPC
The public subnet is where our NAT Gateway will "live", and will only be used to provide Internet access to our private subnet where our Lambdas will be deployed.
Follow the same procedure as above so you can create a new subnet. Pick a different CIDR block (but again, one that is covered by your VPC CIDR block), for example: 192.168.10.0/24.
Create an Internet Gateway for your VPC
Let's now create an Internet Gateway so we can provide Internet access to our new VPC. Head over to the Internet Gateways section of your AWS Console and click Create Internet Gateway, pick a name and save it. Then locate your new Internet Gateway created in the listing, select it, click Attach to VPC and select the VPC you just created.
Create a NAT Gateway in your VPC
So far we have created a VPC and attached an Internet Gateway to it, and inside the VPC we have two subnets. This step will place a NAT gateway in the public subnet so the private subnet can use it to route traffic to/from the Internet.
Go to the NAT Gateways section of your AWS Console and click Create NAT Gateway, choose your Public Subnet and allocate a new (or reuse an old) ElasticIP for it. This ElasticIP is the one that will be used by your Lambdas to access the Internet (so you might want to add it in any Firewalls or Security Groups outside this VPC) if you want to allow traffic and from them.
Create a Route Table for the Public Subnet
We have placed an Internet Gateway in our public subnet in our VPC, but we have to actually specify that we want to route traffic to "unknown locations" through the Internet Gateway. This is done by creating a default route in its routing table.
The default route is specified by the CIDR 0.0.0.0/0. Go to the Route Tables section of your AWS Console and click Create Route Table, choose the VPC you created before and pick a name for it.
Once it is created, locate it in the listing, select it, and click the Routes tab, then click Edit and then click Add another route.
In destination use 0.0.0.0/0, and choose your new Internet Gateway as the target. Save it.
Now go back to your public subnet (in the Subnets section of your AWS Console), select your public subnet, click Route Table and then click Edit. You will now be able to select your new Route Table for your public subnet.
Create a Route Table for the Private Subnet
The procedure is pretty much the same, create a new Route Table and associate it with your private subnet this time. The only difference is that instead of using your Internet Gateway as the default target, you have to specify your NAT Gateway, so all traffic from the private subnet (and heading to the Internet) will flow through the NAT Gateway.
Setup your Amazon AWS Lambdas
As described in the very first section of this article, you can now configure your Lambdas so they are deployed in the VPC and private subnets you just created, and use a Security Group that will allow them any outgoing traffic (inbound traffic will not be allowed to them because they will "live" in a private subnet).
Using these very simple and reasonable steps one can now use Lambdas to do many things, like HTTP requests, use RDS, etc. A lot more space for creativity is at hand now :)