Search code examples
amazon-web-servicesaws-lambdaamazon-rdsamazon-vpcvpc-endpoint

Connect to RDS in Python using pymysql using VPC Peering


I am trying to connect to a RDS Instance from a Python runtime Lambda Function.

Both the RDS and the Lambda are in a different VPC. I have connected both VPC's using VPC Peering and have confirmed that the peering is successful using EC2 instances.

My VPC A is on the CIDR 172.31.0.0/16, VPC B is on the CIDR 10.1.0.0/16.

The SG's are configured using CIDR's and so are the routes.

The Route Table has the entries as such

VPC A route table:

Destination 10.1.0.0/16
Target pcx-xxxxxxx

VPC B route table:

Destination 172.31.0.0/16
Target pcx-xxxxxxx

Destination 10.2.0.0/16
Target pcx-1234567

SG for VPC A

Inbound

Type - MYSQL/ Aurora
Protocol - TCP
Port - 3306
Source - 10.1.0.0/16

SG for VPC B

Outbound

Type - All traffic
Protocol - All
Port - All
Destination - 172.31.0.0/16

VPC B is also using VPC peering with a different VPC in a different region, to access a different service other than RDS. Inside a Lambda I can access that service using boto3 When I try to connect to the RDS using pymysql, the pymysql.connect timeout. I tried to create a VPC endpoint interface for the RDS and use that as the endpoint that I connect to but that doesn't work either.

If I were to give internet access to the lambda then I can access the RDS instance but I don't want to use that solution.


Solution

  • I think the issue is that you have Publicly Accessible = Yes.

    From Working with a DB instance in a VPC - Amazon Relational Database Service:

    When you launch a DB instance inside a VPC, the DB instance has a private IP address for traffic inside the VPC. This private IP address isn't publicly accessible. You can use the Public access option to designate whether the DB instance also has a public IP address in addition to the private IP address. If the DB instance is designated as publicly accessible, its DNS endpoint resolves to the private IP address from within the VPC. It resolves to the public IP address from outside of the VPC.

    This means that the Lambda function (in VPC B) will resolve the RDS DNS name to a public IP address, which is not routable via the VPC Peering connection.

    You can either set Publicly acccessible = No (which is safer), or connect via the Internet, or somehow resolve the RDS DNS name to a private IP address use it for the connection. (Not sure how you would do this from VPC B.)