Cannot connect to MySQL on lightsail from lambda

Viewed 177

I have a MySQL server on a lightsail instance. The goal is to access the MySQL server from a lambda function.

What I did is as follows.

  • Turn on VPC peering of lightsail
  • Create a MySQL user with '%' host
  • Add the following policies to the lambda function (AmazonEC2FullAccess, AWSLambdaBasicExecutionRole, AWSLambdaVPCAccessExecutionRole)
  • Open port 3306 on the firewall of the lightsail
  • Comment out the bind-address in /opt/bitnami/mysql/my.cnf and reboot MySQL

The lambda code and app.py for CDK are below. The result is the following error. If I try to connect to the same MySQL server with the same code from another EC2 instance in the same VPC/subnet, I can connect successfully.

What do I miss?

[ERROR] OperationalError: (2003, "Can't connect to MySQL server on 'host' (timed out)")
Traceback (most recent call last):
  File "/var/task/hello.py", line 13, in main
    con=MySQLdb.connect(host=host,db=db,user=user,passwd=pw,charset="utf8");
  File "/opt/python/pymysql/connections.py", line 353, in __init__
    self.connect()
  File "/opt/python/pymysql/connections.py", line 664, in connect
    raise exc

Lambda function (hello.py)

import pymysql as MySQLdb;
    
def main(event, context):
  print("hello");
  con=MySQLdb.connect(host=host,db=db,user=user,passwd=pw,charset="utf8");
  print("done");

app.py

from aws_cdk import (
    aws_lambda as lam,
    aws_iam as iam,
    aws_ec2 as ec2,
    core,
)
import os;

class MyStack(core.Stack):
    def __init__(self, app: core.App, id: str) -> None:
        super().__init__(app, id)


        vpc = ec2.Vpc.from_vpc_attributes(
            self,"VPC",
            vpc_id=vpcid,
            availability_zones=[zone],
            isolated_subnet_ids=[subnet],
        );
        sg = ec2.SecurityGroup.from_security_group_id(
            self,"SG",
            security_group_id=sgid,
            mutable=False
        );

        layer = lam.LayerVersion(
            self, "MyLayer",
            code=lam.AssetCode.from_asset('./lib'),
        );

        lamrole = iam.Role.from_role_arn(
            self, "LambdaRole",
            rolearn,
        );

        helloFn = lam.Function(
            self, "hello",
            function_name='hello',
            code=lam.AssetCode.from_asset('./code'),
            handler="hello.main",
            timeout=core.Duration.seconds(900),
            role=lamrole,
            vpc=vpc, # for mysql
            security_groups=[sg],
            layers=[layer],
            runtime=lam.Runtime.PYTHON_3_7,
        )

app = core.App()
MyStack(app, "hello")
app.synth()
1 Answers

Know that it's ~8 months old but ran into the same issue and got it to work. However, I was using LightSail with Nginx so things might be slightly different for you.

Think you where very close. I'm not sure about the order but I did it in the following order:

  • In your Python code make sure you set the host to the Private IP of the Lightsail instance. You can find this in the Networking section of the Lightsail admin area. This seems to always start with 172 but might be different for you.
  • I created a seperate SQL user with the host being '%'. This seems to be the best solution but not neccessary. You can use the root user.
  • Add AmazonVPCFullAccess and/or AmazonVPCFullAccess as Permissions on the User Role that relates to the Lambda.
  • Configure the VPC in the Lambda configuration (has to be the Default VPC).
  • Allow your SQL user to connect to the DB: GRANT ALL on *.* TO 'root'@'172.%.%.%' IDENTIFIED BY ‘adminpass’. Make sure to change the user name, IP address and password.
  • Change the my.cnf file from bind_address=127.0.0.1 to bind_address=0.0.0.0
  • Restart your Lightsail via the Terminal: sudo /opt/bitnami/ctlscript.sh restart
  • Enable VPC in LightSail via the admin section.

After doing the above I can finally connect.

Related