0
votes

I have created a vpc having public and private subnet. There is also a NAT gateway and the private subnet is associated with NAT gateway. There is a redshift cluster in private subnet. There is lambda function which is associated with both private and public subnet. Below is the code in lambda function and it is getting timed out every time I run it.

import json
import boto3

EVENT_TYPE = "REDSHIFT-EVENT-2000"


    def hello(event=None, context=None):
        print(event)
        event = st = {'Records': [{'EventSource': 'aws:sns', 'EventVersion': '1.0', 'EventSubscriptionArn': 'arn:aws:sns:us-east-2:427128480243:terraform-redshift-sns-topic:cbdfec04-7502-4509-9954-4ddc5e3c', 'Sns': {'Type': 'Notification', 'MessageId': '2b18e1e5-cbd2-5ab9-8a64-b90f55009fa8', 'TopicArn': 'arn:aws:sns:us-east-2:427128480243:terraform-redshift-sns-topic', 'Subject': '[Amazon Redshift INFO] - Cluster Created', 'Message': '{"Event Source":"cluster","Resource":"qa-redshift-cluster","Event Time":"2021-04-09 18:27:29.405","Identifier Link":"https://console.aws.amazon.com/redshift/home?region=us-east-2#cluster-details:cluster=qa-redshift-cluster ","Severity":"INFO","Category":["Management"],"About this Event":"http://docs.aws.amazon.com/redshift/latest/mgmt/working-with-event-notifications.html#REDSHIFT-EVENT-2000 ","Event Message":"Amazon Redshift cluster \'qa-redshift-cluster\' has been created at 2021-04-09 18:27 UTC and is ready for use."}', 'Timestamp': '2021-04-09T18:27:30.589Z', 'SignatureVersion': '1', 'Signature': 'V58ecuxcerOSQyyVfWOPD7VkWRD2srTKqo/KiuTXruSXuZrDBRRTbd/uN76vLs909Lq1EK1XDFukhJKlgyQN9a3M9EvE4KUyf3nGMFvBQvTzk8BUj90VsLkY+YdVbhkcYjKr9cMuT2snPcUF5BeaqIsSbEFyvxGNmwEs0aTA8PsGBpxLT4Mxv78lY4nLFLdXKpnCB9HYGM1EO/VqtpY9dsd7XXGS3uDlWPo7u7BEntqPOcBmSXKtzy53fAGFEkLsDMH9aSzL3KALe4HxYb0zwLN95EE+h2svMt1X+SzIXG48m7NsNZDhG5LSbsUA==', 'SigningCertUrl': 'https://sns.us-east-2.amazonaws.com/SimpleNotificationService-010a507c1833636cd93083a.pem', 'UnsubscribeUrl': 'https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:427128480243:terraform-redshift-sns-topic:cbdfec04-7502-4509-9954-435c5e3c', 'MessageAttributes': {}}}]}
        print(event)
        if event is not None:
            message = event['Records'][0]['Sns']['Message']
            print(message)
            if message is not None and EVENT_TYPE in message:
                # convert the str to python dictionary
                message_dict = json.loads(message)
                print(message)
                # get the cluster details
                cluster_name = message_dict.get('Resource', None)
                print(cluster_name)
                if cluster_name is not None:
                    client_red = boto3.client('redshift',region_name = 'us-east-2')
                    clusters = client_red.describe_clusters(ClusterIdentifier=cluster_name)
                    cluster_detail = clusters.get('Clusters')[0]
                    print(cluster_detail)
                    db_name = cluster_detail.get('DBName')
                    user_name = cluster_detail.get('MasterUsername')
                    db_endpoint = cluster_detail.get('Endpoint')
                    print(db_endpoint)
                    db_address = db_endpoint.get('Address')
                    db_port = db_endpoint.get('Port')
    
                    print(f'The database name is {db_name}')
                    print(f'The database address is {db_address}')
                    print(f'The database port is {db_port}')
                    print(f'The database user is {user_name}')
                    print(f'The cluster name is {cluster_name}')
    
    
                    client_data = boto3.client('redshift-data' , region_name = 'us-east-2')
    
                    response = client_data.execute_statement(
                        ClusterIdentifier = cluster_name,
                        Database = db_name,
                        DbUser = user_name,
                        Sql = "CREATE TABLE TEST (key LONG)"
                    )
                    print(response)
                    id = response.get('Id')
                    print(id)
    
                    response2 = client_data.describe_statement(Id = id)
                    print(response2)

For testing purpose I have hardcoded the event json.All the resources have been created via Terraform.I looked up Lambda using python 3.6 & boto3 in VPC times out when connecting to Redshift and from this I added NAT but still it fails.

The role attached to lambda has permissions to access redshift and for time been the security groups have all the traffic enabled inbound and outbound.

If I run this script directly from pycharm it works fine but the issue comes when running from lambda where it gets timeout at this line

clusters = client_red.describe_clusters(ClusterIdentifier=cluster_name)

I am not able to figure the issue. Can someone please help me out. Thank you

1
Your lambda function should be only in private subnet, not publics. Does your NAT work? Can you verify that using, e.g. instance your private subnet?Marcin
I was able to create a ec2 instance in private subnet and ping google.com from that instance. I am assuming that because of NAT in public subnet. Also I removed the public subnet from lambda but it didn't work. Same issueDeepak_Spark_Beginner
What about security group for the lambda in the vpc? Does it allow outbound access to the internet?Marcin
Below is what security group for lambda says inbound and outbound. Not sure if this what means access to internet ------ All traffic All All 0.0.0.0/0Deepak_Spark_Beginner
How did you access your ec2 instance, if its in private subnet?Marcin

1 Answers

0
votes

If you want to access the cluster privately and if both of them are in the same VPC.

Can you please check your redshift security group?

Please allow the security group of lambda in the redshift's security group.

I would also suggest you allow the VPC CIDR range in the security group of redshift.