从 VPC 中的 Lambda 访问 AWS S3

Posted

技术标签:

【中文标题】从 VPC 中的 Lambda 访问 AWS S3【英文标题】:Access AWS S3 from Lambda within VPC 【发布时间】:2017-02-08 08:23:34 【问题描述】:

总的来说,我对在 VPC 中使用 AWS Lambda 感到很困惑。问题是 Lambda 在尝试访问 S3 存储桶时超时。解决方案似乎是 VPC Endpoint。

我已将 Lambda 函数添​​加到 VPC,以便它可以访问 RDS 托管数据库(以下代码中未显示,但功能正常)。但是,现在我无法访问 S3,并且任何尝试这样做都会超时。

我尝试创建 VPC S3 端点,但没有任何改变。

VPC 配置

每当我第一次创建 EC2 实例时,我都会使用默认创建的简单 VPC。它有四个子网,都是默认创建的。

VPC 路由表

_Destination - Target - Status - Propagated_

172.31.0.0/16 - local - Active - No

pl-63a5400a (com.amazonaws.us-east-1.s3) - vpce-b44c8bdd - Active - No

0.0.0.0/0 - igw-325e6a56 - Active - No

简单 S3 下载 Lambda:

import boto3
import pymysql
from StringIO import StringIO

def lambda_handler(event, context):
    s3Obj = StringIO()

    return boto3.resource('s3').Bucket('marineharvester').download_fileobj('Holding - Midsummer/sample', s3Obj)

【问题讨论】:

VPC S3 端点需要路由表配置和安全策略配置。如果您需要帮助,您需要展示您是如何配置这些设置的。文档在这里:docs.aws.amazon.com/AmazonVPC/latest/UserGuide/… 或者,您可以向 VPC 添加一个 NAT 网关,这将使 Lambda 函数可以访问 VPC 之外的所有内容,而不仅仅是 S3 服务。 这是 vpc 配置问题。在路由表上配置任何一个与 nat 网关的 sbunet 关联。你还在寻找问题吗? 我添加了一些关于 VPC 配置的信息。我认为这就是问题所在,但 VPC 在很大程度上对我来说是一个黑匣子。我不知道用它检查什么以查看可能配置错误的内容。 【参考方案1】:

还有另一个与 VPC 端点相关的解决方案。

在 AWS 控制台上,选择 VPC 服务,然后选择终端节点。创建一个新端点,将其关联到 s3 服务

VPC S3 endpoint selection

然后选择 VPC 和路由表。

然后选择访问级别(完整或自定义),它将起作用。

【讨论】:

感激不尽,花了一整天的时间来解决这个问题。它修复了!!! 在我将我的 Chalice 功能添加到 *** 并且 S3 刚刚停止连接后,让我非常头疼。 一开始我实际上忽略了这个答案,因为我认为它与创建新 VPC 相关,而实际上它与 endpoints 相关是我选择了gateway 选项而不是interface 选项,因为VPC 定价页面明确指出VPC 端点网关没有成本(不确定接口)。请注意,网关和接口都将具有相同的服务名称。在我的情况下是“com.amazonaws.us-east-2.s3” 这对我来说也是如此,简单而简单,我的s3.get_object 调用没有任何变化,而且我仍然可以使用https:// url 访问文件。 像魅力一样工作。非常感谢。【参考方案2】:

使用 boto3,S3 url 默认为 virtual,这需要将互联网访问解析为特定于区域的 url。这会导致 Lambda 函数挂起,直到超时。

要解决这个问题,需要在创建客户端时使用 Config 对象,这会告诉 boto3 创建基于 path 的 S3 url:

import boto3 
import botocore

client = boto3.client('s3', 'ap-southeast-2', config=botocore.config.Config(s3='addressing_style':'path'))

请注意,调用中的区域必须是您要部署 lambda 和 VPC Endpoint 的区域。

然后您将能够在 Lambda 的安全组中为 VPC 端点使用 pl-xxxxxx 前缀列表,并且仍然可以访问 S3。

这是一个有效的CloudFormation script 演示了这一点。它会创建一个 S3 存储桶、一个与仅包含私有子网和 VPC 端点以及必要的 IAM 角色的 VPC 关联的 lambda(将记录放入存储桶)。

【讨论】:

node.js aws-sdk 有类似的设置吗?我看到了s3ForcePathStyle,但它似乎不起作用。 您的导入语句中有错字。应该是:import botocore 然后下一行应该按预期工作。 sn-p 中的错字,'ap-southeast-2' 中的单引号应关闭。 使用boto3.Session()时该怎么办?这个参数怎么传? 你是一个学者,一个绅士。谢谢你的回答!【参考方案3】:

还有一个与子网和路由有关的问题在其他答案中未解决,因此我正在创建一个单独的答案,但前提是上述所有答案都适用。您必须正确设置它们才能让 lambda 函数访问 S3。

当您创建一个我去年秋天创建的新 AWS 账户时,没有路由表自动与您的默认 VPC 关联(请参阅控制台中的路由表 -> 子网关联)。

因此,如果您按照instructions 创建端点并为该端点创建路由,则不会添加路由,因为没有子网可以放置它。与 AWS 一样,您不会收到错误消息...

您应该为您的 lambda 函数创建一个子网,将该子网与路由表和 lambda 函数关联,然后重新运行 Endpoint 指令,如果成功,您将找到一个包含三个条目的路由表,例如这个:

Destination     Target
10.0.0.0/16     Local
0.0.0.0/0       igw-1a2b3c4d
pl-1a2b3c4d     vpce-11bb22cc

如果你只有两个条目(没有'pl-xxxxx'条目),那么你还没有成功。

最后,我想 lambda 函数需要一个子网才能生存应该不足为奇,就像网络中的任何其他实体一样。并且可能建议它不要与您的 EC2 实例位于同一子网中,因为 lambda 可能需要不同的路由或安全权限。请注意,lambda 中的 GUI 确实希望您在两个不同的 AZ 中拥有两个子网,这也是一个好主意。

【讨论】:

要在 AWS 控制台中创建终端节点,请转到 VPC 仪表板 > 终端节点 我认为这行不通,将采用 igw 路线,但这将丢弃 ref docs.aws.amazon.com/vpc/latest/userguide/…【参考方案4】:

我的问题的原因是没有正确配置我的安全组的出站规则。具体来说,我需要添加目的地为 pl-XXXXXXXX(S3 服务。实际值由 AWS 控制台提供)的自定义协议出站规则。

【讨论】:

你能举例说明如何做到这一点,因为即使我也面临同样的问题 pl-xxx 看起来像一个前缀列表,如下所述:docs.aws.amazon.com/AmazonVPC/latest/UserGuide/…,可以在命令行中使用aws ec2 describe-prefix-lists 找到。 最后我只是为那个 lambda 函数创建了一个安全组:aws ec2 create-security-group --group-name my-lambda --description 'Good luck' --vpc-id vpc-123456 我应用了那个组,没有其他。出口规则是唯一重要的规则。如果你不给,一切都是允许的。我对此不太满意,但代码很小且可审计,我无法让严格的控制正常工作。如果代码变得更复杂,我将不得不重新审视这一点。 如果您将所有端口的安全组的出站规则设置为 0.0.0.0/0,这应该可以工作,对吧?因为download_fileobj 还只是挂着 太棒了!!谢谢,我还完美配置了 VPC 子网和路由表,但忘记了安全网关可以阻止它,以便指出它。【参考方案5】:

我只是想在其他答案中添加一个其他答案,这可能会影响那些冷启动时间很慢的正在运行的功能。

我已按照有关为 S3 设置网关的所有说明进行操作,但仍然无法正常工作。我创建了一个测试 Node.js 函数,它简单地列出了存储桶 - 我验证了如果没有 S3 网关,这不起作用,但一旦建立了网关就可以了。所以我知道部分事情运行良好。

在调试时,我正在更改函数的超时时间以确保函数已更新,并且在调用和测试时我使用的是最新版本的代码。

我已将超时时间减少到 10 秒,但结果表明我的功能在冷启动时需要更像 15 秒。 一旦我再次增加超时,它就起作用了。

【讨论】:

【参考方案6】:

要从 VPC 中的 Lambda 函数访问 S3,您可以使用 Natgateway(与 VPC 终端节点相比,这是一种非常昂贵的解决方案)。如果您在 VPC 中有两个私有子网(其中子网有到 NAT 网关的路由)并将它们与 Lambda 相关联,则它可以像访问 VPC 外部的任何 Lambda 一样访问 S3 存储桶。 陷阱

    如果您将公有子网与 Lambda 相关联,期望它能够工作,但它不会。 确保您的安全组已准备好接受入口。

这种方法将使 Lambda 函数可以访问 Internet 上的任何可用服务。详细步骤可以关注这个博客https://blog.theodo.com/2020/01/internet-access-to-lambda-in-vpc/

【讨论】:

以上是关于从 VPC 中的 Lambda 访问 AWS S3的主要内容,如果未能解决你的问题,请参考以下文章

AWS Lambda 无法访问同一 VPC 中的 EC2 端口

VPC 中的 AWS Lambda 在 NAT 之后没有互联网访问权限

如何从账户 A 中的 Lambda(VPC 中的 Lambda)调用账户 B 中的 AWS Lambda 函数(VPC 中的这个 Lambda)

AWS Lambda:如何为具有 VPC 访问权限的 lambda 函数设置 NAT 网关

AWS - 从公共 API 网关到 VPC 内 lambda 的路由

AWS Lambda 无法调用没有 VPC 的另一个 AWS Lambda - NodeJs