Cluster Autoscaler - Amazon EKS

Cluster Autoscaler

当 Pod 失败或被重新安排到其他节点时,Kubernetes Cluster Autoscaler 会自动调整集群中的节点数。Cluster Autoscaler 通常作为部署安装在集群中。它使用领导选举来确保高可用性,但一次只能由一个副本完成扩展。

在部署集群 Cluster Autoscaler 之前,请确保您熟悉 Kubernetes 概念与AWS功能相互联系的方式。本主题中使用了以下术语:

  • Kubernetes Cluster Autocaler – Kubernetes 控制层面的核心组件,用于制定调度和扩缩决策。有关更多信息,请参阅 GitHub 上的 Kubernetes 控制层面常见问题

  • AWS云提供商实施 – Kubernetes Cluster Autoscaler 的扩展,通过与AWS产品和服务(例如 Amazon EC2)通信实施 Kubernetes Cluster Autoscaler 的决策。有关更多信息,请在 GitHub 上参阅AWS上的 Cluster Autoscaler

  • 节点组 – 集群中一组节点的 Kubernetes 抽象。节点组不是真正的 Kubernetes 资源,但它们在 Cluster Autoscaler、集群 API 和其他组件中作为抽象被找到。在单个节点组中找到的节点可能共享多个常见属性,如标签和污点。但是,它们仍然可以由多个可用区或实例类型组成。

  • Amazon EC2 Auto Scaling 组 – 为 Cluster Autoscaler 所用的一个AWS功能。Auto Scaling 组适用于大量使用案例。Amazon EC2 Auto Scaling 组配置为启动自动加入其 Kubernetes 集群的实例。它们还将标签和污点应用到 Kubernetes API 中的相应节点资源。

作为参考,托管节点组 使用 Amazon EC2 Auto Scaling 组进行管理,并且与 Cluster Autoscaler 兼容。

本主题说明如何将 Cluster Autoscaler 部署到 Amazon EKS 集群以及如何配置它来修改 Amazon EC2 Auto Scaling 组。

Prerequisites

在部署集群 Cluster Autoscaler之前,您必须满足以下先决条件:

  • 拥有现有 Kubernetes 集群 – 如果您没有集群,请参阅 创建 Amazon EKS 集群

  • 集群的现有 IAM OIDC 提供商。要确定是否具有 IAM OIDC 提供商,还是需要创建一个,请参阅 为集群创建 IAM OIDC 提供商

  • 具有 Auto Scaling 组标签的节点组 – Cluster Autoscaler 要求 Auto Scaling 组带有以下标签,以便能够自动发现它们。

    • 如果您使用 eksctl 创建节点组,则节点组会自动应用这些标签。

    • 如果未使用 eksctl,则必须使用以下标签手动标记您的 Auto Scaling 组。有关更多信息,请参阅适用于 Linux 实例的 Amazon EC2 用户指南 中的标记 Amazon EC2 资源

    密钥
    k8s.io/cluster-autoscaler/<cluster-name>

    owned

    k8s.io/cluster-autoscaler/enabled TRUE

创建 IAM 策略和角色

创建授予 Cluster Autoscaler 使用 IAM 角色所需权限的 IAM 策略。将整个过程中的所有 <example-values>(包括 <>)替换为您自己的值。

  1. 创建一个 IAM 策略。

    1. 将以下内容保存到名为 cluster-autoscaler-policy.json 的文件中。如果现有节点组是使用 eksctl 创建的并且您使用了 --asg-access 选项,则此策略已存在,您可以跳至第 2 步。

      { "Version": "2012-10-17", "Statement": [ { "Action": [ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeLaunchConfigurations", "autoscaling:DescribeTags", "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup", "ec2:DescribeLaunchTemplateVersions" ], "Resource": "*", "Effect": "Allow" } ] }
    2. 使用以下命令创建策略。您可以更改 policy-name 的值。

      aws iam create-policy \ --policy-name AmazonEKSClusterAutoscalerPolicy \ --policy-document file://cluster-autoscaler-policy.json

      记下输出中返回的 Amazon Resource Name (ARN)。您需要在后面的步骤中用到它。

  2. 您可以创建一个 IAM 角色并使用 eksctl 或 AWS Management Console 向其附加 IAM 策略。为以下说明选择所需的选项卡。

    eksctl
    1. 如果您使用 eksctl 创建集群,请运行以下命令。如果您使用 --asg-access 选项创建集群,请将 <AmazonEKSClusterAutoscalerPolicy> 替换为 eksctl 为您创建的 IAM 策略的名称。策略名称类似于 eksctl-<cluster-name>-nodegroup-ng-<xxxxxxxx>-PolicyAutoScaling

      eksctl create iamserviceaccount \ --cluster=<my-cluster> \ --namespace=kube-system \ --name=cluster-autoscaler \ --attach-policy-arn=arn:aws:iam::<AWS_ACCOUNT_ID>:policy/<AmazonEKSClusterAutoscalerPolicy> \ --override-existing-serviceaccounts \ --approve
    2. 如果您使用 --asg-access 选项创建集群,我们建议您分离 eksctl 创建的 IAM 策略,然后将其附加到 eksctl 为节点组创建的 Amazon EKS 节点 IAM 角色。将策略与节点 IAM 角色分离,以便 Cluster Autoscaler 正常运行。分离策略不会为节点上的其他 Pod 提供策略中的权限。有关更多信息,请参阅适用于 Linux 实例的 Amazon EC2 用户指南中的删除 IAM 身份权限

    AWS Management Console
    1. 通过以下网址打开 IAM 控制台:https://console.aws.amazon.com/iam/

    2. 在导航窗格中,选择 Roles(角色)Create Role(创建角色)

    3. Select type of trusted entity (选择受信任实体的类型) 部分中,选择 Web identity (Web 身份)

    4. Choose a web identity provider (选择 Web 身份提供商) 部分中:

      1. 对于 Identity provider (身份提供商),选择您集群的 URL。

      2. 对于 Audience (受众),请选择 sts.amazonaws.com

    5. 选择下一步: 权限

    6. Attach Policy(附加策略)部分中,选择您在第 1 步中创建以用于服务账户的 AmazonEKSClusterAutoscalerPolicy 策略。

    7. 选择下一步: 标签

    8. Add tags (optional) (添加标签(可选)) 屏幕上,您可以为账户添加标签。选择 Next: Review (下一步: 审核)

    9. 对于 Role name(角色名称),输入角色的名称(如 AmazonEKSClusterAutoscalerRole),然后选择 Create role(创建角色)

    10. 创建角色后,在控制台中选择角色以将其打开进行编辑。

    11. 选择 Trust relationships 选项卡,然后选择 Edit trust relationship

    12. 该行看起来类似于以下行:

      "oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:aud": "sts.amazonaws.com"

      将该行更改为类似于以下行。将 <EXAMPLED539D4633E53DE1B716D3041E>(包括 <>)替换为集群的 OIDC 提供商 ID,并将 <region-code> 替换为集群所在的区域代码。

      "oidc.eks.<region-code>.amazonaws.com/id/<EXAMPLED539D4633E53DE1B716D3041E>:sub": "system:serviceaccount:kube-system:cluster-autoscaler"
    13. 选择 Update Trust Policy (更新可信策略) 以完成操作。

部署 Cluster Autoscaler

要部署 Cluster Autoscaler,请完成以下步骤。建议您查看 部署注意事项 并优化 Cluster Autoscaler 部署,然后再将其部署到生产集群。

部署 Cluster Autoscaler

  1. 部署 Cluster Autoscaler。

    kubectl apply -f https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml
  2. 使用您以前创建的 IAM 角色的 ARN 对 cluster-autoscaler 服务账户添加注释。将<示例值>替换为您自己的值。

    kubectl annotate serviceaccount cluster-autoscaler \ -n kube-system \ eks.amazonaws.com/role-arn=arn:aws:iam::<ACCOUNT_ID>:role/<AmazonEKSClusterAutoscalerRole>
  3. 使用以下命令修补部署以向 Cluster Autoscaler Pod 添加 cluster-autoscaler.kubernetes.io/safe-to-evict 注释。

    kubectl patch deployment cluster-autoscaler \ -n kube-system \ -p '{"spec":{"template":{"metadata":{"annotations":{"cluster-autoscaler.kubernetes.io/safe-to-evict": "false"}}}}}'
  4. 使用以下命令编辑 Cluster Autoscaler 部署。

    kubectl -n kube-system edit deployment.apps/cluster-autoscaler

    编辑 cluster-autoscaler 容器命令,将 <YOUR CLUSTER NAME>(包括 <>)替换为您的集群名称,然后添加以下选项。

    • --balance-similar-node-groups

    • --skip-nodes-with-system-pods=false

    spec: containers: - command: - ./cluster-autoscaler - --v=4 - --stderrthreshold=info - --cloud-provider=aws - --skip-nodes-with-local-storage=false - --expander=least-waste - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<YOUR CLUSTER NAME> - --balance-similar-node-groups - --skip-nodes-with-system-pods=false

    保存并关闭该文件以应用更改。

  5. 在 Web 浏览器中从 GitHub 打开 Cluster Autoscaler 版本页面,找到与您集群的 Kubernetes 主版本和次要版本相匹配的 Cluster Autoscaler 最新版本。例如,如果您集群的 Kubernetes 版本是 1.21,则查找以 1.21 开头的最新 Cluster Autoscaler 版本。记录该版本的语义版本号 (1.21.n) 以在下一步中使用。

  6. 使用以下命令,将 Cluster Autoscaler 映像标签设置为您在上一步中记录的版本。将 1.21.n 替换为您自己的值。

    kubectl set image deployment cluster-autoscaler \ -n kube-system \ cluster-autoscaler=k8s.gcr.io/autoscaling/cluster-autoscaler:v<1.21.n>

查看 Cluster Autoscaler 日志

部署 Cluster Autoscaler 之后,您可以查看日志并验证它在监控您的集群负载。

使用以下命令查看您的 Cluster Autoscaler 日志。

kubectl -n kube-system logs -f deployment.apps/cluster-autoscaler

您可以在一个 (扩展) 代码行中执行所有这些操作:

I0926 23:15:55.165842 1 static_autoscaler.go:138] Starting main loop I0926 23:15:55.166279 1 utils.go:595] No pod using affinity / antiaffinity found in cluster, disabling affinity predicate for this loop I0926 23:15:55.166293 1 static_autoscaler.go:294] Filtering out schedulables I0926 23:15:55.166330 1 static_autoscaler.go:311] No schedulable pods I0926 23:15:55.166338 1 static_autoscaler.go:319] No unschedulable pods I0926 23:15:55.166345 1 static_autoscaler.go:366] Calculating unneeded nodes I0926 23:15:55.166357 1 utils.go:552] Skipping ip-192-168-3-111.<region-code>.compute.internal - node group min size reached I0926 23:15:55.166365 1 utils.go:552] Skipping ip-192-168-71-83.<region-code>.compute.internal - node group min size reached I0926 23:15:55.166373 1 utils.go:552] Skipping ip-192-168-60-191.<region-code>.compute.internal - node group min size reached I0926 23:15:55.166435 1 static_autoscaler.go:393] Scale down status: unneededOnly=false lastScaleUpTime=2019-09-26 21:42:40.908059094 ... I0926 23:15:55.166458 1 static_autoscaler.go:403] Starting scale down I0926 23:15:55.166488 1 scale_down.go:706] No candidates for scale down

部署注意事项

请查看以下注意事项,以优化 Cluster Autoscaler 部署。

扩展注意事项

Cluster Autoscaler 可以配置为包含节点的任何附加功能。这些功能可以包括附加到节点的 Amazon EBS 卷、节点的 Amazon EC2 实例类型或 GPU 加速器。

跨多个可用区设定节点组的范围

我们建议您配置多个节点组,将每个组的范围设定为单个可用区,并启用 --balance-similar-node-groups 功能。如果您只创建一个节点组,则将该节点组的范围设置为跨越多个可用区。

优化节点组

Cluster Autoscaler 会假定您使用节点组的方式,包括您在组中使用的实例类型。要与这些假设保持一致,请根据以下注意事项和建议配置节点组:

  • 节点组中的每个节点必须具有相同的调度属性,包括标签、污点和资源。

    • 对于 MixedInstancePolicies,实例类型必须具有兼容的 CPU、内存和 GPU 规范。

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

    • 如果您的策略具有拥有更多资源的其他实例类型,则在横向扩展后可能会浪费资源。

    • 如果您的策略具有其他实例类型,其资源比原始实例类型少,则 Pod 在实例上调度可能失败。

  • 请使用较多节点配置较少数量的节点组,因为相反的配置可能会对可扩展性产生不利影响。

  • 只要两个系统都为 Amazon EC2 功能提供支持,就可以使用 Amazon EC2 功能(例如,使用区域和 MixedInstancePolicy。)

如果可能,建议您使用 托管节点组。托管节点组附带强大的管理功能。这包括适用于 Cluster Autoscaler 的功能,例如 Amazon EC2 Auto Scaling 自动组发现功能和正常节点终止功能。

将 EBS 卷用作持久性存储

持久性存储对于构建有状态应用程序(如数据库和分布式缓存)至关重要。借助 Amazon EBS 卷,您可以在 Kubernetes 上构建有状态的应用程序。但是,您只能在单个可用区中构建。有关更多信息,请参阅如何使用 Amazon EKS 中的持久性存储?。要获得更好的解决方案,请考虑为每个可用区使用单独的 Amazon EBS 卷构建跨多个可用区的有状态应用程序。这样做意味着您的应用程序可以实现高度可用性。此外,Cluster Autoscaler 还可以平衡 Amazon EC2 Auto Scaling 组的扩展。为此,请确保满足以下条件:

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

  • 将节点组配置为具有相同的设置(除了位于多个可用区内并使用不同的 Amazon EBS 卷之外)。

协同调度

Machine Learning 分布式培训作业可从同区节点配置的最小化延迟中获益匪浅。这些工作负载将多个 Pod 部署到特定区域。您可以通过使用 topologyKey: failure-domain.beta.kubernetes.io/zone 为所有协同调度 Pod 或节点亲和性设置 Pod 亲和性来实现这一点。使用此配置,Cluster Autoscaler 可横向扩展特定区域以满足需求。分配多个 Amazon EC2 Auto Scaling 组,每个可用区分配一个组,以便为整个协同调度工作负载启用故障转移。确保满足以下条件:

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

  • 当集群同时包含区域节点组和可用区节点组时,使用节点亲和性Pod 抢占,或同时使用这二者。

    • 使用节点亲和性强制或鼓励使用区域 Pod 并避免可用区节点组。

    • 不要将可用区 Pod 调度到区域节点组上。将可用区 Pod 调度到区域节点组上可能会导致用于区域 Pod 的容量不均衡。

    • 如果您的可用区工作负载能够容忍中断和重新定位,则可以配置 Pod 抢占。这样做会强制抢占和重新调度区域扩展 Pod 的争夺较少的区。

加速器和 GPU

某些集群使用专用硬件加速器,例如专用 GPU。横向扩展时,加速器可能需要几分钟才能将资源通告到集群。在此期间,Cluster Autoscaler 会模拟此节点具有加速器的情况。但是,在加速器准备就绪并更新节点的可用资源之前,无法在节点上调度待处理的 Pod。这可能会导致重复、不必要的横向扩展

即使加速器未使用,也不会考虑缩减具有加速器和高 CPU 或内存利用率的节点。但这可能会导致不必要的成本。要避免这些成本,在节点具有未占用的加速器的情况下,Cluster Autoscaler 可以应用特殊规则来考虑节点进行缩减。

要确保在这些情况下执行正确行为,请在加速器节点上配置 kubelet,以便在节点加入集群之前对其进行标注。Cluster Autoscaler 会使用此标签选择器调用经加速器优化的行为。确保满足以下条件:

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

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

从零扩展

Cluster Autoscaler 可以将节点组缩减到零和从零扩展节点组。这可以节省大量成本。Cluster Autoscaler 会通过检查其 LaunchConfiguration 或者 LaunchTemplate 中指定的 InstanceType 来检测 Auto Scaling 组的 CPU、内存和 GPU 资源。某些 Pod 需要额外的资源,例如 WindowsENI 或者 PrivateIPv4Address。或者它们可能需要特定的 NodeSelectorsTaints。后两者不能从 LaunchConfiguration 发现。但是 Cluster Autoscaler 可以通过从 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
注意
  • 当缩减到零时,您的容量将返回到 Amazon EC2,并可能会在将来变得不可用。

  • 您可以使用 describeNodegroup 诊断缩减到零和从零扩展时托管节点组存在的问题。

其他配置参数

有许多配置选项可用于调整 Cluster Autoscaler 的行为和性能。有关参数的完整列表,请参阅 GitHub 上面向 CA 的参数是什么?

性能注意事项

您可以更改一些关键项目来优化 Cluster Autoscaler 的性能和可扩展性。主要项目包括提供给进程的任何资源、算法的扫描间隔以及集群中的节点组数。但是,此算法的真正运行时复杂性也涉及其他几个因素,其中包括调度插件的复杂性和 Pod 的数量。这些因素被视为不可配置的参数,因为它们是集群工作负载的组成部分,而且不容易进行优化。

可扩展性是指随着 Kubernetes 集群中的 Pod 和节点数量的增加,Cluster Autoscaler 的性能如何。如果达到其可扩展性配额,则 Cluster Autoscaler 的性能和功能会降低。此外,当超出其可扩展性配额时,Cluster Autoscaler 就无法再添加或删除集群中的节点。

性能是指 Cluster Autoscaler 可以做出和实施扩展决策的速度。性能完美的 Cluster Autoscaler 可以立即做出决策并调用扩展操作,以对特定状况做出响应,例如 Pod 变得不可调度。

熟悉弹性伸缩算法的运行时复杂性。这样可以更轻松地优化 Cluster Autoscaler,以使其在大型集群(具有超过 1000 个节点)中运行良好。

Cluster Autoscaler 会将整个集群的状态加载到内存中,包括 Pod、节点和节点组。在每个扫描间隔时间期间,算法会识别不可调度的 Pod 并模拟每个节点组的调度。请注意,以不同的方式优化这些因素都会需要做出不同的折衷。

垂直弹性伸缩

您可以通过增加其部署的资源请求,将 Cluster Autoscaler 扩展到较大的集群。这是实现这一点的更简单的方法之一。增加大型集群的内存和 CPU。请注意,内存和 CPU 应该增加的量在很大程度上取决于特定的集群大小。弹性伸缩算法将所有 Pod 和节点存储在内存中。在某些情况下,这可能会导致内存占用大于 1 GB。您通常需要手动增加资源。如果您发现经常需要手动增加资源,请考虑使用 Addon ResizerVertical Pod Autoscaler 来自动执行该过程。

减少节点组数量

您可以减少节点组的数量来提高 Cluster Autoscaler 在大型集群中的性能。如果您以单个团队或应用程序为基础构建节点组,此做法可能具有挑战性。虽然 Kubernetes API 完全支持此做法,但它被认为是 Cluster Autoscaler 反面模式,会影响可扩展性。使用多个节点组有许多好处,例如同时使用 Spot 或 GPU 实例。在许多情况下有替代设计,可在使用少量组的同时实现同样效果。确保满足以下条件:

  • 使用命名空间而非节点组来隔离 Pod。

    • 您可能无法在低信任度、多租户集群中采用此做法。

    • 恰当设置 Pod ResourceRequestsResourceLimits 来避免资源争用。

    • 使用较大的实例类型实现更优化的装箱并减少系统 Pod 开销。

  • 避免使用 NodeTaintsNodeSelectors 来调度 Pod。仅在少数情况下使用它们。

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

缩短扫描间隔时间

缩短扫描间隔时间(如原定设置为 10 秒)可确保 Cluster Autoscaler 在 Pod 变为不可调度时尽快做出响应。但是,每次扫描都会导致对 Kubernetes API 和 Amazon EC2 Auto Scaling 组或 Amazon EKS 托管节点组 API 进行多次 API 调用。这些 API 调用可能会导致您的 Kubernetes 控制层面的速率受限甚至服务不可用。

原定设置的扫描间隔时间为十秒,但在AWS上,启动节点需要更长的时间来启动新的实例。这意味着,可以在不显著增加整体纵向扩展时间的情况下提高扫描间隔时间。例如,如果启动节点需要两分钟时间,请不要将扫描间隔更改为一分钟,因为这可能会出现虽然 API 调用减少 6 倍但纵向扩展速度减慢 38%。

跨节点组分区

您可以将 Cluster Autoscaler 配置为对一组特定的节点组进行操作。通过使用此功能,您可以部署 Cluster Autoscaler 的多个实例。将每个实例配置为在一组不同的节点组上运行。这样,您就可以使用任意大量的节点组,从而换取可扩展性的成本。但是,我们只建议您在万不得已时才采用此做法来提高 Cluster Autoscaler 的性能。

这种配置有其缺点:可能会导致多个节点组不必要的横向扩展。在 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

确保满足以下条件。

  • 每个分区都配置为指向一组唯一的 Amazon EC2 Auto Scaling 组。

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

成本效益和可用性

优化 Cluster Autoscaler 成本效益的主要选择与预置 Amazon EC2 实例有关。此外,成本效益必须与可用性保持平衡。本节介绍使用 Spot 实例降低成本和超额配置以减少创建新节点时的延迟等策略。

  • 可用性 – 能够快速、不中断地调度 Pod。即使是在需要调度新创建的 Pod 以及缩减的节点终止向其调度的任何剩余 Pod 时,也能做到这一点。

  • 成本 – 由横向扩展和横向缩减事件背后的决策确定。如果现有节点未充分利用,或添加的新节点对于传入的 Pod 而言太大,则资源将会被浪费。根据具体的使用案例,可能会由于积极的缩减决策导致产生与过早终止 Pod 相关的成本。

Spot 实例

您可以使用节点组中的 Spot 实例,按需价格最高可节省 90%。这可能会在 Amazon EC2 需要收回容量时随时中断 Spot 实例。每当您的 Amazon EC2 Auto Scaling 组由于缺乏可用容量而无法纵向扩展时,就会发生 Insufficient Capacity Errors。选择许多不同的实例系列有两个主要好处。首先,它可以通过利用许多 Spot 容量池来提高您实现所需扩展的机会。其次,它还可以减少 Spot 实例中断对集群可用性的影响。包含 Spot 实例的混合实例策略是在不增加节点组数量的情况下提高多样性的好方法。但是,请注意,如果您需要有保障的资源,请使用按需实例,而不要使用 Spot 实例。

当对实例的需求增加时,可能会终止 Spot 实例。有关更多信息,请参阅适用于 Linux 实例的 Amazon EC2 用户指南中的 Spot 实例中断部分。AWS Node Termination Handler 项目会在节点出现故障时自动提醒 Kubernetes 控制层面。该项目使用 Kubernetes API 封锁节点,确保节点未安排有任何新工作,然后耗尽节点并删除任何现有工作。

在配置混合实例策略时,所有实例类型具有相似的资源容量至关重要。Autoscaler 的调度模拟器使用混合实例策略中的第一个实例类型。如果后续实例类型较大,在纵向扩展后可能会造成资源浪费。如果实例较小,由于容量不足,Pod 可能无法在新实例上实现调度。例如,M4M5M5a,M5n 实例都具有相似数量的 CPU 和内存,是混合实例策略的绝佳候选项。Amazon EC2 实例选择器工具可帮助您识别相似的实例类型。有关更多信息,请参阅 GitHub 上的 Amazon EC2 实例选择器

我们建议您将按需实例和 Spot 实例容量分离到不同的 Amazon EC2 Auto Scaling 组中。由于按需实例和 Spot 实例的调度属性不同,我们建议使用基本容量策略。Spot 实例可以随时中断。当 Amazon EC2 需要收回容量时,抢占节点通常会受到影响,因此需要对抢占行为具有明确的 Pod 容忍度。这就导致了不同的节点调度属性,因此应将它们分到多个 Amazon EC2 Auto Scaling 组中。

Cluster Autoscaler 涉及 Expander 概念。它们共同为选择要扩展的节点组提供了不同的策略。--expander=least-waste 策略是一种不错的通用型原定设置,如果您打算使用多个节点组实现 Spot 实例多样化(如前所述),那么它可以通过扩缩在扩缩活动后利用率最佳的组来进一步优化节点组的成本。

确定节点组或 Auto Scaling 组的优先级

您还可以通过使用 Priority 扩展器来配置基于优先级的弹性伸缩。--expander=priority 使您的集群能够确定节点组或 Auto Scaling 组的优先级,如果节点组由于任何原因无法扩展,则其会选择优先级列表中下一个节点组。这在某些情况下非常有用,例如您想要使用 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.*

Cluster Autoscaler 尝试纵向扩展与名称 p3-node-group 相匹配的 Amazon EC2 Auto Scaling 组。如果此操作在 --max-node-provision-time 内未成功,则其会尝试扩展与名称 p2-node-group 相匹配的 Amazon EC2 Auto Scaling 组。此值原定设置为 15 分钟,可以降低此值以选择响应更快的节点组。但是,如果此值太低,则可能会发生不必要的横向扩展。

Overprovisioning

Cluster Autoscaler 可以确保仅在需要节点时将节点添加到集群,并在节点未使用时删除节点,以此来帮助最大限度地降低成本。这会极大地影响部署延迟,因为许多 Pod 必须等待节点纵向扩展后才能进行调度。节点可能需要几分钟才能使用,这可能会将 Pod 调度延迟增加一个数量级。

此问题可以通过超额配置来缓解,超额配置是以成本换取调度延迟。使用具有负优先级的临时 Pod 来实施超额配置。这些 Pod 占用集群中的空间。当新创建的 Pod 不可调度且具有较高的优先级时,会抢占临时 Pod 以腾出空间。然后,临时 Pod 变得不可调度,从而导致 Cluster Autoscaler 横向扩展新的超额配置节点。

超额配置还有其他好处。在没有超额配置的情况下,高利用率集群中的 Pod 可以使用 preferredDuringSchedulingIgnoredDuringExecution 规则做出次优调度决定。这种情况的一个常见用例是使用 AntiAffinity 跨可用区为高可用性应用程序分离 Pod。超额配置可以显著提高所需区域的节点的可用性几率。

选择适当数量的超额配置容量非常重要。确保选择适当数量的一种方法是,用平均纵向扩展频率除以纵向扩展新节点所需的时间。例如,如果您平均每 30 秒需要一个新节点,而 Amazon EC2 预置新节点需要 30 秒,则超额配置单个节点可确保始终有一个额外的节点可用。这样就可以以单个额外 Amazon EC2 实例为成本将调度延迟减少 30 秒。为了做出更好的分区调度决策,您还可以超额配置节点数,使其与 Amazon EC2 Auto Scaling 组中的可用区数量相同。这样可确保调度器可以为传入 Pod 选择最佳区域。

防止缩减移出

移出某些工作负载成本非常高昂。大数据分析、机器学习任务和测试运行器可能需要很长时间才能完成,而且如果这些过程被中断,必须要重新启动。Cluster Autoscaler 可以帮助缩减 scale-down-utilization-threshold 下的任意节点。此操作会中断节点上的所有剩余 Pod。但是,您可以通过确保使用经 Cluster Autoscaler 认可的标签来保护移出费用较为昂贵的 Pod,来防止发生这种情况。为此,请确保移出费用较为昂贵的 Pod 具有标签 cluster-autoscaler.kubernetes.io/safe-to-evict=false