【问题标题】:Problems connecting to Neptune from Lambda从 Lambda 连接到 Neptune 的问题
【发布时间】:2020-09-07 10:04:35
【问题描述】:

我创建了一个简单的 AWS Neptune 集群,有一个写入器,没有读取副本。我使用该选项为其创建了一个新的 VPC,并且也自动为其创建了两个安全组。

我还有一个调用 Nepture 集群端点的 Lambda。我已经使用 Neptune 集群的 VPC 配置了 Lambda,指定了它的所有子网和上面提到的两个安全组。在我从 AWS 控制台执行 VPC 配置时自动分配入站和出站规则后,我没有手动修改它们(只是通过这些步骤)。

Lambda 是用 Python 编写的,并使用 requests 库通过 AWS Singature V4 进行 HTTPS 调用。 Lambda 的执行角色具有NeptuneFullAccess 和一个内联策略,以允许为 Lambda 配置 VPC(已完成,因此该策略有效)。

Lambda 在端口 8182 上调用 Neptune 集群的端点,集群的名称和 ID 已编辑:

https://NAME.cluster-ID.us-east-1.neptune.amazonaws.com:8182

我收到以下错误:

{
  "errorMessage": "2020-05-20T21:26:35.066Z c8ee70ac-6390-48fd-a32e-36f80d58a24e Task timed out after 3.00 seconds"
}

我做错了什么?

更新:因此,看起来 Neptune 集群的第二个安全组是由我在创建集群时选择一个选项创建的。因此,我再次尝试使用安全组的Choose existing 选项,而不是Create new。 (我想我之前很困惑,因为我正在创建一个全新的 VPC,那么安全组怎么可能已经存在?但是向导只是假设届时将创建 default 安全组。)

现在,我不再遇到同样的错误。但是,我看到的是这样的:

{
  "errorType": "Runtime.ExitError",
  "errorMessage": "RequestId: 48e3b4fb-1b88-48d3-8834-247dbb1a4f3f Error: Runtime exited without providing a reason"
}

日志显示:

{
  "requestId": "b8b91c18-34cd-c5f6-9103-ed3357b9241e",
  "code": "BadRequestException",
  "detailedMessage": "Bad request."
}

查询是(给定 https://docs.amazonaws.cn/en_us/neptune/latest/userguide/iam-auth-connecting-python.html 中描述的 Lambda 代码):

{
  "host": "NAME.cluster-ID.us-east-1.neptune.amazonaws.com:8182",
  "method": "GET",
  "query_type": "status",
  "query": ""
}

有什么建议吗?

更新:尝试针对另一个 Neptune 集群时,[Errno 111] Connection refused' 错误又回来了。然而,我注意到一件奇怪的事情:我有一些孤立的网络接口,从 Lambda 与现已删除的 Neptune 集群的 VPC 相关联开始。但是,网络接口标记为in use,我无法分离和删除它们,即使使用Force detachment 选项也是如此。收到You are not allowed to manage 'ela-attach' attachments 错误。

更新:从一个新的 Lambda 开始(不再重做其 VPC 配置,因此不再有孤立的网络接口)和一个启用和配置了 IAM 身份验证的新 Neptune 集群(即使 Lambda 的执行角色被授予对出于调试目的,以消除任何丢失的权限),仍然出现此错误:

{
  "errorMessage": "HTTPSConnectionPool(host='NAME.cluster-ID.us-east-1.neptune.amazonaws.com', port=8182): Max retries exceeded with url: /status/ (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f1f9f98c310>: Failed to establish a new connection: [Errno 111] Connection refused'))",
  "errorType": "ConnectionError",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 71, in lambda_handler\n    return make_signed_request(host, method, query_type, query)\n",
    "  File \"/var/task/lambda_function.py\", line 264, in make_signed_request\n    r = requests.get(request_url, headers=headers, verify=False, params=request_parameters)\n",
    "  File \"/var/task/requests/api.py\", line 76, in get\n    return request('get', url, params=params, **kwargs)\n",
    "  File \"/var/task/requests/api.py\", line 61, in request\n    return session.request(method=method, url=url, **kwargs)\n",
    "  File \"/var/task/requests/sessions.py\", line 530, in request\n    resp = self.send(prep, **send_kwargs)\n",
    "  File \"/var/task/requests/sessions.py\", line 643, in send\n    r = adapter.send(request, **kwargs)\n",
    "  File \"/var/task/requests/adapters.py\", line 516, in send\n    raise ConnectionError(e, request=request)\n"
  ]
}

【问题讨论】:

  • 你找到这个[Errno 111]连接被拒绝错误的原因了吗?
  • 是的。稍后会发布。

标签: amazon-web-services aws-lambda amazon-vpc amazon-neptune


【解决方案1】:

感谢 Neptune 团队的帮助(一个惊人的反应!他们打电话给我讨论这个问题),我能够解决这个问题。

首先,当我使用新的 Neptune 集群和安全组的 Use existing 选项以及添加到 Neptune 集群的 VPC 的全新 Lambda 重新设置设置后,Connection refused 错误消失了。显然,在 Lambda 上重做 VPC 配置有时会留下难以删除的孤立网络接口。因此,只需在 Lambda 上进行一次 VPC 配置!

其次,之后开始出现的运行时错误是由于 AWS 在此处提供的 Python 代码中的错误:https://docs.aws.amazon.com/neptune/latest/userguide/iam-auth-connecting-python.html

也就是说,该脚本中的make_signed_request 函数不返回值。它应该返回r.text,或者更好的是,json.loads(r.text)。然后,一切正常。

【讨论】:

    【解决方案2】:

    需要检查的几件事:

    • 附加到 Neptune 实例的安全组是否允许来自为 Lambda 函数配置的子网的流量?附加到 Neptune 的安全组的默认入站规则是只允许来自配置它的 IP 地址的流量。

    • NeptuneFullAccess 内置 IAM 策略适用于控制平面操作,而不是数据平面操作。您需要使用此处定义的策略文档 [1] 创建一个 IAM 策略,并将该策略附加到您正在使用的任何 Lambda 执行角色。然后,您需要使用该角色来签署向 Neptune 发出的请求。 Python request 库不进行 SigV4 签名,因此您需要遵循与此处 [2] 中所述类似的过程。

    • 如果您真的想简化这一切,我们发布了一个 Python 库,可帮助管理连接、IAM 身份验证以及向 Neptune 发送查询。你可以在这里找到它 [3]。

    [1]https://docs.aws.amazon.com/neptune/latest/userguide/iam-auth.html

    [2]https://docs.aws.amazon.com/neptune/latest/userguide/iam-auth-connecting-python.html

    [3]https://github.com/awslabs/amazon-neptune-tools/tree/master/neptune-python-utils

    【讨论】:

    • 谢谢!我确实启用了 IAM 身份验证并将 [1] 策略添加到 Lambda 的角色。但我认为由于 NeptuneFullAccess 没有必要,所以我没有提及。事实上,我确实使用 [2]。但是作为默认配置的 IP 实在是太奇怪了。我在那里添加了另一个安全组作为源,现在得到一个不同的错误:
    • "HTTPSConnectionPool(host='NAME.cluster-ID.us-east-1.neptune.amazonaws.com', port=8182):最大重试次数超过 url:/status/(由NewConnectionError(': 无法建立新连接:[Errno 111] Connection denied'))"
    • 我能够重新创建错误。当您创建 Neptune 集群时,您是否碰巧将其端口更改为 8182 以外的其他端口?当我将集群的端口更改为 8182 以外的端口但仍尝试在端口 8182 上连接时,我收到了与您在上面收到的相同的错误消息(连接被拒绝)。
    • 非常感谢,泰勒。但是不,我没有更改端口。不过,我确实使用只读副本创建了它,后来我删除了它。与默认设置相比,唯​​一的其他更改是启用了 IAM 身份验证,并且与上述安全组有关。
    • 哦,等等。我认为创建第二个安全组是因为我在创建集群期间选择了一个选项。现在尝试不这样做...
    【解决方案3】:

    根据您的错误消息:

    3.00 秒后任务超时

    你必须增加你的 lambda 执行 timeout,因为你当前的 3 秒设置不足以让它成功竞争:

    Lambda 允许函数在停止之前运行的时间量。默认值为 3 秒。允许的最大值为 900 秒

    如果您的函数运行时间超过设置的超时时间,则 lambda 服务将因运行时间超过给定的超时阈值而终止它。

    附注:

    由于您在 vpc 中使用 lambda,因此您必须记住 lambda 函数没有公共 IP 也没有互联网访问权限。即使您增加函数超时,您也可能无法连接到您的数据库。如果您在 私有子网 中运行 lambda 函数并正确设置 NAT 网关或 NAT 实例,则可以克服此问题。

    【讨论】:

    • 谢谢,但似乎不是这样。经过一些更改,我得到了一个不同的错误,现在它需要不到 100 毫秒。我怀疑一个简单的状态请求甚至会花费这么长时间。
    • @silverberry 这也是我在回答中指出的。您的 VPC 和 lambda 函数是否已正确设置以连接到数据库?
    • 是的,试图弄清楚如何正确设置它。不需要公共 IP,因为 Lambda 的 VPC 配置是专门为解决这个问题而引入的。我会在万不得已的情况下公开它。
    猜你喜欢
    • 2019-03-08
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 2021-12-07
    • 2018-08-22
    • 1970-01-01
    • 2019-06-04
    • 2018-10-11
    相关资源
    最近更新 更多