简而言之,我想将Nginx和Node.js docker映像部署到AWS ECS。要构建基础结构,我正在使用Terraform。但是,在服务器中运行的任务不断失败。另外,访问域bb-diner-api-https.shaungc.com时得到503 Service Temporarily Unavailable
。
(您可以see my entire project repo here,但我将在下面嵌入链接,并向您介绍特定的相关文件。)
terraform apply
之后,它报告创建的15个资源,我可以在ECS Web门户中看到正在运行的服务和任务。但是,一段时间后,我的任务将总是失败:
因为运行状况检查始终失败:
对于nodejs,我有错误代码137,这是由于收到关闭信号引起的。这意味着不是nodejs的原因-它的nginx无法通过太多的运行状况检查,从而终止了nodejs。对于nginx,单击View logs in CloudWatch
后根本不显示任何消息(我在task definition中设置了awslogs
)。
基本上,我在nginx中准备了一条仅用于健康检查的路由。在task definition> container_definition
(json格式)中,我对容器nginx
进行了运行状况检查,如下所示:
"command": ["CMD-SHELL","curl -f http://localhost/health-check || exit 1"]
,在我的nginx.conf中,我有:
...
server {
listen 80;
...
location /health-check {
# access_log off;
return 200 "I'm healthy!" ; # refer to https://serverfault.com/questions/518220/nginx-solution-for-aws-amazon-elb-health-checks-return-200-without-if
}
}
所以我真的不知道为什么任务无法通过健康检查。
我还为我创建了一个应用程序负载均衡器,以将我在Route 53上的域名链接到该负载均衡器。我注意到还有另一个地方可以进行运行状况检查:目标组和应用程序负载平衡器。检查在这里也失败了,我的实例状态为draining
。
我想我打开了所有可能的端口。
有很多文章指出AWS上的Nginx配置,PORT或入站限制(安全组/目标组)可能是常见原因,我研究了所有这些。我让Nginx侦听80,将容器端口设置为80,在安全组中允许广泛的入站端口。我还能缺少什么?
答案 0 :(得分:1)
我自己弄清楚了。虽然我从未通过容器级别的运行状况检查,但还是设法修复了应用程序负载平衡器上的运行状况检查失败。
事实证明,这与EC2实例的安全组有关。当我遵循AWS troubleshooting page进行健康检查失败时,我注意到了这一点,他们建议SSH进入实例并直接在实例上尝试curl -v ...
。 curl
失败,我发现我的EC2实例安全组正在使用默认sg。虽然默认安全组(sg)允许所有流量,但它将其来源限制为自身,即默认安全组。这可能会造成混淆,但是我认为这表明它仅允许来自使用默认安全组的AWS服务的流量。无论如何,这都会阻止aws服务以外的任何流量,因此我无法通过域名访问,ALB健康状况检查代理也无法访问。
我的最终解决方案是为ALB建立一个专用的安全组,然后为EC2实例创建一个新的安全组,该EC2实例仅允许来自ALB安全组的流量。还要注意,由于我们已经在ALB的安全组中将端口限制为80和443,并且现在EC2实例sg设置在ALB的sg之后(现在是所有内部流量),因此无需在EC2实例sg中将端口限制为80/443。您可以将其保留为0以允许所有端口。如果限制到错误的端口,则运行状况检查将开始失败。请参阅AWS故障排除页面中的以下内容:
- 确认与您的容器实例相关联的安全组允许与负载均衡器相关联的安全组中的临时端口范围(通常是端口32768-65535)上的所有入口流量
重要:如果您在任务定义中声明了主机端口,则该服务将在指定端口上公开,而不是在临时端口范围内。因此,请确保您的安全组反映了指定的主机端口而不是临时端口范围。
这确实使我花了很多精力和时间来弄清楚。需要注意的一点是,我仍然无法使容器级别的运行状况检查正常工作,这在AWS ECS的任务定义中进行了定义。我尝试将ssh
放入容器实例(EC2实例),结果发现localhost
显然不起作用。直接在EC2实例上测试docker inspect
时,甚至AWS trouble shooting page都使用从curl
生成的ip地址。但是,对于任务定义容器运行状况检查,如果不检查localhost
,应该检查什么?我是否还应该在运行状况检查命令中运行docker inspect
以获得IP地址?这个问题仍然没有解决,现在我只给exit 0
绕过运行状况检查。如果有人知道什么是正确的配置方式,请随时分享,我也很想知道。