无法使 AWS ECS 服务通过服务发现进行通信
Posted
技术标签:
【中文标题】无法使 AWS ECS 服务通过服务发现进行通信【英文标题】:Not able to make AWS ECS services communicate over service discovery 【发布时间】:2019-11-15 18:35:53 【问题描述】:我正在尝试让 2 个服务通过 AWS ECS 服务中的服务发现端点进行通信。
示例:
Service1:运行任务定义来运行nginx和phpfpm
Service2:运行任务定义来运行redis
现在,我需要让 service1 容器与 service2 通信 容器
根据互联网上的文档和资源。这就是我所做的,无法实现需求。
-
我们需要开启服务发现(完成)
设置正确的服务名称和命名空间,作为服务发现端点(完成)
创建任务定义并使用上述属性集创建服务(完成)
现在 AWS 将在 Route53 上生成一条 SRV 记录(OK)
现在,当使用服务发现端点时,通常采用格式
service_discovery_service_name.service_discovery_namespace.
错误日志显示,无法解析名称。
【问题讨论】:
您需要在为每个服务任务分配 IP 的 Route53 中创建 DNSType A
记录而不是 SRV
。只有当您的通信支持 SRV 记录查找时,您才需要 SRV
记录,即客户端需要知道它需要执行 SRV 查找然后获取 IP。
@Imran 是的,但是 aws ECS 具有该功能的内置权利,并且也生成了 A 记录,该记录又指向实例的 IP 地址
您在任务定义中使用了哪种 docker 网络模式?如果您不使用awspvc
,那么它将仅创建SRV
类型,然后指向A
类型。当您执行nslookup myapp.local
时,您将不会得到任何东西,因为它的类型是SRV
而不是A
。当您尝试nslookup -type=srv myapp.local
时,您将获得 SRV 列表,然后您可以尝试 nslookup taskid.myapp.local
提供容器的 IP。除非您的客户端支持执行 SRV 查找然后执行 IP 查找,否则您最好只创建 A
记录。如果您需要示例,请告诉我,将其作为答案发布。
我的任务定义网络模式是桥接,它创建的 SRV 具有 taskid 和指向容器 ip 的 A 记录。请检查在编辑问题部分上传的图片@Imran
这就是我要说的!您的客户端(Service1)需要知道它需要对 Service2 执行SRV
查找,然后使用 SRV 结果(端口和主机名)的详细信息进行通信。例如 - 如果您的 Service1 是 nginx,那么 premium 是 nginx supports 的版本。如果您的 Service1 是 phpfpm
,我不确定它是否支持 SRV 查找通信。首先understandSRV
记录与A
类型有何不同。
【参考方案1】:
我想详细说明@Imran 的详细答案,因为大多数答案都讨论了SRV
DNS 记录类型,并且仅针对高级版本的 Nginx(和SRV
)显示 Nginx 示例。
如果您使用 ECS Fargate 并配置了 A
DNS 记录。最重要的是配置一个合适的resolver
。
来自文档:
配置名称服务器,用于将上游服务器的名称解析为 地址,例如:
解析器 127.0.0.1 [::1]:5353;
地址可以指定为 域名或 IP 地址,带有可选端口。如果端口不是 指定,则使用端口 53。名称服务器在 循环时装。
话虽如此,解析器必须解析私有 DNS。因此,我们需要使用NS
DNS 记录。
使用 8.8.8.8
作为解析器将不起作用,因为此 DNS 无法解析私有 DNS。
NS 代表“名称服务器”,此记录指示哪个 DNS 服务器 对该域具有权威性(哪个服务器包含实际的 DNS 记录)。一个域通常会有多个 NS 记录,它们可以 指明该域的主要和备用名称服务器。
为了获得 DNS 解析器,请运行以下命令:
aws route53 list-resource-record-sets --hosted-zone-id %HOSTED_ZONE_ID% --query "ResourceRecordSets[?Type == 'NS']"
选择其中一条资源记录并将其放入 Nginx resolver
(包括尾随的.
)。
Nginx 基本模板:
events
worker_connections 768;
http
# DNS Resolver
resolver ns-###.awsdns-####.com. valid=10s;
gzip on;
gzip_proxied any;
gzip_types text/plain application/json;
gzip_min_length 1000;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
server
listen 80;
location /
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# This is the important part
proxy_pass http://ecs-fargate-svc.local:8080;
location = /health-check
return 200 'all good';
需要考虑的几点:
不要忘记添加映射端口(在我的示例中为8080
)。
确保安全组允许 VPC 内的流量。
由于使用 Fargate 并且我们的日志有限,请考虑在 ECS Fargate 任务所在的 VPC 中创建一个 EC2 实例,并尝试 curl\ping URL\DNS 记录。
我的服务发现:
文档:
Nginx resolver
The name server (NS) record
【讨论】:
【参考方案2】:根据我们的谈话,这里是正在发生的事情的一些摘要。
如果 Service1(在您的情况下为nginx
)需要使用 AWS ServiceDiscovery 选项与 Service2(redis
) 交互并使用 SRV 记录,则 Service1 需要注意它需要执行 DNS SRV
查找而不是 DNS A
(Address) 查找。
您有多种选择。首先,如果您想继续使用SRV
记录,那么您的客户端nginx 需要代理redis 上游服务器,其中service
和resolve
选项为available,仅在premium 版本的nginx 中.检查我在答案底部测试过的示例 nginx 配置。
SRV
记录而是转至标准A
记录查找,那么您将不得不对容器使用awsvpc
模式并选择A
选项。
使用 DNS A 选项,您对 service_discovery_service_name.service_discovery_namespace
的查询将正常工作。
使用 DNS A 选项,有一些限制。由于 ENI 的数量限制取决于 EC2 实例系列,因此您无法在同一 EC2 实例上为给定服务创建多个任务,因此我只希望 SRV 记录。
示例 nginx DNS SRV 选项配置:
stream
resolver 172.31.0.2;
upstream redis
zone tcp_servers 64k;
server redisservice.local service=_http._tcp resolve;
server
listen 12345;
status_zone tcp_server;
proxy_pass redis;
一些参考资料-
https://aws.amazon.com/blogs/aws/amazon-ecs-service-discovery/ https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-service-discovery.html
【讨论】:
如果不使用 nginx-plus。我想我可以使用前端服务发现(弹性负载均衡器)来解决这个问题。 @Imran @TaraPrasadGurung 我上面提到的另一个选项也没有使用 nginx-plus,但它有一些注意事项。是的。如果体积不是那么高,那么 ELB 是不错的选择,而不是 nginx-plus。 PS - 当你接受它作为答案时,它总是很高兴:)。以上是关于无法使 AWS ECS 服务通过服务发现进行通信的主要内容,如果未能解决你的问题,请参考以下文章
AWS S3 Angular 应用程序通过 Route 53 地址调用 ECS 任务