无法使 AWS ECS 服务通过服务发现进行通信
Not able to make AWS ECS services communicate over service discovery
我正在尝试让 2 个服务通过 AWS ECS 服务中的服务发现端点进行通信。
示例:
Service1: 运行s 任务定义到 运行 nginx 和 phpfpm
Service2: 运行s 任务定义到 运行 redis
Now, I need to make service1 container communicate to service2
container
根据互联网上的文档和资源。这是我做的,没能达到需要。
- 我们需要打开服务发现(完成)
- 设置适当的服务名称和命名空间作为服务发现端点(完成)
- 使用上述 属性 设置创建任务定义并创建服务 (done)
- 现在AWS会在Route53上生成一条SRV记录(OK)
现在,当使用一般格式的服务发现端点时
service_discovery_service_name.service_discovery_namespace.
错误日志显示,无法解析名称。
更新 03/2022
AWS 现在有 ENI T运行king,它可以增加多少 ENI 可以附加到 VPC 中给定的 EC2 实例类型。这使得使用 awsvpc
模式与 DNS A
记录更加灵活,并使服务发现更容易为 ECS 服务配置。
将此与 AWS App Mesh and AWS Cloud Map 相结合,您可以使 ECS 服务发现变得更加容易。
有关 ENI T运行king 和 App Mesh 示例的更多信息。
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-instance-eni.html
https://github.com/aws/aws-app-mesh-examples/tree/main/walkthroughs/howto-ingress-gateway
原答案
根据我们的谈话,这里是对正在发生的事情的一些总结。
如果Service1(nginx
在你的情况下)需要与Service2(redis
) 使用 AWS ServiceDiscovery 选项并使用 SRV 记录然后 Service1 需要知道它需要执行 DNS SRV
查找而不是 DNS A
(地址)查找。
这里有多种选择。首先,如果您想继续使用 SRV
记录,请使用您的客户端 nginx needs to proxy redis upstream server with options of service
and resolve
which are available only in premium 版本的 nginx。检查我在答案底部测试过的示例 nginx 配置。
还要确保您创建的 AWS 服务发现名称带有前缀 _http._tcp
否则,我在没有前缀的 nginx 配置中遇到配置 SRV resolve/service
选项的问题。
- 其他选项,如果您不想依赖
SRV
记录而是使用标准 A
记录查找,那么您将不得不对容器使用 awsvpc
模式并且 select A
选项。
- 使用 DNS A 选项,您的
service_discovery_service_name.service_discovery_namespace
查询将正常工作。
- 对于 DNS A 选项,有一些限制。由于可以附加的 ENI 数量限制,您不能 运行 在给定的 EC2 实例上执行多个任务,具体取决于 EC2 实例系列。 更新检查上面的 03/2022 修改。
示例 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
我想更详细地阐述@Imran 的详细答案,因为大部分答案都是关于 SRV
DNS 记录类型并仅显示 Nginx 高级版本的 Nginx 示例(和 SRV
).
如果您使用 ECS Fargate 并配置了 A
DNS 记录。最重要的是配置一个合适的resolver
.
来自文档:
Configures name servers used to resolve names of upstream servers into
addresses, for example:
resolver 127.0.0.1 [::1]:5353;
The address can be specified as a
domain name or IP address, with an optional port. If port is not
specified, the port 53 is used. Name servers are queried in a
round-robin fashion.
话虽如此,解析器必须解析私有 DNS。因此,我们需要使用 NS
DNS 记录。
使用 8.8.8.8
作为解析器将不起作用,因为此 DNS 无法解析私有 DNS。
NS stands for ‘name server’ and this record indicates which DNS server
is authoritative for that domain (which server contains the actual DNS
records). A domain will often have multiple NS records which can
indicate primary and backup name servers for that domain.
为了获得 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 记录。
我的服务发现:
文档:
我正在尝试让 2 个服务通过 AWS ECS 服务中的服务发现端点进行通信。
示例:
Service1: 运行s 任务定义到 运行 nginx 和 phpfpm
Service2: 运行s 任务定义到 运行 redis
Now, I need to make service1 container communicate to service2 container
根据互联网上的文档和资源。这是我做的,没能达到需要。
- 我们需要打开服务发现(完成)
- 设置适当的服务名称和命名空间作为服务发现端点(完成)
- 使用上述 属性 设置创建任务定义并创建服务 (done)
- 现在AWS会在Route53上生成一条SRV记录(OK)
现在,当使用一般格式的服务发现端点时
service_discovery_service_name.service_discovery_namespace.
错误日志显示,无法解析名称。
更新 03/2022
AWS 现在有 ENI T运行king,它可以增加多少 ENI 可以附加到 VPC 中给定的 EC2 实例类型。这使得使用 awsvpc
模式与 DNS A
记录更加灵活,并使服务发现更容易为 ECS 服务配置。
将此与 AWS App Mesh and AWS Cloud Map 相结合,您可以使 ECS 服务发现变得更加容易。
有关 ENI T运行king 和 App Mesh 示例的更多信息。 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-instance-eni.html https://github.com/aws/aws-app-mesh-examples/tree/main/walkthroughs/howto-ingress-gateway
原答案
根据我们的谈话,这里是对正在发生的事情的一些总结。
如果Service1(
nginx
在你的情况下)需要与Service2(redis
) 使用 AWS ServiceDiscovery 选项并使用 SRV 记录然后 Service1 需要知道它需要执行 DNSSRV
查找而不是 DNSA
(地址)查找。这里有多种选择。首先,如果您想继续使用
SRV
记录,请使用您的客户端 nginx needs to proxy redis upstream server with options ofservice
andresolve
which are available only in premium 版本的 nginx。检查我在答案底部测试过的示例 nginx 配置。还要确保您创建的 AWS 服务发现名称带有前缀
_http._tcp
否则,我在没有前缀的 nginx 配置中遇到配置 SRVresolve/service
选项的问题。
- 其他选项,如果您不想依赖
SRV
记录而是使用标准A
记录查找,那么您将不得不对容器使用awsvpc
模式并且 selectA
选项。
- 使用 DNS A 选项,您的
service_discovery_service_name.service_discovery_namespace
查询将正常工作。 - 对于 DNS A 选项,有一些限制。由于可以附加的 ENI 数量限制,您不能 运行 在给定的 EC2 实例上执行多个任务,具体取决于 EC2 实例系列。 更新检查上面的 03/2022 修改。
示例 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
我想更详细地阐述@Imran 的详细答案,因为大部分答案都是关于 SRV
DNS 记录类型并仅显示 Nginx 高级版本的 Nginx 示例(和 SRV
).
如果您使用 ECS Fargate 并配置了 A
DNS 记录。最重要的是配置一个合适的resolver
.
来自文档:
Configures name servers used to resolve names of upstream servers into addresses, for example:
resolver 127.0.0.1 [::1]:5353;
The address can be specified as a domain name or IP address, with an optional port. If port is not specified, the port 53 is used. Name servers are queried in a round-robin fashion.
话虽如此,解析器必须解析私有 DNS。因此,我们需要使用 NS
DNS 记录。
使用 8.8.8.8
作为解析器将不起作用,因为此 DNS 无法解析私有 DNS。
NS stands for ‘name server’ and this record indicates which DNS server is authoritative for that domain (which server contains the actual DNS records). A domain will often have multiple NS records which can indicate primary and backup name servers for that domain.
为了获得 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 记录。
我的服务发现:
文档: