AWS Lambda 无法连接到 RDS 实例,但我可以在本地连接?

Posted

技术标签:

【中文标题】AWS Lambda 无法连接到 RDS 实例,但我可以在本地连接?【英文标题】:AWS Lambda can't connect to RDS instance, but I can locally? 【发布时间】:2016-09-30 01:18:45 【问题描述】:

我正在尝试从 lambda 连接到我的 RDS 实例。我在本地编写了 lambda 并在本地进行了测试,一切都很顺利。我部署到 lambda,突然它不起作用。下面是我正在运行的代码,如果有帮助,我将通过 kinesis 流调用 lambda。

'use strict';

exports.handler = (event, context, handlerCallback) => 
    console.log('Recieved request for kinesis events!');
    console.log(event);
    console.log(context);

    const connectionDetails = 
        host:     RDS_HOST,
        port:     5432,
        database: RDS_DATABASE,
        user:     RDS_USER,
        password: RDS_PASSWORD
    ;

    const db = require('pg-promise')(promiseLib: require('bluebird'))(connectionDetails);

    db
            .tx(function () 
                console.log('Beginning query');

                return this.query("SELECT 'foobar'")
                           .then(console.log)
                           .catch(console.log)
                           .finally(console.log);
            )
            .finally(() => handlerCallback());
;

如果有帮助,这里是来自 Cloud Watch 的日志:

START RequestId: *********-****-****-****-********* Version: $LATEST 
2016-05-31T20:58:25.086Z    *********-****-****-****-*********  Recieved request for kinesis events! 
2016-05-31T20:58:25.087Z    *********-****-****-****-*********   Records:  [  kinesis: [Object], eventSource: 'aws:kinesis', eventVersion: '1.0', eventID: 'shardId-000000000000:**********************************', eventName: 'aws:kinesis:record', invokeIdentityArn: 'arn:aws:iam::******************:role/lambda_kinesis_role', awsRegion: 'us-east-1', eventSourceARN: 'arn:aws:kinesis:us-east-1:****************:stream/route-registry'  ]  
2016-05-31T20:58:25.283Z    *********-****-****-****-*********   callbackWaitsForEmptyEventLoop: [Getter/Setter], done: [Function], succeed: [Function], fail: [Function], logGroupName: '/aws/lambda/apiGatewayRouteRegistry-development', logStreamName: '2016/05/31/[$LATEST]******************', functionName: 'apiGatewayRouteRegistry-development', memoryLimitInMB: '128', functionVersion: '$LATEST', getRemainingTimeInMillis: [Function], invokeid: '*********-****-****-****-*********', awsRequestId: '*********-****-****-****-*********', invokedFunctionArn: 'arn:aws:lambda:us-east-1:*************:function:apiGatewayRouteRegistry-development'  
END RequestId: *********-****-****-****-********* 
REPORT RequestId: *********-****-****-****-*********    Duration: 20003.70 ms   Billed Duration: 20000 ms Memory Size: 128 MB   Max Memory Used: 22 MB   
2016-05-31T20:58:45.088Z *********-****-****-****-********* Task timed out after 20.00 seconds

【问题讨论】:

您是否为您的 Lambda 函数启用了 VPC 访问? @MarkB 不。我将下拉菜单设置为“无 VPC” 那么您在 RDS 实例上启用了可公开访问,并且您已将 RDS 实例的安全组向全世界开放? @MarkB 是的,我可以直接从我的笔记本电脑访问 RDS。整个 lambda 在我的本地机器上运行良好。 20 秒似乎足够了,但是如果你将 Lambda 超时时间暂时提高到 60 秒,它会起作用吗? 【参考方案1】:

@MarkB @Michael-sqlbot 在 cmets 中是正确的,这是一个安全组问题。

我终于得到了 AWS 支持的回复,指出 RDS 安全组确实对特定 IP 是私有的。这没有任何意义,因为我从未配置过,我可以从本地机器和弹性 beanstalk 访问数据库。我将 0.0.0.0/0 添加到安全组,现在 lambda 可以连接。谢谢你们的帮助!

【讨论】:

您好,您能详细说明一下吗?您在哪里添加了 0.0.0.0/0? 但是将 0.0.0.0/0 添加到安全组中的入站意味着打开与世界的连接。你不怕吗? @Nativ 用于开发和测试目的。后来它被锁定到正确的安全组。是的,开放与世界的连接对于生产用途来说并不是一个好主意。 那么,您最终是否将您的 lambda 添加到 VPC 中? @LordZardeck AWS 在创建 RDS 实例时自动将您的公共 IP 配置为安全组中的入站。这就是为什么代码可以在您的机器上运行,但不能在其他地方运行。我也发生了同样的事情! :)【参考方案2】:

这是我解决此问题的方法。

创建数据库实例时,系统会要求您选择 VPC。即使您选择默认值,它也会将您系统的公共 IP 作为默认入站 IP。另一方面,Lambda 函数有自己的 IP 设置。这就是为什么您可以通过任何 IDE 或本地访问但不能通过 lambda 函数访问的原因。

添加IP限制:

    转到您实例的安全组。选择默认安全组后,单击它。在新页面中,向下滚动以查找入站和出站设置。

    在入站设置中,单击编辑。您可以在此处更改 IP。 (0.0.0.0/0 向世界开放)

    如果您在此处添加公共 IP,则 IDE 或您的本地连接将起作用。

    要使 lambda 函数正常工作,请添加 lambda 函数的 IP。 转到 Lambda 函数,网络 --> VPC -->(如果没有选择 VPC,请选择与 DB 函数相同的 VPC)并在此处记下 IP。

    在入站设置中输入此 IP,这将显示自动填充。

保存并测试您的 lambda 函数。

【讨论】:

如果我将 Publicly Accessible 设置为 true,这是否适用? 你是一个救生员。非常感谢! 子网怎么样?在那里选择什么重要吗?【参考方案3】:

这是无法在全球范围内访问的答案。

Allow AWS Lambda to access RDS Database

重复马克的回答:

    为 lambda 函数添​​加 vpc 访问权限 为 lambda 创建一个新的安全组 将 RDS 安全组添加到 lambda 的 SG。

【讨论】:

这对答案有什么好处? 我更喜欢这个答案,因为第一个向全世界打开了您的 RDS 实例,而第二个不起作用,或者至少它不适合我。这个很优雅,被广泛引用。 子网怎么样?在那里选择什么重要吗?

以上是关于AWS Lambda 无法连接到 RDS 实例,但我可以在本地连接?的主要内容,如果未能解决你的问题,请参考以下文章

无法从 AWS Lambda 连接到 AWS RDS MySql DB。 ClassNotFoundException:com.mysql.jdbc

无法通过 AWS.RDS.Signer 连接到 RDS

使用 AWS Lambda 连接到 Oracle RDS 时出现错误 (DPI-1047)

无法通过 PDO 连接到 AWS RDS

无法通过 Python Elastic Beanstalk 中的 Flask SQLAlchemy URI 连接到 AWS MySQL RDS 实例

如何从 AWS Lambda .Net Core 应用程序 API 连接到 AWS RDS SQL Server?