View a markdown version of this page

Cluster Autoscaler - Amazon EKS

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Cluster Autoscaler

概述

Kubernetes 集群自动缩放器是一种流行的集群自动缩放解决方案,由 SIG Autoscaling 维护。https://github.com/kubernetes/community/tree/master/sig-autoscaling它负责确保您的集群有足够的节点来调度 pod,而不会浪费资源。它监视无法调度的 Pod 以及未充分利用的节点。然后,它会模拟节点的添加或移除,然后再将更改应用到您的集群。集群自动扩展器中的 AWS 云提供商实施控制您的 EC2 自动扩展组的.DesiredReplicas字段。

架构

本指南将为配置集群 Autoscaler 和选择最佳折衷方案以满足组织要求提供一个心理模型。虽然没有单一的最佳配置,但有一组配置选项可让您在性能、可扩展性、成本和可用性之间进行权衡。此外,本指南还将提供优化 AWS 配置的技巧和最佳实践。

术语表

本文档中将经常使用以下术语。这些术语可能具有广泛的含义,但就本文档而言,仅限于以下定义。

可扩展性是指随着您的 Kubernetes 集群容器和节点数量的增加,集群自动扩缩器的性能如何。当达到可扩展性极限时,集群自动扩缩器的性能和功能就会降低。由于集群 Autoscaler 超过了其可扩展性限制,它可能不再在您的集群中添加或删除节点。

性能是指集群 Autoscaler 能够以多快的速度做出和执行扩展决策。性能完美的 Cluster Autoscaler 会立即做出决定并触发扩展操作以响应刺激,例如 Pod 变得不可调度。

可用性意味着 Pod 可以快速调度,不受干扰。这包括何时需要对新创建的 Pod 进行调度,以及缩小规模的节点何时终止调度到其中的任何剩余 Pod。

成本由活动规模扩大和规模背后的决策决定。如果现有节点未得到充分利用,或者添加的新节点对于传入的 Pod 来说太大,就会浪费资源。视用例而定,由于积极的缩小规模决定而过早终止 Pod 可能会产生成本。

节点组是一个抽象的 Kubernetes 概念,指的是集群内的一组节点。它不是真正的 Kubernetes 资源,而是作为抽象存在于集群自动扩缩器、集群 API 和其他组件中。节点组中的节点共享标签和污点等属性,但可能由多个可用区或实例类型组成。

EC2 自动扩展组可用作 EC2 上节点组的实现。EC2 Auto Scaling 组配置为启动自动加入其 Kubernetes 集群的实例,并在 Kubernetes API 中为相应的节点资源应用标签和污点。

EC2 托管节点组是 EC2 上节点组的另一种实现。它们消除了手动配置 EC2 Autoscaling 扩展组的复杂性,并提供了额外的管理功能,例如节点版本升级和优雅的节点终止。

操作集群自动扩缩器

Cluster Autoscaler 通常作为部署安装在集群中。它使用领导者选举来确保高可用性,但工作一次只能由一个副本完成。它不能横向扩展。对于基本设置,它应该按照提供的安装说明开箱即用,但有几点需要记住。

请确保:

使用 IAM 角色的最低权限访问权限

使用 Auto Discovery 时,我们强烈建议您通过限制 Actions autoscaling:SetDesiredCapacity 和 Auto Scaling 组autoscaling:TerminateInstanceInAutoScalingGroup来使用最低权限访问权限,这些组的作用域仅限于当前集群。

这将防止在一个集群中运行的集群 Autoscaler 修改另一个集群中的节点组,即使--node-group-auto-discovery参数没有使用标签(例如)限定到集群的节点组。k8s.io/cluster-autoscaler/<cluster-name>

{ "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup" ], "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/k8s.io/cluster-autoscaler/enabled": "true", "aws:ResourceTag/k8s.io/cluster-autoscaler/my-cluster": "owned" } } }, { "Effect": "Allow", "Action": [ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeLaunchConfigurations", "autoscaling:DescribeScalingActivities", "autoscaling:DescribeTags", "ec2:DescribeImages", "ec2:DescribeInstanceTypes", "ec2:DescribeLaunchTemplateVersions", "ec2:GetInstanceTypesFromInstanceRequirements", "eks:DescribeNodegroup" ], "Resource": "*" } ] }

配置您的节点组

有效的自动扩展首先要为您的集群正确配置一组节点组。选择正确的节点组集是最大限度地提高可用性和降低工作负载成本的关键。AWS 使用 EC2 自动扩展组实现节点组,这些组可灵活应对大量用例。但是,集群自动扩缩器会对您的节点组做出一些假设。保持您的 EC2 Auto Scaling 组配置与这些假设保持一致将最大限度地减少不良行为。

请确保:

  • 节点组中的每个节点都有相同的调度属性,例如标签、污点和资源。

    • 对于 MixedInstancePolicies,CPU、内存和 GPU 的实例类型必须具有相同的形状

    • 策略中指定的第一个实例类型将用于模拟调度。

    • 如果您的策略有额外的实例类型和更多的资源,则横向扩展后可能会浪费资源。

    • 如果您的策略有额外的实例类型和较少的资源,则 pod 可能无法在实例上调度。

  • 与节点较少的许多节点组相比,具有许多节点的节点组更受青睐。这将对可扩展性产生最大的影响。

  • 当两个系统都提供支持时,尽可能首选 EC2 功能(例如区域、 MixedInstancePolicy)

注意

我们建议使用 EKS 托管节点组。托管节点组具有强大的管理功能,包括集群自动扩缩器功能,例如 EC2 Auto Scaling 组自动发现和正常终止节点。

针对性能和可扩展性进行优化

了解自动缩放算法的运行时复杂性将有助于您调整集群自动扩缩器,使其在节点超过 1,000 的大型集群中继续平稳运行。

调整集群 Autoscaler 可扩展性的主要旋钮是为进程提供的资源、算法的扫描间隔以及集群中节点组的数量。该算法的真正运行时复杂性还涉及其他因素,例如调度插件的复杂性和 pod 的数量。这些参数被认为是不可配置的参数,因为它们是集群工作负载的自然参数,不容易进行调整。

集群 Autoscaler 将整个集群的状态加载到内存中,包括 Pod、节点和节点组。在每个扫描间隔中,该算法会识别不可调度的 pod 并模拟每个节点组的调度。调整这些因素需要不同的权衡取舍,应根据您的用例仔细考虑。

垂直自动缩放集群自动缩放器

将集群 Autoscaler 扩展到更大的集群的最简单方法是增加其部署的资源请求。对于大型集群,应增加内存和 CPU,尽管这会随集群大小而有很大差异。自动缩放算法将所有 Pod 和节点存储在内存中,在某些情况下,这可能会导致内存占用量超过 1 GB。增加资源通常是手动完成的。如果你发现持续的资源调整会带来运营负担,可以考虑使用插件调整器垂直容器自动缩放器。

减少节点组的数量

最大限度地减少节点组的数量是确保集群 Autoscaler 在大型集群上继续保持良好性能的一种方法。对于某些按团队或每个应用程序构建节点组的组织来说,这可能具有挑战性。尽管这完全受到 Kubernetes API 的支持,但它被视为集群自动缩放器的反模式,会对可扩展性产生影响。使用多个节点组(例如 Spot 或 GPU)的原因有很多,但在许多情况下,还有一些替代设计可以在使用少量组的同时达到相同的效果。

请确保:

  • Pod 隔离是使用命名空间而不是节点组完成的。

    • 这在低信任的多租户集群中可能不可能。

    • Pod ResourceRequests 和 ResourceLimits 已正确设置以避免资源争用。

    • 更大的实例类型将带来更优的箱子打包并减少系统容器开销。

  • NodeTaints 或者 NodeSelectors 用于将容器调度为例外情况,而不是按惯例进行调度。

  • 区域资源被定义为具有多个可用区的单个 EC2 Auto Scaling 组。

缩短扫描间隔

较短的扫描间隔(例如 10 秒)将确保集群 Autoscaler 在 pod 不可调度时尽快做出响应。但是,每次扫描都会导致对 Kubernetes API 和 EC2 Auto Scaling Group 或 EKS 托管节点组 API 进行多次 API 调用。这些 API 调用可能会导致您的 Kubernetes 控制平面的速率限制甚至服务不可用。

默认扫描间隔为 10 秒,但在 AWS 上,启动节点启动新实例所需的时间要长得多。这意味着,可以在不显著增加整体纵向扩展时间的情况下提高扫描间隔时间。例如,如果启动节点需要 2 分钟,则将间隔更改为 1 分钟将需要权衡,将 API 调用次数减少 6 倍,扩展速度减慢 38%。

跨节点组分片

可以将集群自动调节器配置为在一组特定的节点组上运行。使用此功能,可以部署集群 Autoscaler 的多个实例,每个实例都配置为在一组不同的节点组上运行。此策略允许您使用任意数量的节点组,交易成本以实现可扩展性。我们仅建议将其用作提高性能的最后手段。

集群自动调节器最初不是为这种配置设计的,因此存在一些副作用。由于分片无法通信,因此多个自动缩放器可能会尝试调度不可调度的 pod。这可能会导致不必要地横向扩展多个节点组。之后,这些额外的节点将缩减规模scale-down-delay

metadata: name: cluster-autoscaler namespace: cluster-autoscaler-1 ... --nodes=1:10:k8s-worker-asg-1 --nodes=1:10:k8s-worker-asg-2 --- metadata: name: cluster-autoscaler namespace: cluster-autoscaler-2 ... --nodes=1:10:k8s-worker-asg-3 --nodes=1:10:k8s-worker-asg-4

请确保:

  • 每个分片都配置为指向一组独特的 EC2 Auto Scaling 组

  • 每个分片都部署到单独的命名空间以避免领导者选举冲突

优化成本和可用性

竞价型实例

您可以在节点组中使用竞价型实例,最多可节省按需价格的90%,但要权衡一下,当EC2需要恢复容量时,竞价型实例可以随时中断。当您的 EC2 Auto Scaling 组由于可用容量不足而无法向上扩展时,就会出现容量不足错误。通过选择多个实例系列来最大限度地提高多样性可以增加利用多个竞价容量池实现所需规模的机会,并减少竞价型实例中断对集群可用性的影响。包含 Spot 实例的混合实例策略是在不增加节点组数量的情况下提高多样性的好方法。请记住,如果您需要有保障的资源,请使用 On-Demand 实例而不是竞价型实例。

配置混合实例策略时,所有实例类型都必须具有相似的资源容量。自动缩放程序的调度模拟器使用了 InstanceType 中的第一个。 MixedInstancePolicy如果后续实例类型更大,则在向上扩展后可能会浪费资源。如果容量较小,则由于容量不足,您的 pod 可能无法在新实例上进行调度。例如,M4、M5、M5a 和 M5n 实例都具有相似数量的 CPU 和内存,是理想的候选对象。 MixedInstancePolicyEC2 实例选择器工具可以帮助您识别相似的实例类型。

Spot_mix_instance_policy

建议将容量隔离 On-Demand 并分配到单独的 EC2 Auto Scaling 组中。这比使用基本容量策略更可取,因为调度属性根本不同。由于竞价型实例随时会中断(当 EC2 需要恢复容量时),因此用户通常会污染其抢占节点,要求对抢占行为进行明确的 pod 容忍。这些污点会导致节点的调度属性不同,因此应将它们分成多个 EC2 Auto Scaling 组。

集群自动扩缩器有一个扩展器的概念,它为选择要扩展的节点组提供了不同的策略。该策略--expander=least-waste是一个很好的通用默认策略,如果您打算使用多个节点组来实现竞价型实例多样化(如上图所述),则可以通过扩展节点组来进一步优化节点组的成本,而扩展活动结束后最能利用该组。

优先考虑节点组/ASG

您也可以使用优先级扩展器配置基于优先级的自动缩放。--expander=priority使您的集群能够优先考虑节点组/ ASG,如果由于任何原因无法扩展,它将选择优先级列表中的下一个节点组。例如,这在您想要使用 P3 实例类型的情况下很有用,因为它们的 GPU 可为您的工作负载提供最佳性能,但作为第二种选择,您也可以使用 P2 实例类型。

apiVersion: v1 kind: ConfigMap metadata: name: cluster-autoscaler-priority-expander namespace: kube-system data: priorities: |- 10: - .*p2-node-group.* 50: - .*p3-node-group.*

集群 Autoscaler 将尝试向上扩展名为 p3-node-group 的 EC2 Auto Scaling 组。如果此操作在内部不成功--max-node-provision-time,它将尝试扩展名为 p2- node-group 的 EC2 Auto Scaling 组。该值默认为 15 分钟,可以缩短以提高节点组选择的响应速度,但如果该值太低,可能会导致不必要的横向扩展。

超额配置

Cluster Autoscaler 通过确保仅在需要时向集群添加节点并在未使用时移除节点,从而最大限度地降低成本。这会显著影响部署延迟,因为许多 Pod 将被迫等待节点向上扩展后才能进行调度。节点可能需要几分钟才能使用,这可能会将 Pod 调度延迟增加一个数量级。

此问题可以通过超额配置来缓解,超额配置是以成本换取调度延迟。过度配置是使用优先级为负的临时 Pod 实现的,这会占用集群中的空间。当新创建的 pod 不可调度且优先级更高时,临时 pod 将被抢占以腾出空间。然后,临时 Pod 变得不可调度,从而触发集群 Autoscaler 向外扩展新的超额配置节点。

过度配置还有其他不太明显的好处。在不进行过度配置的情况下,高利用率集群的副作用之一是,Pod 将使用 Pod 或 Node Affinity preferredDuringSchedulingIgnoredDuringExecution 规则做出不太理想的调度决策。一个常见的用例是使用跨可用区将高可用性应用程序的容器分开 AntiAffinity。过度配置可以显著增加正确区域的节点可用的机会。

对于您的组织而言,超额预置容量是一项谨慎的业务决策。从本质上讲,它是性能和成本之间的权衡。做出此决定的方法之一是确定您的平均向上扩展频率,然后将其除以向上扩展新节点所需的时间。例如,如果您平均每隔 30 秒需要一个新节点,而 EC2 需要 30 秒来预置新节点,则单个预留节点将确保始终有额外的节点可用,从而以额外一个 EC2 实例为代价将调度延迟降低 30 秒。为了改进分区调度决策,过度配置相当于您的 EC2 Auto Scaling 组中可用区域数量的节点数量,以确保调度器可以为传入的 Pod 选择最佳区域。

防止缩小规模驱逐

移出某些工作负载成本非常高昂。大数据分析、机器学习任务和测试运行器最终将完成,但如果中断,必须重新启动。集群 Autoscaler 将尝试向下扩展利用率阈值下的任何节点进行缩减,这将中断该节点上所有剩余的 Pod。通过确保驱逐成本高昂的 Pod 受到集群 Autoscaler 识别的标签的保护,可以防止出现这种情况。

请确保:

  • 驱逐 pod 的代价高昂有注解 cluster-autoscaler.kubernetes.io/safe-to-evict=false

高级使用案例

EBS 卷

持久存储对于构建有状态的应用程序(例如数据库或分布式缓存)至关重要。EBS 卷在 Kubernetes 上启用了此用例,但仅限于特定的区域。如果为每个可用区使用单独的 EBS 卷在多个可用区之间进行分片,则这些应用程序可以实现高可用性。然后,集群自动扩缩器可以平衡 EC2 自动扩展组的扩展。

请确保:

  • 通过设置 balance-similar-node-groups=true 启用节点组平衡。

  • 除了不同的可用区域和 EBS 卷外,节点组的配置设置相同。

Co-Scheduling

Machine Learning 分布式培训作业可从同区节点配置的最小化延迟中获益匪浅。这些工作负载将多个 Pod 部署到特定区域。这可以通过为所有联合调度的 pod 设置 Pod 关联性或使用设置节点亲和性来实现。topologyKey: failure-domain.beta.kubernetes.io/zone然后,集群自动扩缩器将横向扩展特定区域以满足需求。您可能希望分配多个 EC2 Auto Scaling 组,每个可用区一个,以便为整个共同计划的工作负载启用故障转移。

请确保:

加速器

一些集群利用 GPU 等专用硬件加速器。横向扩展时,加速器设备插件可能需要几分钟才能向集群发布资源。集群 Autoscaler 已模拟该节点将拥有加速器,但是在加速器准备就绪并更新节点的可用资源之前,无法在该节点上调度待处理的 pod。这可能会导致重复、不必要的横向扩展

此外,即使加速器未使用,也不会考虑向下扩展具有加速器和 CPU 或内存利用率较高的节点。由于加速器的相对成本,这种行为可能会很昂贵。相反,如果节点的加速器未被占用,集群自动调节器可以应用特殊规则来考虑向下扩展。

为确保这些情况下的行为正确,您可以在加速器节点上配置 kubelet,以便在节点加入集群之前对其进行标记。集群自动扩缩器将使用此标签选择器来触发加速器优化行为。

请确保:

  • 适用于 GPU 节点的 Kubelet 配置为 --node-labels k8s.amazonaws.com/accelerator=$ACCELERATOR_TYPE

  • 带有加速器的节点遵循上述相同的调度属性规则。

从 0 缩放

集群 Autoscaler 能够将节点组扩展到零或从零扩展到零,这可以节省大量成本。它通过检查 Auto Scaling 组中InstanceType 指定的 CPU、内存和 GPU 资源来检测 Auto Scaling 组的 CPU、内存和 GPU 资源。 LaunchConfiguration LaunchTemplate有些 pod 需要额外的资源,例如WindowsENIPrivateIPv4Address或特定资源 NodeSelectors 或污点,这些资源无法从中 LaunchConfiguration发现。集群自动扩缩器可以通过从 EC2 Auto Scaling 组的标签中发现这些因素来考虑这些因素。例如:

Key: k8s.io/cluster-autoscaler/node-template/resources/$RESOURCE_NAME Value: 5 Key: k8s.io/cluster-autoscaler/node-template/label/$LABEL_KEY Value: $LABEL_VALUE Key: k8s.io/cluster-autoscaler/node-template/taint/$TAINT_KEY Value: NoSchedule
注意

请记住,当扩展到零时,您的容量将返回 EC2,将来可能不可用。

其他参数

有许多配置选项可用于调整 Cluster Autoscaler 的行为和性能。完整的参数列表可在上找到GitHub

参数 说明 默认

扫描间隔

重新评估集群以向上或向下扩展的频率

10 秒

最大缩小并行度

可以并行删除的最大节点数(包括空的和需要排空的)。集群 Autoscaler v1.32.0 已弃用--max-empty-bulk-delete,取而代之的是。--max-scale-down-parallelism如果您使用早于 v1.32.0 的集群自动扩缩器版本,请改用。--max-empty-bulk-delete

10

向下缩小添加后延迟

缩小规模评估将在扩大规模后多久恢复

10 分钟

向下缩小删除后延迟

在删除节点后多长时间内,缩小评估将恢复,默认为扫描间隔

扫描间隔

缩小规模失败后延迟

缩小规模评估在缩小规模失败后多久会恢复

3 分钟

缩小不必要的时间

一个节点需要多长时间才有资格缩小规模

10 分钟

缩小未就绪时间

一个未就绪的节点需要多长时间才有资格缩小规模

20 分钟

缩小利用率阈值

节点利用率,定义为请求的资源总和除以容量,低于该水平的节点可以考虑缩小容量

0.5

缩小非空候选人数

在一次迭代中考虑作为向下扩展候选的非空节点的最大数量。较低的值意味着更好的 CA 响应能力,但缩减延迟的时间可能更慢。较高的值会影响大型集群(数百个节点)的 CA 性能。设置为非正值可关闭此启发式方法-CA 不会限制其考虑的节点数量。”

30

缩小候选人池比例

当先前迭代的某些候选节点不再有效时,被视为向下扩展的额外非空候选节点的比例。较低的值意味着更好的 CA 响应能力,但缩减延迟的时间可能更慢。较高的值会影响大型集群(数百个节点)的 CA 性能。设置为 1.0 以关闭此启发式算法-CA 将所有节点作为其他候选节点。

0.1

缩小候选人库最小数量

当先前迭代的某些候选节点不再有效时,被视为向下扩展的额外非空候选节点的最小数量。在计算其他候选人的人才库规模时,我们采取 max(#nodes * scale-down-candidates-pool-ratio, scale-down-candidates-pool-min-count)

50

其他资源

本页包含集群自动扩缩器演示和演示的列表。如果您想在此处添加演示文稿或演示,请发送拉取请求。

Presentation/Demo 演示者

在 Kubernetes 上自动缩放和成本优化:从 0 到 100

Guy Templeton、Skyscanner 和 Jiaxin Shan,亚马逊

SIG-Autoscaling 深度潜水

Maciek Pytel & Marcin Wielgus

参考

  • https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md

  • https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md

  • https://github.com/aws/amazon-ec2-instance-selector

  • https://github.com/aws/aws-node-termination-handler