How to deploy a serverless multi-region, active-active backend inside of AWS VPC
A question asked several times: how to deploy the serverless multi-region, active-active backend inside an Amazon VPC (Virtual Private Cloud)? Learn how today!
Jun 08, 2023 • 6 Minute Read
A question asked several times: how to deploy the serverless multi-region, active-active backend inside an Amazon VPC (Virtual Private Cloud)? I thought it would be great if I pushed our approach a bit further and enhance the solution to answer some of these questions.
What is a VPC?
A VPC improves privacy and security — especially for apps with strict compliance and audit requirements or sensitive data. Typically, you use a VPC so that resources inside the VPC cannot be accessed from the public Internet. These resources could be AWS service resources, such as your data warehouses, your cache clusters or your database.
Since by default, resources within a VPC are not accessible from Lambda functions, we have to do a bit of extra work.
How to Permit Lambda into the VPC?
To permit your Lambda function to access resources inside your VPC, we must provide additional VPC-specific information such as VPC subnet IDs and security group IDs. This information is used to set up an elastic network interface (ENI) that enables the Lambda function to connect to resources within the VPC.
In addition, we’ll also need to enable DynamoDB VPC endpoints and add our VPC routing information to it.
Note: For the sake of diversity, I will create everything from the Command Line Interface (CLI), but you can, of course, do everything from the console :)
Let’s get cracking!
Level up your career in the cloud
Looking to level up your cloud career? Get started with A Cloud Guru for free and see how our hands-on approach can help you master modern tech skills.
Building the VPC Networking Foundation
Step #1 — Create our VPCs
We, of course, first need to create our VPCs in every region where we want to deploy our backend. I will use the us-east-1 and us-west-2 regionsin this example.
Do the same in the us-west-2 region.
Step #2 — Create a Subnet inside each of your VPCs
Note: you can add one or more subnets in each Availability Zone and in fact, you should since it is the best practice.
Of course, we need to do the same for the us-west-2 region.
Step #3 — Get the routing information for each of the VPCs
Repeat this in the us-west-2 region and keep the field “RouteTableId” information close to you since you will need it later.
Create the DynamoDB Global Table
This is very similar to how we did it in the Step #1: Creating a Global Table in DynamoDB of my previous post:
Great, so now we have a global table that we can access from our Lambda functions within the VPC … OR is it so?
Well … NO!!! Our default DynamoDB Global Table is not YET in the VPC, so it is treated like the public internet. Since we’ve configured our Lambda functions to run inside our VPC, we need to create what we call a VPC endpoint for DynamoDB.
DynamoDB already offers data protection and security using TLS endpoints for encryption-in-transit, a client-side encryption library, and fine-grained access control using AWS Identity and Access Management (IAM), so why would we want a VPC Endpoints for DynamoDB?
Simply put, it further improves privacy and security, especially for applications with strict compliance and audit requirements or that handle sensitive data.
Indeed, if you’re connecting to DynamoDB from a VPC, you do not need an Internet gateway or NAT gateway anymore, so your VPC remains closed and isolated from the public Internet. The VPC endpoints also offer simplified network configuration that removes the need for you to set up and maintain firewalls to keep you VPC secure from network attacks.
More security = Happier customers
Step #4 — Creating a VPC endpoint for DynamoDB
Step #5 — Adding the VPC routing to the DynamoDB endpoint
Here we need to add the “RoutingTableId” value returned previously to the command.
Great! Now our DynamoDB Global Table is accessible from within my VPCs.
NOTE: Of course, we need to duplicate the commands for each of the regions :)
Creating the backend using API Gateway and AWS Lambda Functions deployed in a VPC
The backend functions are the same as in my previous post, no changes here; we still have a GET item_id, a POST item_id and a GET health.
What DOES change is the Serverless frameworktemplate used to deploy the Lambda functions in a VPC and configure the API Gateway.
However, before we can do that, we need to create Security Groups for our Lambda functions in each region. Here are the default inbound and outbound rules of the security group configuration for one of my VPC. Notice the inbound rule references itself in the source?
Note: the security groups that you choose for a function will control the function’s access to the resources in the subnets and on the Internet. So feel free to modify it accordingly.
Now we can update __all__ the VPC fields necessary to deploy the backend using the serverless framework and since I don’t want to manage templates for each region, I will use variables supported by the framework since they allow users to dynamically replace configuration values in the serverless.yml file.
Notice the VPC part of the template and how I use the cool variable syntax to pass the region information to the configuration depending on the region where I deploy?
${file(env_${opt:region}.yml):lambdaExecSecurityGroups}
Note: Please make sure to replace the “xxxxxxxxxxxxx” in the serverless.yml file with your AWS Account ID in which the previously DynamoDB tables were created and by the correct Subnet and Security Group IDs in the env files.
Deploy the API in both us-east-1 and us-west-2, where our DynamoDB global tables with the VPC Endpoint is deployed.
The rest does not change from here — so you can continue from the “Step #3: Creating the Custom Domain Names” in my previous blog post and go all the way :)
Voilà! Hope you have enjoy this small encore. I am planning few more .. so stay tuned!
-Adrian