Blog post
Giving VPC Lambdas Internet Access using Serverless Framework
Giving VPC Lambdas Internet Access using Serverless Framework
Nikola Jovanovic
2021-06-09
In the last tutorial, we showed how to connect to an RDS using an RDS Proxy with a Lambda function. To do this, we needed to put the Lambda in the same VPC as the RDS and the RDS Proxy. This, of course, makes Lambda lose internet access. In this tutorial, I will show you how to fix this.
This tutorial will continue from where the last one left off and we will be building the example app.
First, we will create a Lambda function which we will use to test internet access. Add this in the serverless.yml file under the functions section:
1 testInternetAccess:
2 handler: lib/handlers/testInternetAccess.handler
3 events:
4 - http:
5 path: test-internet-access
6 method: getThis is how the testInternetAccess.js file looks like:
1const fetch = require('node-fetch')
2
3const testInternetAccess = async (event, context) => {
4 console.log(JSON.stringify({ event, context }))
5
6 let response
7 try {
8 console.log('Fetching data')
9 const res = await fetch('https://jsonplaceholder.typicode.com/posts/1')
10
11 if (!(res.status >= 200 && res.status < 300)) {
12 throw new Error('Unsuccessful API response')
13 }
14
15 response = {
16 statusCode: 200,
17 body: JSON.stringify({
18 internetStatus: 'Online',
19 data: await res.json()
20 })
21 }
22 } catch (error) {
23 console.error(error)
24 response = {
25 statusCode: 500,
26 body: JSON.stringify({
27 internetStatus: 'Offline',
28 error: error.message
29 })
30 }
31 }
32
33 console.log(response)
34 return response
35}
36
37module.exports.handler = testInternetAccessYou can deploy this function now by running:
1$ serverless deploy --stage devSend a GET request to the endpoint shown in the terminal after the deployment has finished. You’ll get a response which looks something like this: {"message": "Internal server error"}. If you check CloudWatch logs for the testInternetAccess Lambda, it should tell you that the Lambda had timed out after a certain amount of time. This is expected behavior if your Lambda doesn’t have internet access.
Now we’ll be starting setting up the resources which grant our Lambdas internet access. We’ll begin by creating two more Subnets in our VPC. One for each availability region which we’re already using. We’ll also create a NAT Gateway for one of the previously created Subnets. The Subnet which we choose must have an Internet Gateway in its Route Table. We’ll add the following code anywhere in the VpcResources.yml file:
1SubnetAPrivate:
2 Type: AWS::EC2::Subnet
3 Properties:
4 VpcId: !Ref VPC
5 AvailabilityZone: ${self:provider.region}a
6 CidrBlock: ${self:custom.VPC_CIDR}.0.2.0/24
7 Tags:
8 - Key: "Name"
9 Value: "SubnetAPrivate"
10
11SubnetBPrivate:
12 Type: AWS::EC2::Subnet
13 Properties:
14 VpcId: !Ref VPC
15 AvailabilityZone: ${self:provider.region}b
16 CidrBlock: ${self:custom.VPC_CIDR}.0.3.0/24
17 Tags:
18 - Key: "Name"
19 Value: "SubnetBPrivate"
20
21EIP:
22 Type: AWS::EC2::EIP
23 Properties:
24 Domain: vpc
25
26NATGateway:
27 Type: AWS::EC2::NatGateway
28 Properties:
29 AllocationId: !GetAtt EIP.AllocationId
30 SubnetId: !Ref SubnetAUpdate the vpc section of the serverless.yml file to look like this:
1vpc:
2 securityGroupIds:
3 - !Ref LambdaSecurityGroup
4 subnetIds:
5 - !Ref SubnetAPrivate
6 - !Ref SubnetBPrivateNext, we need to create a Route Table with a Route with a NAT Gateway and associate the newly created private Subnets to that Route Table. Add this code anywhere in the RoutingResources.yml file:
1RouteTablePrivate:
2 Type: AWS::EC2::RouteTable
3 Properties:
4 VpcId: !Ref VPC
5 Tags:
6 - Key: "Name"
7 Value: "RouteTablePrivate"
8
9RoutePrivate:
10 Type: AWS::EC2::Route
11 Properties:
12 DestinationCidrBlock: 0.0.0.0/0
13 NatGatewayId: !Ref NATGateway
14 RouteTableId: !Ref RouteTablePrivate
15
16RouteTableAssociationSubnetAPrivate:
17 Type: AWS::EC2::SubnetRouteTableAssociation
18 Properties:
19 RouteTableId: !Ref RouteTablePrivate
20 SubnetId: !Ref SubnetAPrivate
21
22RouteTableAssociationSubnetBPrivate:
23 Type: AWS::EC2::SubnetRouteTableAssociation
24 Properties:
25 RouteTableId: !Ref RouteTablePrivate
26 SubnetId: !Ref SubnetBPrivateThat’s it. Now you can deploy your stack and test if your Lambdas have internet access using the testInternetAccess Lambda.
Suppose you have any deployment errors; check your stack in the AWS CloudFormation console. Go to the Events tab, and there you’ll see which resources failed, why, and when.
Nikola Jovanovic
2021-06-09
Nikola is software engineer with a problem solving mindset, in love with JavaScript and the whole ecosystem. Passionate about frontend and backend work.
Leave your thought here
Your email address will not be published. Required fields are marked *