在VPC内从Lambda访问AWS S3

mus*_*ole 29 amazon-s3 amazon-web-services amazon-vpc aws-lambda

总的来说,我对在VPC中使用AWS Lambda感到非常困惑.问题是Lambda在尝试访问S3存储桶时超时.该解决方案似乎是一个VPC端点.

我已将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
Run Code Online (Sandbox Code Playgroud)

简单的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)
Run Code Online (Sandbox Code Playgroud)

小智 31

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

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

VPC S3 端点选择

然后选择 VPC 和路由表。

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

  • 我真是太感谢你了,我花了一整天的时间来解决这个问题。修好了!!! (7认同)
  • 我一开始实际上忽略了这个答案,因为我认为它与创建新的 VPC 有关,而实际上它与 **端点** 有关。我要在这个答案中添加的唯一内容是我选择了“网关”选项,而不是VPC 定价页面中的“接口”选项明确表示 VPC 终端节点网关没有成本(不确定接口)。请注意,网关和接口都将具有相同的服务名称。就我而言,这是“com.amazonaws.us-east-2.s3” (3认同)

Geo*_*ff 16

使用boto3,默认情况下S3 URL是虚拟的,然后需要将Internet访问权限解析为特定于区域的URL.这导致挂起Lambda函数直到超时.

要解决此问题,需要Config在创建客户端时使用对象,这告诉boto3创建基于路径的S3 URL:

import boto3 import botocore.config

client = boto3.client('s3', 'ap-southeast-2, config=botocore.config.Config(s3={'addressing_style':'path'}))
Run Code Online (Sandbox Code Playgroud)

请注意,调用中的区域必须是要部署lambda和VPC端点的区域.

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

这是一个可用于演示此功能的CloudFormation脚本.它创建一个S3存储桶,一个与仅包含私有子网和VPC端点的VPC相关联的lambda(将记录放入存储桶)以及必要的IAM角色.


mus*_*ole 5

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

  • 你能举例说明如何做到这一点,因为即使我也面临同样的问题 (5认同)

Pau*_*l S 5

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

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

因此,如果您按照说明创建一个端点并为该端点创建路由,则不会添加任何路由,因为没有子网可放置它。像往常一样,使用AWS不会收到错误消息...

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

Destination     Target
10.0.0.0/16     Local
0.0.0.0/0       igw-1a2b3c4d
pl-1a2b3c4d     vpce-11bb22cc
Run Code Online (Sandbox Code Playgroud)

如果您只有两个条目(没有“ pl-xxxxx”条目),则您尚未成功。

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