首页 > 解决方案 > AWS Lambda 函数读取红移详细信息超时

问题描述

我创建了一个具有公共子网和私有子网的 vpc。还有一个 NAT 网关,私有子网与 NAT 网关相关联。私有子网中有一个 redshift 集群。有一个与私有子网和公共子网相关联的 lambda 函数。下面是 lambda 函数中的代码,每次运行它都会超时。

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)

出于测试目的,我对事件 json 进行了硬编码。所有资源都是通过 Terraform 创建的。我在 VPC 中使用 python 3.6 和 boto3 查找 Lambda 在连接到 Redshift 时超时,并从这里添加了 NAT,但它仍然失败。

附加到 lambda 的角色有权访问 redshift,并且安全组暂时启用了所有入站和出站流量。

如果我直接从 pycharm 运行此脚本,它可以正常工作,但是从 lambda 运行时会出现问题,它在此行超时

clusters = client_red.describe_clusters(ClusterIdentifier=cluster_name)

我无法弄清楚这个问题。有人可以帮帮我吗。谢谢

标签: pythonamazon-web-servicesaws-lambdaamazon-redshiftamazon-vpc

解决方案


如果您想私下访问集群并且它们都在同一个 VPC 中。

你能检查一下你的红移安全组吗?

请允许 lambda 的安全组在 redshift 的安全组中。

我还建议您在 redshift 的安全组中允许 VPC CIDR 范围。


推荐阅读