【问题标题】:Lambda function within VPC doesn't have access to public Internet [closed]VPC 中的 Lambda 函数无法访问公共 Internet [关闭]
【发布时间】:2018-10-20 22:59:13
【问题描述】:

我正在尝试从 Lambda 函数中向第三方服务发出出站 API 请求,但该函数总是超时且没有任何错误。

这之前发生在尝试在不同的函数中执行 s3.putObject 操作时(仍在同一个 VPC/子网中),我设法通过添加一个服务名称为 com.amazonaws.us-east-1.s3 的端点并连接它来解决这个问题到与此 Lambda 函数所在的 VPC 关联的路由表。

在网络框内的 Lambda 仪表板 -> 安全组部分,我看到以下警告:

当您启用 VPC 时,您的 Lambda 函数将失去默认互联网 使用权。如果您的功能需要外部互联网访问, 确保您的安全组允许出站连接并且 您的 VPC 有一个 NAT 网关。

我相信这个安全组允许出站连接,基于下面的出站规则表:

对于第二个要求,我可以确认此 VPC 具有 NAT 网关,因为在 VPC 仪表板的 NAT 网关选项卡中,出现在那里的 VCP 具有与之关联的 VCP,并且该 VPC 与托管Lambda 函数。

我按照指南创建了一个Flow Log 来监控进出 VPC 的流量,希望看到这些出站请求确实被拒绝了。但是,在这样做并检查 CloudWatch 日志后,所有记录都以 ACCEPT OKNODATA 结尾。

How can I grant internet access to my VPC Lambda function? 是我最初尝试遵循的指南,但我在To create a public or private subnet 下的第 4 步卡住了:

  1. 从更改为:下拉菜单中,选择适当的路由表: 对于私有子网,默认路由应指向 NAT 网关 或 NAT 实例:

    目的地:0.0.0.0/0 目标:nat-...(或 eni-...) 对于公共子网, 默认路由应指向 Internet 网关:

    目的地:0.0.0.0/0 目标:igw-…

对于此 VPC 中的所有四个子网,单击 Change to: 右侧的下拉菜单仅显示一个选项,即已选择的选项 rtb-xxxxxxxx。单击该路由表的链接并单击摘要旁边的路由选项卡后,我看到了:

我做错了什么会阻止 Lambda 函数访问 Internet?

【问题讨论】:

  • 您的 Lambda 函数是否需要访问 VPC 中的资源?如果没有,您只需将其从 VPC 中分离出来,它就会自动访问 Internet。
  • @JohnRotenstein 是的,它需要访问 VPC 中的 ElastiCache 集群

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


【解决方案1】:

要让 Lambda 能够通过 VPC 访问互联网,它应该位于 Private Subnet 中,并附有 NAT Gateway

根据您的屏幕截图,附加到子网的路由表已附加igw-xxxxxxx,使您当前的子网成为public subnet

为了让事情顺利进行,您可以执行以下操作:

  • 在当前subnet 的路由表中附加NAT Gateway 而不是igw-xxxxxx

  • 如果您想访问互联网,请查找附加到您的 Lambda 的 ENI 并附加 Elastic IP

根据@John Rotenstein,如果您的 Lambda 不需要 VPC 资源,您可以将 Lambda 移出 VPC

【讨论】:

  • 我认为不可能将弹性 IP 附加到 Lambda ENI。
  • @JohnRotenstein 是的。导航到 EC2 仪表板上的 Network Interfaces。然后通过搜索附加到 Lambda 的安全组找到ENI ID(我确实喜欢这个 .. 会有更好的方法)。现在你得到了ENI ID。导航到Elastic IP页面,分配并附加所需的IP。
  • 哇,你说的很对!为了对此进行测试,我使用 VPC 向导创建了一个公共 VPC。我创建了一个访问 Internet 的 Lambda 函数。测试 1:没有 VPC,工作正常。测试 2:附加到 VPC,失败。测试 3:将弹性 IP 地址关联到 Lambda ENI,成功了!整洁!!
  • 这里需要注意的是,VPC 中的 lambda 冷启动非常慢(超过 12 秒)。
  • @NavpreetSingh @JohnRotenstein - Elastic IP => ENI,这会起作用,但每个请求 lambda 都会创建一个新的 ENI 并附加。对于持续的 Internet 访问,这是行不通的。
【解决方案2】:

我开发了一个带有明确截图的分步教程:

第一部分

  1. 在 AWS 中创建 lambda 函数
  2. 创建 API 网关以将所有请求重定向到您的 AWS Lambda 函数

https://medium.com/@shontauro/how-can-i-turn-my-restful-api-into-a-serverless-application-and-deploy-it-to-aws-lambda-step-by-ec7ce38e18be

第二部分

  1. 为您的 lambda 函数配置 VPC
  2. 以安全的方式授予对 lambda 函数的 Internet 访问权限
  3. 将 Node.js Restful API 部署到您的 Lambda 函数中

https://medium.com/@shontauro/how-can-i-turn-my-restful-api-into-a-serverless-application-and-deploy-it-to-aws-lambda-step-by-8ff6cc97780f

【讨论】:

    【解决方案3】:

    您可能做错的一件事(这正是我做错的,但从上面的@Ramratan Gupta 得到了提示)是将 NAT 网关放在私有子网中而不是公共子网中。

    NAT 网关为您的私有 IP Lambda 函数提供 Internet 连接,因此 NAT 网关本身需要具有 Internet 访问权限并位于公共网络中。

    总结一下:

    • 您必须至少创建两个子网:一个公共子网和一个私有子网。将两者放在同一个 VPC 中。

    • 使子网成为公共或私有子网的是0.0.0.0/0 路由。

    • 您需要同时拥有互联网网关 (igw) 和 NAT 网关 (ngw)。

    • 要创建 NAT 网关,您需要一个弹性 IP。

      另外,我做错了,你需要在 PUBLIC 网络中创建 NAT 网关。

    • igw 与 NAT 网关位于同一子网中:公共子网。

    • 您需要有两条路由:一条是 0.0.0.0/0 路由引用 igw,另一条引用 ngw。

    • 然后您需要将包含 NAT-route 的路由表与私有子网关联,并将包含 igw-route 的路由表与公共子网关联。请注意,在您进行此关联之前,将一个公有和一个私有的子网之间没有区别。您可以通过将子网与路由表相关联的方式将一个私有化,另一个公开化。

    • 最后,您需要将 Lambda 函数连接到 VPC 以及私有子网。这样,当您的 lambda 尝试访问 Internet 时,它会转到私有子网,查找 0.0.0.0/0 路由,该路由将其定向到公共子网中的 NAT 网关。然后 NAT 网关使用 igw 联系互联网(因为它们在同一个子网中)并在收到响应后将其返回给您的 Lambda 函数。

    • 另请注意,您的 Lambda 函数需要一些权限(AWS 会警告您)才能连接到 VPC。

    【讨论】:

      【解决方案4】:

      VPC 模式下设置 AWS Lambda Internet 访问是很棘手的,因为在 AWS 方面没有提供适当的 AWS 文档,我确实多次阅读了这篇文章https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/,但没有观看 YouTube 视频。经过这么多的研发,我可以总结为在 VPC 模式下设置 AWS Lambda

      需要以下步骤
      - Route Tables two router
          - One for EC2 - EC2_ROUTER
          - Another for AWS Lambda - AWS_Lambda_ROUTER
      - Create an Internet Gateway
          - Add 0.0.0.0/0 rule in EC2_ROUTER for target igw-xxxxx
          - This will create public subnet and give INTERNET access for EC2
      
      - Create a NATGateway with public subnet which has igw-xxxxx as target
      - Create a private subnet which and attach to AWS_Lambda_ROUTER, with target 0.0.0.0/0 as nat-xxxxxxx
      - Select VPC for AWS Lambda
      - Select a/all private subnet which is private having NAT Gateway for all traffic 0.0.0.0/0
      
      all done, go ahead and enjoy
      

      注意

      • 访问 AWS 以外的公共 API 时需要 NATGateway
      • 内部 AWS 服务有 AWS Endpoints,可以通过创建在 AWS_Lambda_ROUTER 中附加 AWS 端点

      AWS Lambda 中的 Internet 访问 -> 具有 NATGateway 的私有子网 -> NATGateway 位于具有访问 AWS Lambda 的 Internet 网关的公共子网中。

      附言

      我不知道为什么 AWS Lambda 不能通过 InternetGateway 访问 INTERNET 为什么它需要 NATGateway

      【讨论】:

      • 您不能使用 IG,因为 IG 需要静态 IP 来路由进出某些资源的流量。 Lambda 是短暂的,需要一个长期存在的 NAT 网关来充当它们的代理。
      猜你喜欢
      • 1970-01-01
      • 2019-10-28
      • 2018-12-25
      • 2020-02-06
      • 2020-05-12
      • 2019-12-31
      • 2019-03-30
      相关资源
      最近更新 更多