如何找出 ECS 运行状况检查失败的原因?

Posted

技术标签:

【中文标题】如何找出 ECS 运行状况检查失败的原因?【英文标题】:How do I work out why an ECS health-check is failing? 【发布时间】:2017-08-03 20:29:18 【问题描述】:

大纲:

我有一个非常简单的 ECS 容器,它侦听端口 5000 并写出 HelloWorld,以及运行它的实例的主机名。我想使用 ECS 部署许多这些容器并对其进行负载平衡,以便真正了解更多有关其工作原理的信息。它在一定程度上可以工作,但我的健康检查失败(超时),这导致容器任务上下跳动。

当前配置:

1 个 VPC (10.0.0.0/19) 1 个互联网网关 3 个私有子网,一个用于 eu-west-1 中的每个可用区(10.0.0.0/24、10.0.1.0/24、10.0.2.0/24) 3 个公有子网,一个用于 eu-west-1 中的每个可用区(10.0.10.0/24、10.0.11.0/24、10.0.12.0/24) 3 个 NAT 实例,每个公共子网中一个,将 0.0.0.0/0 路由到 Internet 网关,每个实例都分配了一个弹性 IP 3 个 ECS 实例,每个私有子网中也有一个,路由到与 ECS 实例位于同一可用区的相应公有子网中的 NAT 实例 1 个 ALB 负载平衡器(面向 Internet)已在我的 3 个公共子网中注册 1 目标组(没有根据 ECS 文档注册的实例),但在 /health 的“流量”端口上设置了健康检查 1 服务带来 3 个任务,分布在 AZ 中并使用动态端口(然后在 docker 容器中映射到 5000)

路由

每个私有子网都有一条到 10.0.0.0/19 的规则,以及一条从 0.0.0.0/0 到与其位于同一 AZ 的公有子网中的 NAT 实例的默认路由。

每个公有子网都有相同的 10.0.0.0/19 路由和 0.0.0.0/0 到互联网网关的默认路由。

安全组

我的实例位于一个组中,该组允许从 ALB 所在的安全组出口到任何地方并在端口 32768 - 65535 上入口。

ALB 位于一个安全组中,该安全组只允许在端口 80 上进入,但在我的 ECS 实例在任何端口/协议上的安全组中出口

会发生什么

当我提出这一切时,它确实有效 - 我可以获取 ALB 的公共 dns 记录并刷新,我看到我的容器应用程序返回给我的响应告诉我主机名。这正是我想要实现的然而,它未能通过运行状况检查并且容器被排空并被替换为另一个未能通过运行状况检查的容器。如此循环往复,我从未见过一次成功的健康检查。

我尝试过的

调整了健康检查间隔,使 ECS 需要大约 5 在终止任务之前,健康检查失败了几分钟。一世 认为这会消除它在任务时有点敏感 启动?尽管有我,这仍然会触发拆除 能够始终查看在我的浏览器中运行的应用程序。 以多种方式确认 /health url 端点。我可以通过 ALB 公开检索它(以及在“/”处查看主应用程序根 url),curl 告诉我有正确的 200 OK 响应(健康检查默认设置为查找)。我已经 ssh'ed 到我的 ECS 实例并在'/'和'/health'上执行了 curl --head url 并且都给出了 200 OK 响应。我什至在公共子网中启动了另一个实例,授予它与 ALB 安全组对我的实例相同的访问权限,并能够从那里进行运行状况检查。

总结

我可以通过负载均衡器、ECS 实例本身以及使用实例,在其主 url '/' 和运行状况检查 url '/health' 上查看我的应用程序在 AZ 和私有子网上的正确负载均衡来自 ALB 所在公共子网中另一台计算机的私有 IP 和端口。ECS 服务在没有超时的情况下无法看到此运行状况检查。我到底能错过什么?

【问题讨论】:

【参考方案1】:

对于接下来的任何事情,我设法意外破坏了容器中的应用程序,并引发了 500 错误。但至关重要的是,健康检查开始报告这个 500 错误 -> 因此它不是网络超时。这意味着当健康检查联系我的应用程序中的端点时,它没有正确处理响应,这似乎是与 Nancy(我正在使用的 api 框架)和 Go 相关的问题,它有时会报告“Client.Timeout等待标头时超出”,我确信 ECS 将其解释为网络超时。我将 tcpdump 网络流量,查看运行状况检查发送的内容以及 Nancy 的响应,并将其与正常工作的容器进行比较。也许有一个 Nancy 修复,或者 ECS 不需要那么挑剔。

编辑:

只需将我的 Nancy 应用程序使用的所有 nuget 包更新到最新可用的包,突然一切都开始工作了!

【讨论】:

很高兴你解决了它。打算建议您检查应用程序日志以确认它是否正在接收健康检查。我在让 NAT 在 ALB 设置中工作时偶然发现了一个切题的问题:为什么要使用 NAT 实例而不是 NAT 网关?【参考方案2】:

问题多于答案。但也许他们会带你走向正确的方向。

您说您可以通过 ALB 访问容器应用程序,但随后节点未通过健康检查。在健康检查成功之前,ALB 不应允许连接到节点。因此,如果您通过 ALB 连接到节点,则 ALB 必须经过测试并确定它是健康的。是否有其他健康检查正在杀死节点?

您是否检查过 CloudTrail 以查看它是否有任何关于触发拆卸的线索?拆机是由 ALB 还是 Auto Scaling 组触发的?可能是 Auto Scaling 组的缩容标准错误?

祝你好运

【讨论】:

感谢您的意见!我会检查cloudtail,看看是否有健康检查的记录。至于问题多于答案,我只是想找出“下一步”来解决这个问题,所以谢谢! 不幸的是,CloudTrail 只是重复超时消息。我什至能够从同一私有子网中的另一个实例卷曲运行状况检查,这是一个有效的 200 OK 响应。所以我可以从公共网络、我的公共子网、我的私有子网上的另一个实例和实例本身进行连接。不知道:-|

以上是关于如何找出 ECS 运行状况检查失败的原因?的主要内容,如果未能解决你的问题,请参考以下文章

Terraform 创建了 AWS ECS 基础设施:运行状况检查一直失败

AWS ECS Fargate 容器运行状况检查命令

如何在Elastic Load Balancer运行状况检查中获取302重定向的URL?

通过 API 网关安全路由的 ECS 容器未返回,但容器的运行状况检查良好

如何找出 PyImportModule 导入失败的原因?

人脸识别一直失败是啥原因?