AWS ECS Service Connect 与服务发现

Gar*_*son 9 amazon-web-services amazon-ecs aws-cloudmap aws-service-connect

AWS Cloud Map 允许您为 VPC 设置一些命名空间,然后将该命名空间内的名称分配给各个服务。这些名称可以是 A) 仅可通过 API 调用私下发现,B) 可通过 API 调用或通过 VPC 内的 DNS 私下发现,或 C) 可通过公共 DNS 和 API 调用发现。ECS可以与云地图交互,自动注册服务。所有这些在 AWS ECS 中称为服务发现

AWS ECS 还有一个相对较新的东西,称为Service Connect。它利用 Cloud Map,但还向您的 ECS 服务添加了 sidecar“代理”容器,从而有效地创建了自动服务网格。

我使用 CloudFormation 将 Service Connect 与 ECS 结合使用。在我的 CloudFormation 中, AWS::ECS::Cluster我配置了ServiceConnectDefaults我想要使用的 Cloud Map 命名空间,例如example.internal. 然后我设置了下的定义enabled: true,以及一些额外的详细信息,例如提供服务/端口的名称。假设我已经命名了我的 service/port ,我相信现在在同一 VPC 中使用 Service Connect 的其他一些服务可以连接到,并且 sidecar-proxy 会找出要连接到的某个实例,甚至无需使用 DNS!(我还没有测试过;我首先想对当前的问题进行一些澄清。)AWS::ECS::ServiceServiceConnectConfigurationmy-servicemy-service.example.internalmy-service

但我也想要私有 DNS 访问,如果没有别的办法,那就是能够访问 Cloud9 并发出例如 a,curl my-service.example.internal/api/test而不需要查找其中一个my-service实例的 IP 地址。我发现我可以定义 aAWS::ServiceDiscovery::PrivateDnsNamespace和 a AWS::ServiceDiscovery::Service(使用相同的名称my-service),甚至可以使用 将后者与我的 ECS 服务关联起来ServiceRegistries。但是当我尝试部署 CloudFormation 堆栈时,出现错误:

提供的请求无效:CreateService 错误:服务已存在。

我猜测,为了让 Service Connect 正常工作,ECS 在内部创建了自己的AWS::ServiceDiscovery::Service,此时它发现我的 CloudFormation 堆栈已经创建了AWS::ServiceDiscovery::Service同名的 。但如果我不AWS::ServiceDiscovery::Service自己创建,ECS 创建的将不会提供my-service.

我是否可以推断 AWS ECS 可以与 Service Connect 配合使用(在这种情况下,不会有服务 DNS 条目,但 sidecar 代理将使用 API 调用来查找注册的服务)或服务发现(在这种情况下我手动创建 Cloud Map) DNS 条目和 ECS 将根据AWS::ServiceDiscovery::Service与 ECS 服务的关联自动注册它们),但不能同时注册?或者我配置不正确?

我想如果我使用服务发现并获取 DNS 条目,我可以简单地指示其他服务中的(在我的情况下是私有的)DNS 条目,他们将通过云地图找到它们,为我提供与 Service Connect 相同的功能,而无需需要一个 sidecar 代理。但也许 Service Connect 有一些我会失去的额外监控功能?

有人可以确认这是一个正确的理解,并详细说明将 Service Connect 或 Service Discovery 与 ECS 结合使用之间的实际差异和影响吗?

Gar*_*son 10

与使用普通 Cloud Map 进行服务发现相比,Service Connect 带来的好处是,当服务实例出现故障时,故障转移速度更快。将基于 DNS 的查找与 Cloud Map 结合使用意味着当服务出现故障时,您的客户端可能需要一段时间(基于 TTL 设置)才能意识到它应该获取新的 IP 地址。更糟糕的是,您的客户端库可能会将相同的 IP 地址缓存更长时间,和/或您的客户端的重试逻辑可能会在失败时继续尝试相同的 IP 地址。

另一方面,Service Connect 引入了一个 sidecar“代理”容器,该容器拦截传出连接并将其路由到正确的目的地。sidecar 使用对 Cloud Map 的 API 调用来实时查找健康的服务实例的 IP 地址,而不是依赖可能已过时的 DNS 条目。这带来了 Envoy 等服务网格的标准优势,只不过在这种情况下 Service Connect 会为您管理 sidecar。有关这些优势的更多讨论,请参阅将现有 Amazon ECS 服务从服务发现迁移到 Amazon ECS Service Connect 。

由于 Service Connect 不依赖于 DNS,因此它甚至不需要注册私有 DNS 条目,而是向 Cloud Map 注册只能通过 API 调用私下发现的端点。似乎没有办法告诉 Service Connect 在 DNS 中注册服务名称。

您不能对同一服务名称同时使用 Service Connect 和 Service Discovery ,因为如问题中所述,Service Connect 和 Service Discovery 都会尝试向 Cloud Map 注册相同的服务名称。但是您可以使用两个不同的服务名称将它们一起使用!如果您ServiceConnectConfiguration使用服务/端口发现名称(例如 )定义任务定义端口映射和服务,并指定了命名空间为 的my-service-connectECS 集群,则即使没有该名称的 DNS 条目,您的其他 ECS 服务也可以连接到,如下所述多于。ServiceConnectDefaultsexample.internalmy-service-connect.example.internal

但您还可以定义一个AWS::ServiceDiscovery::PrivateDnsNamespaceof example.internal(Service Connect 将使用它而不是创建一个新的)以及AWS::ServiceDiscovery::Service使用不同的服务名称,例如my-service。使用 将此服务发现与 ECS 服务关联起来ServiceRegistries,您将两全其美!ECS 服务可以使用 进行通信my-service-connect.example.internal,但您仍然可以转到 Cloud9 并my-service.example.internal通过 DNS 连接到(注意不同的名称),因为 ECS 将确保两者都已注册。不能保证这两种方法在任何特定时间都会引用相同的服务实例,并且如果服务实例出现故障,则 DNS 方法my-service.example.internal可能会过时,直到传播新的 DNS 值,但对于 Cloud9 中的临时测试(动机首先)这并不重要。

我发布了一篇博文,结合使用 AWS ECS Service Connect 和服务发现,其中更深入地介绍了如何实现此功能,并配有 CloudFormation 模板片段。