HDE BLOG

コードもサーバも、雲の上

Configuring an AWS Lambda Function to Access Both Resources in Public Internet and an Amazon VPC

Hello, this is Bagus from HDE, Inc.

This post is a summary of my presentation on HDE's 21st Monthly Technical Session.

Recently, I’ve been working more with AWS Lambda. There was a time when I created a Lambda function which accesses both resources in public internet and an Amazon VPC. I learned quite a lot from it, so I'd like to share the experience.

Our Case

Please create a Lambda function which accesses:

  • an EC2 instance in a VPC (in a different AWS account, in the same region)

  • a DynamoDB table

  • an S3 bucket

First, our Lambda function should be able to access an EC2 instance in a VPC. By default, Lambda functions can’t access resources in a VPC. For our Lambda function to be able to do so, we should include VPC information in its configuration. This VPC information includes VPC, subnet, and security group IDs. AWS Lambda would then use this information to set up Elastic Network Interfaces (ENIs). These ENIs would enable our Lambda function to access resources in a VPC.

Furthermore, our Lambda function and the EC2 instance are in different AWS accounts. As stated above, our Lambda function would be configured to access resources in a VPC. In other words, our Lambda function would be in the VPC we specified in its configuration. The EC2 instance we’re trying to access is in a VPC as well. To connect two VPCs, we can create a VPC peering connection.

Second, our Lambda function should be able to access a DynamoDB table. DynamoDB resources are not in a VPC, they are treated like public Internet instead. Therefore, we need to provide access to public Internet for our Lambda function. Remember that our Lambda function would be configured to access resources in a VPC. For such Lambda functions, we can create a NAT gateway to provide access to public Internet.

Third, our Lambda function should be able to access a S3 bucket. Like with DynamoDB, S3 resources are not in a VPC either. Both of them require access to public Internet. S3 is a special case, though. Other than NAT gateway, actually we can create a VPC endpoint instead. However, because we would create NAT gateway for DynamoDB anyway, creating a VPC endpoint would not be necessary.

VPC Peering

By creating a VPC peering connection, we'd be able to route traffic between peer VPCs using private IP addresses. There are 2 types of connections we can create, which are:

  • connection between VPCs in the same AWS account

  • connection between VPCs in different AWS accounts, in the same region

Fortunately, our case corresponds with the second type.

However, before proceeding to create a VPC peering connection, we need to confirm that the VPCs don’t have overlapping CIDR blocks. The table below describes some cases of VPC peering connection in relation to CIDR blocks of the VPCs.

Local VPC Remote VPC Result Details
10.0.0.0/16 10.0.0.0/16 Fail Identical CIDRs
10.0.0.0/28 10.0.0.0/16 Fail Overlapping CIDRs
10.0.0.0/16 10.10.0.0/16 Success Non-overlapping CIDRs

In our case, the VPCs don't have overlapping CIDR blocks.

Finally, we can start creating a VPC peering connection.

Creating a VPC Peering Connection with a VPC in Another AWS Account

AWS Documentation

  • Local VPC: the VPC we specified in our Lambda function's configuration
  • Remote VPC: the VPC where the EC2 instance is
Accepting a VPC Peering Connection

AWS Documentation

This step is not to be done by us, but by the owner of the remote VPC instead.

Updating Route Tables for Your VPC Peering Connection

AWS Documentation

Route tables are associated with subnets. If a VPC has several subnets, then it would have several route tables. We only need to update the route tables of the subnets where our Lambda function and EC2 instance are.

This step is done both by us and the owner of the remote VPC. On both sides' route tables, we set the VPC peering connection ID as target. In local VPC's route table(s), we set the remote VPC's CIDR block as destination. In remote VPC's route table(s), we set the local VPC's CIDR block as destination.

NAT Gateway

We stated that we create a NAT gateway to provide access to public Internet for Lambda functions which are configured to access resources in a VPC. Actually, NAT gateway is only one part of the solution.

Near the top of the document, we established that ENIs enable Lambda functions to access resources in a VPC. The ENIs that AWS Lambda creates do not have access to public Internet, though. This is because each of them are assigned private IP address, but none of them are assigned public IP address. The role of a NAT gateway is to translate private IP addresses to a public IP address. The public IP address would be used to send Internet traffic to an Internet gateway. An Internet gateway allows communication between resources in a VPC and the public Internet.

Internet Gateway

AWS Documentation

Creating a NAT Gateway

AWS Documentation

We need to create a NAT gateway in a public subnet. Public subnets are subnets which points its Internet traffic to an Internet gateway.

Updating Your Route Table

AWS Documentation

In this step, we need to point our private subnets' Internet traffic to the NAT gateway we created.

Putting It All Together

This is the solution I came up with to realise the specification given at the top of this article. f:id:bagus-rahman:20160518195640p:plain

About VPC Peering

Our VPC peering connection enables access between VPCTest and OtherVPC. To use the VPC peering connection, we updated VPCTest's Main Route Table, adding a route which points to OtherVPC's CIDR block. We also updated OtherVPC's Other Route Table, adding a route which points to VPCTest's CIDR block.

About NAT Gateway

As stated above, our NAT gateway should reside in a public subnet. VPCTest's subnet Alpha points its Internet traffic to an Internet gateway, which makes it a public subnet. Our Lambda function should reside in a private subnet. VPCTest's subnet Beta doesn't point its Internet traffic to an Internet gateway, which makes it a private subnet. Finally, we point subnet Beta's internet traffic to our NAT gateway instead. This enables our Lambda function to access public Internet, through which it accesses the DynamoDB table and S3 bucket.

Conclusion

If our Lambda function accesses resources in public Internet only, there's no need to add VPC information to its configuration.

If our Lambda function accesses resources in a VPC only, simply add VPC information to its configuration.

If, however, our Lambda function accesses both resources in public Internet and a VPC, we'll need to add VPC information to its configuration and set up a NAT gateway (and an Internet gateway).

To enable access between VPCs, we can create a VPC peering connection. However, if the two VPCs are in a different region or have overlapping CIDR blocks, then we can't enable access between them.


I hope this article can be useful to you.

Thank you so much for reading!