我正在为我的应用程序使用带有应用程序负载均衡器的Amazon Web Services EC2容器服务。当我部署新版本时,我得到503服务暂时不可用大约2分钟。它比我的应用程序的启动时间多一点。 这意味着我现在无法进行零停机部署。
是否有设置在启动时不使用新任务?或者我在这里缺少什么?
更新:
ALB目标组的运行状况检查号如下:
Healthy threshold: 5
Unhealthy threshold: 2
Timeout: 5 seconds
Interval: 30 seconds
Success codes: 200 OK
健康阈值是'在考虑不健康目标健康之前所需的连续健康检查成功次数'
不健康的阈值是'在考虑目标不健康之前所需的连续健康检查失败次数。'
超时是'没有响应意味着健康检查失败的时间量,以秒为单位。'
间隔是'单个目标的健康检查之间的大致时间'
更新2: 因此,我的群集包含两个EC2实例,但如果需要可以扩展。所需和最小计数为2.我为每个实例运行一个任务,因为我的应用程序需要特定的端口号。在我部署之前(jenkins运行aws cli脚本)我将实例数设置为4.如果没有这个,AWS就无法部署我的新任务(这是另一个需要解决的问题)。网络模式是桥梁。
答案 0 :(得分:7)
因此,问题似乎在于任务定义中容器设置的端口映射。
在我使用80作为主机和8080作为容器端口之前。我以为我需要使用这些,但主机端口实际上可以是任何值。如果将其设置为0,则ECS将分配32768-61000范围内的端口,因此可以将多个任务添加到一个实例。为了实现这一点,我还需要更改安全组,让流量从ALB流向这些端口上的实例。
因此,当ECS可以在同一个实例上运行多个任务时,50/200最小/最大健康百分比是有意义的,并且可以在不需要添加新实例的情况下部署新任务修订。这也确保了零停机时间的部署。
感谢所有提出或评论过的人!
答案 1 :(得分:3)
由于您使用的是AWS ECS,我可以问一下该服务的“最低健康百分比”和“最高健康百分比”
确保您的“最大运行状况百分比”为200,“最低运行状况百分比”为50,以便在部署期间不会使所有服务都停止运行。
请查看这两个术语的文档定义:
最大百分比提供部署期间正在运行的任务数量的上限,使您可以定义部署批处理大小。
最低运行百分比在部署期间提供运行任务数量的下限,使您无需使用其他群集容量即可进行部署。
“最低运行状况百分比”的限制为50将确保在部署新版本的容器之前,只有一半的服务容器被杀死,即,如果服务的所需任务值是“2”而不是部署时间只有旧版本的“1”容器将首先被杀死,一旦部署新版本,第二个旧容器将被杀死并部署新版本容器。这将确保在任何给定时间都有处理请求的服务。
同样,“最大健康百分比”的限制为200告诉ecs-agent,在部署期间的给定时间,服务的容器最多可以射出所需任务的两倍。
如有任何进一步的问题,请告诉我。
答案 2 :(得分:2)
使用您的设置,应用程序启动应该花费超过30秒才能使2次健康检查失败并被标记为不健康(假设您的应用程序停机后立即进行首次检查)。并且至少需要2分钟到3分钟才能再次标记为健康状态(在最佳情况下您的应用程序重新联机后立即进行首次检查,或者在最糟糕的情况下,在应用程序恢复之前立即进行首次检查)。
因此,快速而肮脏的修复是增加不健康的阈值,以便在更新期间不会标记为不健康。并且可能会降低健康阈值,以便更快地恢复健康。
但如果您真的希望实现零停机时间,那么您应该使用应用程序的多个实例,并按照Manish Joshi的建议告诉AWS进行阶段部署(以便ELB背后始终有足够健康的实例来保持您的网站正常运行)。
答案 3 :(得分:2)
我如何解决这个问题是在应用程序根目录中有一个平面文件,ALB将监视该文件以保持健康状态。在部署之前,脚本将在监视节点时删除此文件,直到它注册OutOfService
。
这样所有实时连接都会停止并耗尽。此时,通过停止节点或应用程序进程来启动部署。部署之后,通过添加回此平面文件并监视该节点,直到它为此节点注册Inservice
,然后移动到第二个节点以完成上述相同步骤,将节点添加回LB.
我的脚本如下所示
# Remove Health Check target
echo -e "\nDisabling the ELB Health Check target and waiting for OutOfService\n"
rm -f /home/$USER/$MYAPP/server/public/alive.html
# Loop until the Instance is Out Of Service
while true
do
RESULT=$(aws elb describe-instance-health --load-balancer-name $ELB --region $REGION --instances $AMAZONID)
if echo $RESULT | grep -qi OutOfService ; then
echo "Instance is Deattached"
break
fi
echo -n ". "
sleep $INTERVAL
done
答案 4 :(得分:1)
你在谈论 Jenkins ,所以我会回答 Jenkins主服务,但我的回答仍然适用于任何其他情况(即使它不是 ECS 的一个好例子, Jenkins master 无法正确扩展,因此只能有一个实例。
我经常遇到与负载均衡器失败的健康检查相关的 503网关错误(没有健康的实例)。查看负载均衡器监控选项卡,确保健康主机的数量始终高于0。
如果您正在进行 HTTP运行状况检查,则必须在您的服务器上返回代码200 (有效代码列表可在负载均衡器设置中配置)真的开始运行了。否则,负载均衡器可能会处置尚未完全运行的处理实例。
如果问题是您总是遇到 503错误网关,可能是因为您的实例需要很长时间才能回答(当服务正在初始化时),因此 ECS 在初始化完成之前将它们视为关闭并关闭它们。 第一次运行 Jenkins 就是这种情况。
为了避免上一个问题,您可以考虑调整负载均衡器 ping目标(运行状况检查目标以获取经典负载均衡器,监听器,用于应用程序负载均衡器):
如果您需要确保每个实例只有一个节点,则可以使用经典负载均衡器(它也适用于 ECS )。使用经典负载均衡器, ECS 可确保每台服务器只运行一个实例。 这也是非HTTP端口可访问的唯一解决方案(例如Jenkins需要80,但奴隶也需要50000)。
但是,由于端口不是动态的经典负载均衡器,您必须进行一些端口映射,例如:
myloadbalancer.mydomain.com:80(负载均衡器的端口80) - >实例:8081(容器的外部端口) - > service:80(容器的内部端口)。
当然,每项服务需要一台负载均衡器。
如果这是您要启动的 Jenkins 服务,则应使用 Jenkins Metrics插件来获取良好的运行状况检查网址。
安装它,在全局选项中生成令牌并激活ping,您应该能够找到如下所示的URL:http://myjenkins.domain.com/metrics/mytoken12b3ad1/ping
只有在服务器完全运行时,此URL才会回答 HTTP代码200 ,这对于负载均衡器仅在完全准备就绪时才能激活它。
最后,如果您想知道您的实例发生了什么以及它失败的原因,您可以添加日志以查看容器在 AWS Cloudwatch 中所说的内容。
只需在任务定义(容器配置)中添加:
日志配置: awslogs
awslogs-group: mycompany (将重新组合容器日志的Cloudwatch键)
awslogs-region: us-east-1 (您的群集区域)
awslogs-stream-prefix: myservice (创建日志名称的前缀)
它可以让您更深入地了解容器初始化过程中发生的事情,如果它只需要太长时间或是否失败。
希望它有所帮助!!!