在具有服务发现的 aws ecs fargate 上重启后,nginx 服务未启动应用程序服务

问题描述 投票:0回答:2

我的集群上有两个服务:myapp-service 和 nginx-service。我正在使用服务发现来连接两者,一切正常。

问题发生在我部署新版本的 myapp-service 时,它带有一个新的私有(和公共)IP 地址。部署后,我看到 ip 在 Route 53 上正确更新,但是当我尝试通过 nginx 访问我的应用程序时,它返回一个错误的网关。当我查看 Cloudwatch 上的 nginx 日志时,我可以看到 nginx 正在尝试连接到 myapp-service 的旧私有 IP 地址。

  • 目前我没有使用任何负载平衡或自动缩放配置。
  • 任务定义上我的容器有任何健康检查。
  • “Enable ECS task health propagation”开启

这是我的 nginx 配置(default.conf),marketplace-service.local 是我在 Route 53 上的注册表。

upstream channels-backend {
    server marketplace-service.local:8000;
}

server {
    listen 80;

    location / {
        proxy_pass http://channels-backend;
    }

}

任何人都可以帮我发现我在这里错过了什么吗??

谢谢

amazon-web-services nginx amazon-route53 aws-fargate service-discovery
2个回答
0
投票

我不知道

upstream
部分。

upstream channels-backend {
    server marketplace-service.local:8000;
}

但我确定

server
部分。对于
Fargate
,使用
localhost
所以添加
server_name localhost;
。然后将下面显示的 4 行代码添加到
location
块。

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://channels-backend;
    }

}

0
投票

问题与DNS缓存有关。与许多服务器一样,Nginx 缓存 DNS 查找,这意味着 Nginx 不会为它代理的每个请求执行 DNS 查找。相反,它解析 DNS 名称一次并在一段时间内重复使用该 IP 地址(由 DNS 条目的生存时间 (TTL) 定义)。

你的案例中棘手的部分来自 proxy_pass 指令,它使 Nginx 仅在启动时解析 proxy_pass 中定义的地址一次 - 在启动时不遵守 route53 记录 TTL!

当您更新通道后端服务时,它会获得一个新的 IP 地址,Nginx 服务将继续使用旧 IP 地址,直到您重新启动 Nginx。这就是为什么您看到 Nginx 尝试连接到旧 IP 地址并返回错误网关错误的原因。

为了能够永久解决这个问题,您必须明确告诉 Nginx 使用解析器和有效指令遵守 TTL,并结合使用 proxy_pass 指令中的变量。

resolver <DNS_IP_ADDRESS> valid=10s;

upstream channels-backend {
    server marketplace-service.local:8000;
}

server {
    listen 80;

    location / {
        set $backend "http://channels-backend";
        proxy_pass $backend;
    }
}

根据你的DNS服务器IP替换。 可能的 DNS 地址:

  1. 169.254.169.253(如果您使用 awsvpc 作为网络模式)
  2. Base VPC cidr your ecs services resides plus 2 (例如:如果你的VPC cidr是 10.0.0.0/16 ,那么使用 10.0.0.2 作为DNS服务器IP。)
  3. 127.0.0.11(Docker 容器的默认 DNS 服务器)

我不确定第三个选项,但我认为它应该可行。

如果您的位置块操纵 URI(例如重写),请考虑使用 map 而不是 set。我遇到了类似的问题,地图是唯一对我有用的解决方案。

# When specifying multiple servers, they are queried in the order
# they appear in the directive

resolver 10.0.0.2 169.254.169.253 127.0.0.11 valid=10s;

upstream channels-backend {
    server marketplace-service.local:8000;
}

map $request_uri $backend {
    hostnames;
    default http://channels-backend;
}

server {
    listen 80;

    location ~ ^/api/ {
        rewrite  ^/api/(.*) /$1 break; 
        proxy_pass $backend;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.