AWS AutoScaling 'oldestinstance' 终止策略并不总是终止最旧的实例

Posted

技术标签:

【中文标题】AWS AutoScaling \'oldestinstance\' 终止策略并不总是终止最旧的实例【英文标题】:AWS AutoScaling 'oldestinstance' Termination Policy does not always terminate oldest instancesAWS AutoScaling 'oldestinstance' 终止策略并不总是终止最旧的实例 【发布时间】:2014-02-16 00:58:00 【问题描述】:

场景

我正在创建一个脚本,它将在 AutoScaling 组中启动新实例,然后删除旧实例。目的是将新创建(或更新)的 AMI 引入 AutoScaling 组。这是通过将Desired 容量增加一倍当前实例数来实现的。然后,在新实例为Running 之后,将Desired 容量减少相同的数量。

问题

当我运行脚本时,我看到组容量增加了一倍,新实例上线,它们达到Running 状态,然后组容量减少。奇迹般有效。问题是有时因减少而终止的实例实际上是新实例而不是旧实例。

问题

如何确保 AutoScaling 组始终终止最旧的实例?

设置

AutoScaling 组具有以下Termination Polices:OldestInstance、OldestLaunchConfiguration。 Default 政策已被移除。 Default Cooldown 设置为 0 秒。 集团只有一个可用区。

疑难解答

我使用了Cooldown 设置。最后只是把它放在 0 上。 我等待了不同的时间长度,以查看现有服务器是否需要运行一定时间才能终止。似乎如果它们不到 5 分钟,它们就不太可能被终止,但并非总是如此。我有 20 分钟前没有终止的服务器,而不是新的服务器。也许新启动的实例有一些终止保护宽限期?

让步

我知道在大多数情况下,我要替换的服务器已经运行了很长时间。在生产中,这可能不是问题。尽管如此,在 AutoScaling 的正常过程中,旧服务器可能会继续运行,而不是新服务器。这不是可接受的操作方式。

我可以强制终止特定实例,但这会违背OldestInstance 终止政策的要点。

更新:2014 年 2 月 12 日 我继续在生产中看到这一点。已运行数周且具有较旧启动配置的实例将继续运行,而较新的实例将被终止。在这一点上,我认为这是一个错误。几年前为这个话题打开了thread at Amazon,显然没有解决方案。

更新:2014 年 2 月 21 日 我一直在与 AWS 支持人员合作,此时他们已经初步确认这可能是一个错误。他们正在研究这个问题。

【问题讨论】:

到底是什么问题? 【参考方案1】:

您似乎做不到,确切地说,因为自动扩展除了让正确数量的实例运行之外,还试图为您做另一件事:保持您的实例计数在可用区之间保持平衡......以及它比您的终止政策优先考虑这一点。

在 Auto Scaling 选择要终止的实例之前,它首先确定实例比该组使用的其他可用区更多的可用区。如果所有可用区具有相同数量的实例,它会标识一个随机可用区。在确定的可用区内,Auto Scaling 使用终止策略来选择要终止的实例。

——http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/us-termination-policy.html

如果您失去平衡,那么保持平衡无疑是最明智的策略,尤其是在您使用 ELB 时。 documentation 有点模棱两可,但 ELB 会在 DNS 中为配置它的每个可用区通告一个公共 IP;这三个IP地址将通过轮询DNS实现第一层负载均衡。如果启用 ELB 的所有可用区都有健康的实例,那么流量命中的外部 IP 与 ELB 将向哪个可用区的服务器提供流量之间似乎存在 1:1 的相关性——至少如此是我的服务器日志显示的。 似乎ELB不会跨可用区域将流量路由到备用服务器,除非给定区域中的所有服务器都被检测为不健康,这可能是它们实施的理由之一以这种方式自动缩放。

尽管此算法可能并不总是在整个区域范围内首先杀死最旧的实例,但如果它确实按照记录的方式运行,它会杀死所选可用区域中最旧的实例,并且在某些时候它应该会结束循环在负载的几个变化过程中通过所有这些......所以它也不会让最旧的运行无限期。组中的实例数越多,这种影响似乎就越不显着。

【讨论】:

感谢您的 cmets。我实际上考虑了可用区。但是在我的情况下,我只使用一个区域,所以我认为这不适用。 您是否 100% 确定您的 Auto Scaling 组未设置为使用所有可用区?我看到的正是您的问题所描述的行为,并且更改为单个可用区似乎已经解决了它。我现在已经完成了六次滚动部署,它可靠地终止了最旧的实例。以前,至少每隔一次它就会终止新实例。与文档相反,似乎“OldestInstance”实际上可能会考虑可用区。【参考方案2】:

还有其他几种方法可以做到这一点:

    希望增加到 2 倍 等待增加容量的操作 当新实例运行时,暂停所有 AS 活动 (as-suspend-processes MyAutoScalingGroup) 需要重置 终止旧实例 恢复 AS 活动。

或者:

    使用新的启动配置打造全新的 ASG。 暂停 AS 活动,直到 1. 完成。 如果一切正常,请删除旧的 ASG。 恢复 AS 活动

对于最终回滚部署:

    创建新的 ELB(如果您有大量流量,可能需要让 Amazon 预置更多的 elb,这有点蹩脚,而且对自动化不友好) 用新的信用证创建新的 ASG 将 DNS 切换到新的 ELB 如果一切正常,请删除旧的 ELB/ASG/LC,如果不只是将 DNS 改回来

或者使用允许您从 ASG 附加/分离实例的新 ASG API:

    以某种方式启动您的新实例(可能只是运行实例或创建临时 asg) 暂停 AS 活动,使用 http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/attach-instance-asg.html 将它们附加到您的旧 ASG, 使用http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/detach-instance-asg.html 或终止您的旧实例 恢复 AS 活动

您可能想要使用旧的 ASG 的原因是,重新设置所有策略(即使是自动化的)可能很容易,而且尽可能少地进行更改感觉更安全。

一个。

【讨论】:

【参考方案3】:

我的用例是我们需要缩小规模并能够选择哪些机器停机。不幸的是,终止政策“OldestFirst”也对我们不起作用。我能够使用 ambakshi 共享的附加/分离方法的变体来删除最旧的(或我选择的任何实例),同时降低自动缩放组的所需实例值。

第 1 步 - 将自动缩放组的最小值更改为您想要缩小到的数字。

第 2 步 - 暂停 ASG

第 3 步 – 分离要终止的实例,您可以在一个命令中执行多个实例。确保使用 should-decrement-desired-capacity 标志

第 4 步 - 恢复 ASG

第 5 步 - 使用控制台或 CLI 终止您的实例

更新

无需暂停 Auto Scaling 组,只需执行步骤 1、3 和 5 即可。请注意可能发生的任何可用区平衡。

【讨论】:

以上是关于AWS AutoScaling 'oldestinstance' 终止策略并不总是终止最旧的实例的主要内容,如果未能解决你的问题,请参考以下文章

减少 (AWS::AutoScaling::AutoScalingGroup) 中的所需实例是不是会终止实例而不停止它

Terraform aws_autoscaling_group 启动的 AWS EC2 实例的动态命名

服务角色 arn:aws:iam::20011470201:role/deploy 无权执行以下操作:autoscaling:DescribeLifecycleHooks

AWS AutoScaling,缩减 - 等待进程终止

CloudWatch SQS 指标问题上的 AWS Autoscaling

如何在 AWS AutoScaling 中添加 Laravel 环境文件