ELB 和 ECS 集群前的 Amazon API Gateway

Posted

技术标签:

【中文标题】ELB 和 ECS 集群前的 Amazon API Gateway【英文标题】:Amazon API Gateway in front of ELB and ECS Cluster 【发布时间】:2017-06-16 21:19:03 【问题描述】:

我正在尝试将 Amazon API Gateway 放在 Application Load Balancer 的前面,以平衡我的 ECS 集群的流量,我的所有微服务都在其中部署。使用 API Gateway 的动机是通过 lambda 函数使用自定义授权器。

系统图

用亚马逊的话 (https://aws.amazon.com/api-gateway/faqs/):“对后端操作的代理请求也需要在 Internet 上公开访问”。这迫使我将 ELB 公开(面向互联网)而不是内部。然后,我需要一种方法来确保只有 API 网关能够访问 VPC 之外的 ELB。

我的第一个想法是在 API 网关中使用客户端证书,但 ELB 似乎不支持它。

任何想法都将受到高度赞赏!

【问题讨论】:

我认为没有简单的解决方案。 API Gateway 不适合您,或者您必须做更多的事情。解决方案包括将 HAProxy 放在将验证客户端证书的 ALB 之前。或者在 ALB 之前放置一个 lambda,但这将需要缓冲整个响应,这可能会减慢速度。或者,如果您随后可以将秘密标头注入到从 API 网关到 ALB 的请求中。然后将在后端验证此秘密。我不推荐 IP 白名单,因为 API 网关的 IP 范围不是静态的,并且可以更改中断内容。 谢谢@doorstuck。我想避免合并像 HAProxy 这样的新组件。我猜这种场景(API 网关、ELB、ECS 集群)很常见。 AWS 不为其提供开箱即用的解决方案吗? API Gateway 更适合 Lambda 函数服务。当放在带有托管服务的 docker 容器前面时,我觉得它增加了太多的延迟和复杂性。我使用另一个代理而不是 API Gateway,因为无论如何我只使用 API Gateway 的代理部分。我成功地使用了 Zalando 的 Skipper。但是,如果您想使用授权者、云端缓存等,那么 API 网关仍然是可行的方法。 谢谢。我在我的 VPC 中创建了一个 lambda 来代理请求,但我不喜欢这种方法,因为它增加了延迟和复杂性。我最终用开源 TyK 替换了 Amazon API Gateway。 【参考方案1】:

ALB 应该是内部的,以便通过专用链接将请求路由到那里。在我的设置中工作得非常好,无需将 NLB 放在它前面。 路线应该如下:

$默认值 / GET(或 POST 或任何你想使用的) 集成应附加到所有路径 $default 和 GET/POST/ANY 等

【讨论】:

【参考方案2】:

我知道这是一个老问题,但我认为他们可能最近才增加了支持。

“Amazon API Gateway 宣布全面推出 HTTP API,使客户能够轻松构建高性能 RESTful API,与 API Gateway 提供的 REST API 相比,这些 API 可节省高达 71% 的成本并减少 60% 的延迟。作为其中的一部分推出后,客户将能够利用多项新功能,包括将请求路由到私有 AWS Elastic Load Balancer (ELB) 的能力,包括对 AWS ALB 的新支持,以及在 AWS CloudMap 中注册的基于 IP 的服务。”

https://aws.amazon.com/about-aws/whats-new/2020/03/api-gateway-private-integrations-aws-elb-cloudmap-http-apis-release/

【讨论】:

【参考方案3】:

目前没有办法将 API 网关放在私有 ELB 前面,所以你说得对,它必须面向互联网。对于您的情况,我能想到的最佳解决方法是将 ELB 置于 TCP 直通模式并终止 ELB 后面的终端主机上的客户端证书。

【讨论】:

【参考方案4】:

现在似乎已添加此支持。没测试过,YMMV:

https://aws.amazon.com/about-aws/whats-new/2017/11/amazon-api-gateway-supports-endpoint-integrations-with-private-vpcs/

【讨论】:

顺便说一句,我最终确实尝试了这个,是的,它确实有效,但它几乎不是超级方便 - 首先,您只能让 API 网关与网络负载均衡器而不是应用程序负载均衡器通信,所以如果您当前设置了网关正在与之通信的面向外部的 ALB,则需要将它们替换为网络负载均衡器(这意味着您将丢失 SSL 终止,以及您可能会或可能不会使用的各种其他选项)或添加NLB 在 ALB 前面,现在只能是内部的。此外,将现有路由从“HTTP”更改为“VPC 链接”也不是完全无缝的。 关于如何在 ALB 前设置 NLB 的任何建议? @JoshEdwards 有一篇博文 here 如果您仍然感兴趣 除了使用NLB替代ALB外,还需要将ECS配置到现有VPC中,不暴露公网IP。仍然不是一个简单的解决方案。与其陷入这个麻烦,我可能更喜欢仍然使用 ALB + ECS 的解决方案,并在后端逻辑中添加一种方法来验证来自 API 网关的请求。 感谢这个巫术@DylanNicholson【参考方案5】:

如果您使用 VPC 链接和网络负载均衡器,则可以。

请看这篇文章: https://adrianhesketh.com/2017/12/15/aws-api-gateway-to-ecs-via-vpc-link/

TL;DR

    创建连接到目标组的内部网络负载均衡器 (VPC 中的实例) 在 API Gateway 控制台中,创建一个 VPC Link 并将其链接到上面的 NLB 创建 API Gateway 端点,选择“VPC 链接集成”并将您的 NLB 内部 URL 指定为“端点 URL”

希望有帮助!

【讨论】:

如果我们只使用ECS,我们可以添加哪个实例作为目标组。【参考方案6】:

现在可以在 ECS 前直接向 Application Load Balancer (ALB) 添加授权方。

这可以直接在监听器的规则中配置。有关详细信息,请参阅此博客文章:

https://aws.amazon.com/de/blogs/aws/built-in-authentication-in-alb/

【讨论】:

【参考方案7】:

我们决定使用标头来检查以确保所有流量都来自 API 网关。我们在我们的应用程序环境变量中保存一个秘密,并告诉 API 网关在我们创建 API 时注入它。然后在我们的应用中检查该密钥。

这是我们正在做的:

在我们的基本控制器中,我们检查密钥(我们只是在网关后面有一个 REST API):

string ApiGatewayPassthroughHeader = context.HttpContext.Request.Headers["ApiGatewayPassthroughHeader"];

if (ApiGatewayPassthroughHeader != Environment.GetEnvironmentVariable("ApiGatewayPassthroughHeader"))

    throw new error;

在我们的 swagger 文件中(我们使用 swagger.json 作为 API 的来源)

"x-amazon-apigateway-integration": 
    "type": "http_proxy",
    "uri": "https://$stageVariables.url/path/to/resource",
    "httpMethod": "post",
    "requestParameters": 
      "integration.request.header.ApiGatewayPassthroughHeader": "$ApiGatewayPassthroughHeader"
    
  ,

在我们的 docker compose 文件中(我们使用的是 docker,但同样可以在任何设置文件中使用)

services:
  example:
      environment:
        - ApiGatewayPassthroughHeader=9708cc2d-2d42-example-8526-4586b1bcc74d

在构建时,我们从设置文件中获取秘密并将其替换到 swagger.json 文件中。这样我们就可以在设置文件中轮换密钥,API 网关将更新为使用应用正在寻找的密钥。

【讨论】:

【参考方案8】:

考虑到它的推动方式,这似乎是 API 网关技术缺失的一大块。无法调用 VPC 中面向内部的服务器严重限制了其作为互联网访问身份验证前门的实用性。 FWIW,在 Azure 中,API 管理开箱即用地支持这一点 - 它可以接受来自 Internet 的请求并直接调用您的虚拟网络,否则会被防火墙关闭。 在 AWS 下这似乎是可能的唯一方法是使用 Lambdas,它增加了一个重要的复杂层,尤其是。如果您需要支持各种二进制协议。

【讨论】:

以上是关于ELB 和 ECS 集群前的 Amazon API Gateway的主要内容,如果未能解决你的问题,请参考以下文章

提供最新 amazon-ecs-optimized image 的 ami-id 的脚本或 api

使用AWS ELB将域名添加到ECS应用程序

Amazon ECS 上的 Keycloak 集群失败(org.infinispan.commons.CacheException:缓存的初始状态传输超时)

用于返回安全图像 URL 的 Amazon ECS API

Amazon ECS API 获取 1000 本畅销书

Netflix Zuul/Ribbon/Eureka 与 AWS ELB/ALB 和 ECS