Cannot connect to a AWS RDS mysql database from lambda serverless in python

I have wrote an AWS lambda function in python to access my mysql instance in RDS. The mysql instance is in the same region as the AWS lambda function and was assigned a default VPC.

The following is the python handler code, with an error printing out: “ERROR: Unexpected error: Could not connect to MySql instance”. The handler is “mysql_test”. I am new to serverless.com. Would you guys please help me in this issue since it is very urgent and important for our business to migrate from the traditional architecture to serverless framework. Thanks!

import sys
import logging
import pymysql

name = "xxxx"
password = "xxxxxxxxxx"
db_name = "xxxxxxxxxx"
rds_host = "xxxxxxxxxxxx.us-west-2.rds.amazonaws.com"
port = 3306

logger = logging.getLogger()
logger.setLevel(logging.INFO)

try:
** conn = pymysql.connect(rds_host, user=name,**
** passwd=password, db=db_name, connect_timeout=5)**
except:
** logger.error(“ERROR: Unexpected error: Could not connect to MySql instance.”)**
** sys.exit()**

logger.info(“SUCCESS: Connection to RDS mysql instance succeeded”)

def mysql_test(event, context):
** “”"**
** This function inserts content into mysql RDS instance**
** “”"**
** item_count = 0**

** with conn.cursor() as cur:**
** cur.execute(“create table Employee3 (EmpID int NOT NULL, Name varchar(255) NOT NULL, PRIMARY KEY (EmpID))”)**
** cur.execute(‘insert into Employee3 (EmpID, Name) values(1, “Joe”)’)**
** cur.execute(‘insert into Employee3 (EmpID, Name) values(2, “Bob”)’)**
** cur.execute(‘insert into Employee3 (EmpID, Name) values(3, “Mary”)’)**
** conn.commit()**

** cur.execute(“select * from Employee3”)**
** for row in cur:**
** item_count += 1**
** logger.info(row)**

** response = {**
** “statusCode”: 200,**
** “body”: “Added %d items to RDS MySQL table” %(item_count)**
** }**

** return response**

Best,
Michael

@michaelmei just browsing your code looks like you might have to pass in the port as well in your connection string.

Hi @rupakg,

Thanks for pointing that out. I have changed the code to the following, but still got the same error message. Would it might be caused by the VPC network? Shall I configure the VPC network for the function even it is in the same aws region as the RDS mysql instance?

import sys
import logging
import pymysql

name = "xxxx"
password = "xxxxxxxxxx"
db_name = "xxxxxxxxxx"
rds_host = "xxxxxxxxxxxx.us-west-2.rds.amazonaws.com:3306"
port = 3306

logger = logging.getLogger()
logger.setLevel(logging.INFO)

try:
** conn = pymysql.connect(rds_host, user=name,**
** passwd=password, db=db_name, connect_timeout=5)**
except:
** logger.error(“ERROR: Unexpected error: Could not connect to MySql instance.”)**
** sys.exit()**

logger.info(“SUCCESS: Connection to RDS mysql instance succeeded”)

def mysql_test(event, context):
** “”"**
** This function inserts content into mysql RDS instance**
** “”"**
** item_count = 0**

** with conn.cursor() as cur:**
** cur.execute(“create table Employee3 (EmpID int NOT NULL, Name varchar(255) NOT NULL, PRIMARY KEY (EmpID))”)**
** cur.execute(‘insert into Employee3 (EmpID, Name) values(1, “Joe”)’)**
** cur.execute(‘insert into Employee3 (EmpID, Name) values(2, “Bob”)’)**
** cur.execute(‘insert into Employee3 (EmpID, Name) values(3, “Mary”)’)**
** conn.commit()**

** cur.execute(“select * from Employee3”)**
** for row in cur:**
** item_count += 1**
** logger.info(row)**

** response = {**
** “statusCode”: 200,**
** “body”: “Added %d items to RDS MySQL table” %(item_count)**
** }**

** return response**

Best,
Michael

@michaelmei Is the RDS configured within a VPC? If yes, then you have to configure you function to access the VPC network.

Hi Rupak,

Yes. The RDS Mysql instance is in the default VPC. would you please give me an example of how to configure the function to be in the same VPC region in serverless yaml file?

Thanks!
Michael.

@michaelmei you can put the following snippet under the provider section:

  vpc:
    securityGroupIds:
      - sg-xxxxxxx
    subnetIds:
      - subnet-xxxxxxx
  iamRoleStatements:
    - Effect: Allow
      Action:
        - "ec2:CreateNetworkInterface"
      Resource: "*"

Let me know if it works for you,

Thanks,
Rupak Ganguly

@rupakg Thanks for the reply. appreciated. Just changed the serverless.yaml as following. But I got the following error when trying to deploy. I have admin access to the user. Would you please provide any suggestion? Thank you heaps!

(venv) MacBook-Pro:serverless-wechatapitest michaelmei$ serverless deploy
Serverless: Installing required Python packages with python3.6…
Serverless: Docker Image: lambci/lambda:build-python3.6
Serverless: Linking required Python packages…
Serverless: Packaging service…
Serverless: Excluding development dependencies…
Serverless: Unlinking required Python packages…
Serverless: Uploading CloudFormation file to S3…
Serverless: Uploading artifacts…
Serverless: Uploading service .zip file to S3 (22.35 MB)…
Serverless: Validating template…
Serverless: Updating Stack…
Serverless: Checking Stack update progress…
Serverless: Operation failed!
** Serverless Error ---------------------------------------**
** An error occurred: IamRoleLambdaExecution - API: iam:AttachRolePolicy User: arn:aws:iam::xxxxxxxxxxxxx:user/xxxxxxxxx is not authorized to perform: iam:AttachRolePolicy on resource: role aws-python-wechatapi-dev-us-west-2-lambdaRole.**
** Your Environment Information -----------------------------**
** OS: darwin**
** Node Version: 8.6.0**
** Serverless Version: 1.25.0**

Below is my serverless yaml file

service: aws-python-wechatapi

frameworkVersion: “>=1.2.0 <2.0.0”

provider:
name: aws
stage: dev
region: us-west-2
runtime: python3.6
vpc:
securityGroupIds:
- sg-xxxxxx
subnetIds:
- subnet-xxxxxxxxx
- subnet-xxxxxxxxx
- subnet-xxxxxxxxx
iamRoleStatements:
- Effect: Allow
Action:
- "ec2:CreateNetworkInterface"
Resource: “*”

functions:
currentTime:
handler: handler.mysql_test
events:
- http:
path: mysql
method: get

resources:
Resources:
WriteDashPostLogGroup:
Type: AWS::Logs::LogGroup
Properties:
RetentionInDays: "30"
MyDB:
Type: AWS::RDS::DBInstance
Properties:
DBName: 'xxxxxxxxxx’
AllocatedStorage: '5’
DBInstanceIdentifier: 'xxxxxxxxxx’
DBInstanceClass: db.m1.small
Engine: MySQL
MasterUsername: xxxxxxxxxxxx
MasterUserPassword: xxxxxxxxxxxx
DeletionPolicy: Snapshot

plugins:

  • serverless-python-requirements

custom:
pythonRequirements:
dockerizePip: non-linux

If you copied this directly from your serverless.config then it looks like you’ve indented the securityGroupIds and subnetIds too much. Instead of

  vpc:
      securityGroupIds:
        - sg-xxxxxx
      subnetIds:
        - subnet-xxxxxxxxx
        - subnet-xxxxxxxxx
        - subnet-xxxxxxxxx

use

  vpc:
    securityGroupIds:
      - sg-xxxxxx
    subnetIds:
      - subnet-xxxxxxxxx
      - subnet-xxxxxxxxx
      - subnet-xxxxxxxxx

Hi @buggy, I have changed the indention and attached the screenshot of the configuration. Still got the error. Please indicate. Thanks!

@michaelmei Are you still getting the following error:

If so, it looks like a permissions error for your IAM user doing deploys. Are you still using the same credentials that were working previously?

Hi @alexdebrie1,

Thanks for the reply. I have double checked with the iam user and it turned out it is the one that worked previously. Would you please refer to the following permission I gave to the user and provide some hints on it? Thanks!

Did you ever figure this out? I’m running into the same problem trying to connect to RDS Postgres within a VPC from my node lambda function. I’ve added the following to my serverless.yml, but it’s not helping:

provider:
  name: aws
  runtime: nodejs6.10
  vpc:
    securityGroupIds:
      - sg-011159da68f5dd3ae
    subnetIds:
      - subnet-36a85808
      - subnet-0465080b
      - subnet-c038488a
      - subnet-36a85808
      - subnet-85e14cd9
      - subnet-b1b311d6
      - subnet-fba20dd5
  iamRoleStatements:
    - Effect: Allow
      Action:
        - "ec2:CreateNetworkInterface"
      Resource: "*"

Any help much appreciated!

@kvarela What is not working? The above yaml looks good to me. Give me more details of what error you are seeing.

Hello
@michaelmei michaelmei
@rupakg
I am facing this same issue
Cannot connect to a AWS RDS mysql database from lambda in python with same code … Kindly help me with this issue .

Can any one have solution for this issue