Windows 个容器的 AWS ECS Auto Scaling
AWS ECS Auto Scaling for Windows Containers
我们有几个 (> 5) windows 框架 4.8 .Net MVC Web 应用程序工作负载托管在多可用区 ECS 集群中(EC2 类型:Windows) 被 ALB 暴露在外面。所有这些应用程序在相当长的一段时间内都运行良好。现在需要有选择地为这些应用程序引入自动缩放(5 个中有 3 个需要缩放 out/in)。
我们正在考虑一起利用以下两个功能来实现这一目标。
ECS 服务自动扩展 以扩展每个 容器实例(任务级别)。
在 EC2 实例 级别使用 ECS 容量提供程序ECS 集群自动缩放。它为第 1 步中任务启动的容器提供 space。
我的问题是,这是可以实现的吗?或者这是 Windows 容器 的正确方法吗? .为什么我强调 Windows container 是因为 AWS ECS 与 Linux containers 相比缺乏很多功能,例如我们不能设置 Container memory Soft limit(memory reservation) 但应该提到 hard limit(memory)在配置任务本身时,我认为这是一个主要限制。
如果这无法实现,有哪些选择?我们现在无法迁移到 EKS,显然 Fargate 没有 Windows 支持。
是的,这是可以实现的。我们有一个 ECS 集群 运行 六个使用 Windows docker 容器的服务。正如您所提到的,有两种类型的自动缩放:任务级别和容器实例级别。任务级别的自动缩放比容器实例的自动缩放更容易。
容器实例
对于容器实例自动伸缩组,您需要以下资源:
- ECS 集群(您已有)。
- 您的容器实例的启动配置,使用 Windows ECS Optimized AMIs。
- 使用您的启动配置创建新实例的自动缩放组。
- 您的扩展策略,可以是预留目标策略、计划策略或容量提供程序的组合。
在启动配置中,您需要将新实例注册到您的 ECS 集群。我们为此使用 UserData,并配置一些额外的选项(例如,处理您提到的 Windows 中的 hard/soft 内存限制):
<powershell>
[Environment]::SetEnvironmentVariable(ECS_RESERVED_MEMORY, 256, Machine)
[Environment]::SetEnvironmentVariable(ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE, $TRUE, Machine)
[Environment]::SetEnvironmentVariable(ECS_ENABLE_CPU_UNBOUNDED_WINDOWS_WORKAROUND, $TRUE, Machine)
Initialize-ECSAgent -Cluster <your-cluster> -EnableTaskIAMRole -LoggingDrivers '[json-file,awslogs]'
</powershell>
就自动缩放策略而言,您在这里有多种选择,因此您必须选择最适合您的用例的。我们现在使用 80% 的内存预留目标进行扩展,并在一天中的特定时间进行一些计划的扩展操作,以确保我们在一天中有几次预期的峰值时有足够的容量。我们还没有开始使用容量提供者,因为它们存在一些错误和问题,所以我给他们更多时间来“成熟”(我认为他们现在已经解决了很多问题......你可以阅读更多关于这个 from this comment 以后)。
这几乎是您扩展容器实例所需的全部内容。您可以开始向集群添加任务,您的自动缩放组应该开始添加更多容器实例。
请注意,如果没有容量容器,即使没有足够的内存或 CPU 在任何情况下都无法添加新任务,也可能会出现组无法扩展的情况。这将取决于您的任务的内存和 CPU 配置以及您的预留目标(例如,您的任务需要整个集群当前可用内存容量的 20%,您的集群有 85% 的内存使用率,但是您的扩展策略在您达到 90% 的内存使用率之前不会扩展)。这是能力提供者旨在解决的问题。在我们的用例和我们的任务配置中,我们从来没有遇到过组不能扩展的问题,但我们知道我们过度配置了集群以避免这种情况。
另一个问题是在缩减容器实例时:您需要将实例设置为以某种方式耗尽,以便您的任务有时间优雅地结束,AWS 不会自动处理这些事情。有an open issue here which you can track. We solved this issue using a lambda function and an autoscaling life cycle hook based on this Github repo from this comment.
任务
扩展任务更容易:
- 您需要将您的任务关联到您的负载均衡器,以便任务 registered/de-registered 自动 in/from ELB。
- 您为任务创建扩展策略(例如,您可以使用 ALBRequestCountPerTarget 根据每个目标的请求量来增加,或者也安排自动扩展操作)。
在任务定义中,您必须将主机端口设置为 0,以便 ELB 自动分配它(阅读主机端口 here 的文档)。
这里的主要问题是确保您的应用程序设计为作为集群工作(例如,使用外部会话管理器而不是内存中的会话管理器)。
这是流程的要点。每个步骤都有很多文档可供阅读,但这应该可以回答您提出的问题,为您指明正确的方向,并帮助您避免我们在此过程中发现的一些问题。
为了禁用 windows 容器的硬内存限制,在启动模板 UserData 上将“ECS_ENABLE_MEMORY_UNBOUNDED_WINDOWS_WORKAROUND”环境变量设置为 true。
- AWS Launch 模板用户数据
<powershell>
[Environment]::SetEnvironmentVariable("ECS_RESERVED_MEMORY",256, "Machine")
[Environment]::SetEnvironmentVariable("ECS_ENABLE_MEMORY_UNBOUNDED_WINDOWS_WORKAROUND", $true, "Machine")
[Environment]::SetEnvironmentVariable("ECS_ENABLE_CPU_UNBOUNDED_WINDOWS_WORKAROUND", $true, "Machine")
Initialize-ECSAgent -Cluster <clustername>-EnableTaskIAMRole -LoggingDrivers '["json-file","awslogs"]'
</powershell>
- 在任务定义中跳过内存硬限制并提供将被代理忽略的软限制(保留)。
代理版本应该>=1.32.1(越大越好)
我们有几个 (> 5) windows 框架 4.8 .Net MVC Web 应用程序工作负载托管在多可用区 ECS 集群中(EC2 类型:Windows) 被 ALB 暴露在外面。所有这些应用程序在相当长的一段时间内都运行良好。现在需要有选择地为这些应用程序引入自动缩放(5 个中有 3 个需要缩放 out/in)。 我们正在考虑一起利用以下两个功能来实现这一目标。
ECS 服务自动扩展 以扩展每个 容器实例(任务级别)。
在 EC2 实例 级别使用 ECS 容量提供程序ECS 集群自动缩放。它为第 1 步中任务启动的容器提供 space。
我的问题是,这是可以实现的吗?或者这是 Windows 容器 的正确方法吗? .为什么我强调 Windows container 是因为 AWS ECS 与 Linux containers 相比缺乏很多功能,例如我们不能设置 Container memory Soft limit(memory reservation) 但应该提到 hard limit(memory)在配置任务本身时,我认为这是一个主要限制。
如果这无法实现,有哪些选择?我们现在无法迁移到 EKS,显然 Fargate 没有 Windows 支持。
是的,这是可以实现的。我们有一个 ECS 集群 运行 六个使用 Windows docker 容器的服务。正如您所提到的,有两种类型的自动缩放:任务级别和容器实例级别。任务级别的自动缩放比容器实例的自动缩放更容易。
容器实例
对于容器实例自动伸缩组,您需要以下资源:
- ECS 集群(您已有)。
- 您的容器实例的启动配置,使用 Windows ECS Optimized AMIs。
- 使用您的启动配置创建新实例的自动缩放组。
- 您的扩展策略,可以是预留目标策略、计划策略或容量提供程序的组合。
在启动配置中,您需要将新实例注册到您的 ECS 集群。我们为此使用 UserData,并配置一些额外的选项(例如,处理您提到的 Windows 中的 hard/soft 内存限制):
<powershell>
[Environment]::SetEnvironmentVariable(ECS_RESERVED_MEMORY, 256, Machine)
[Environment]::SetEnvironmentVariable(ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE, $TRUE, Machine)
[Environment]::SetEnvironmentVariable(ECS_ENABLE_CPU_UNBOUNDED_WINDOWS_WORKAROUND, $TRUE, Machine)
Initialize-ECSAgent -Cluster <your-cluster> -EnableTaskIAMRole -LoggingDrivers '[json-file,awslogs]'
</powershell>
就自动缩放策略而言,您在这里有多种选择,因此您必须选择最适合您的用例的。我们现在使用 80% 的内存预留目标进行扩展,并在一天中的特定时间进行一些计划的扩展操作,以确保我们在一天中有几次预期的峰值时有足够的容量。我们还没有开始使用容量提供者,因为它们存在一些错误和问题,所以我给他们更多时间来“成熟”(我认为他们现在已经解决了很多问题......你可以阅读更多关于这个 from this comment 以后)。
这几乎是您扩展容器实例所需的全部内容。您可以开始向集群添加任务,您的自动缩放组应该开始添加更多容器实例。
请注意,如果没有容量容器,即使没有足够的内存或 CPU 在任何情况下都无法添加新任务,也可能会出现组无法扩展的情况。这将取决于您的任务的内存和 CPU 配置以及您的预留目标(例如,您的任务需要整个集群当前可用内存容量的 20%,您的集群有 85% 的内存使用率,但是您的扩展策略在您达到 90% 的内存使用率之前不会扩展)。这是能力提供者旨在解决的问题。在我们的用例和我们的任务配置中,我们从来没有遇到过组不能扩展的问题,但我们知道我们过度配置了集群以避免这种情况。
另一个问题是在缩减容器实例时:您需要将实例设置为以某种方式耗尽,以便您的任务有时间优雅地结束,AWS 不会自动处理这些事情。有an open issue here which you can track. We solved this issue using a lambda function and an autoscaling life cycle hook based on this Github repo from this comment.
任务
扩展任务更容易:
- 您需要将您的任务关联到您的负载均衡器,以便任务 registered/de-registered 自动 in/from ELB。
- 您为任务创建扩展策略(例如,您可以使用 ALBRequestCountPerTarget 根据每个目标的请求量来增加,或者也安排自动扩展操作)。
在任务定义中,您必须将主机端口设置为 0,以便 ELB 自动分配它(阅读主机端口 here 的文档)。
这里的主要问题是确保您的应用程序设计为作为集群工作(例如,使用外部会话管理器而不是内存中的会话管理器)。
这是流程的要点。每个步骤都有很多文档可供阅读,但这应该可以回答您提出的问题,为您指明正确的方向,并帮助您避免我们在此过程中发现的一些问题。
为了禁用 windows 容器的硬内存限制,在启动模板 UserData 上将“ECS_ENABLE_MEMORY_UNBOUNDED_WINDOWS_WORKAROUND”环境变量设置为 true。
- AWS Launch 模板用户数据
<powershell>
[Environment]::SetEnvironmentVariable("ECS_RESERVED_MEMORY",256, "Machine")
[Environment]::SetEnvironmentVariable("ECS_ENABLE_MEMORY_UNBOUNDED_WINDOWS_WORKAROUND", $true, "Machine")
[Environment]::SetEnvironmentVariable("ECS_ENABLE_CPU_UNBOUNDED_WINDOWS_WORKAROUND", $true, "Machine")
Initialize-ECSAgent -Cluster <clustername>-EnableTaskIAMRole -LoggingDrivers '["json-file","awslogs"]'
</powershell>
- 在任务定义中跳过内存硬限制并提供将被代理忽略的软限制(保留)。
代理版本应该>=1.32.1(越大越好)