--- title: Node 自动扩缩容 linkTitle: Node 自动扩缩容 description: >- 自动在集群中制备和整合 Node,以适应需求并优化成本。 content_type: concept weight: 15 --- 为了在集群中运行负载,你需要 {{< glossary_tooltip text="Node" term_id="node" >}}。 集群中的 Node 可以被**自动扩缩容**: 通过动态[**制备**](#provisioning)或[**整合**](#consolidation)的方式提供所需的容量并优化成本。 自动扩缩容操作是由 Node [**Autoscaler**](#autoscalers) 执行的。 ## Node 制备 {#provisioning} 当集群中有 Pod 无法被调度到现有 Node 上时,系统将**制备**新的 Node 并将其添加到集群中,以容纳这些 Pod。 如果由于组合使用[水平负载和 Node 自动扩缩容](#horizontal-workload-autoscaling)使得 Pod 个数随着时间发生变化,这种自动扩缩容机制将特别有用。 Autoscaler 通过创建和删除云驱动基础资源来制备 Node。最常见的支撑 Node 的资源是虚拟机(VM)。 制备的主要目标是使所有 Pod 可调度。 由于各种限制(如已达到配置的制备上限、制备配置与特定 Pod 集不兼容或云驱动容量不足),此目标不一定总是可以实现。 在制备之时,Node Autoscaler 通常还会尝试实现其他目标(例如最小化制备 Node 的成本或在故障域之间平衡 Node 的数量)。 在决定制备 Node 时针对 Node Autoscaler 有两个主要输入: - [Pod 调度约束](#provisioning-pod-constraints) - [Autoscaler 配置所施加的 Node 约束](#provisioning-node-constraints) Autoscaler 配置也可以包含其他 Node 制备触发条件(例如 Node 个数低于配置的最小限制值)。 {{< note >}} 在 Cluster Autoscaler 中,制备以前称为**扩容**。 {{< /note >}} ### Pod 调度约束 {#provisioning-pod-constraints} Pod 可以通过[调度约束](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/)表达只能调度到特定类别 Node 的限制。 Node Autoscaler 会考虑这些约束,确保 Pending 的 Pod 可以被调度到这些制备的 Node 上。 最常见的调度约束是通过 Pod 容器所指定的资源请求。 Autoscaler 将确保制备的 Node 具有足够资源来满足这些请求。 但是,Autoscaler 不会在 Pod 开始运行之后直接考虑这些 Pod 的真实资源用量。 要根据实际负载资源用量自动扩缩容 Node, 你可以组合使用[水平负载自动扩缩容](#horizontal-workload-autoscaling)和 Node 自动扩缩容。 其他常见的 Pod 调度约束包括 [Node 亲和性](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity)、 [Pod 间亲和性/反亲和性](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity)或特定[存储卷](/docs/concepts/storage/volumes/)的要求。 ### Autoscaler 配置施加的 Node 约束 {#provisioning-node-constraints} 已制备的 Node 的具体规格(例如资源量、给定标签的存在与否)取决于 Autoscaler 配置。 Autoscaler 可以从一组预定义的 Node 配置中进行选择,或使用[自动制备](#autoprovisioning)。 ### 自动制备 {#autoprovisioning} Node 自动制备是一种用户无需完全配置 Node 容许制备规格的制备模式。 Autoscaler 会基于 Pending 的 Pod 和预配置的约束(例如最小资源量或给定标签的需求)动态选择 Node 配置。 ## Node 整合 {#consolidation} 运行集群时的主要考量是确保所有可调度 Pod 都在运行,并尽可能降低集群成本。 为此,Pod 的资源请求应尽可能利用 Node 的更多资源。 从这个角度看,集群中的整体 Node 利用率可以用作集群成本效益的参考指标。 {{< note >}} 对于集群的整体成本效益而言,正确设置 Pod 的资源请求与优化 Node 的利用率同样重要。 将 Node 自动扩缩容与[垂直负载自动扩缩容](#vertical-workload-autoscaling)结合使用有助于实现这一目标。 {{< /note >}} 集群中的 Node 可以被自动**整合**,以提高整体 Node 利用率以及集群的成本效益。 整合操作通过移除一组利用率低的 Node 来实现。有时会同时[制备](#provisioning)一组不同的 Node 来替代。 与制备类似,整合操作在做出决策时仅考虑 Pod 的资源请求而非实际的资源用量。 在整合过程中,如果一个 Node 上仅运行 DaemonSet 和静态 Pod,这个 Node 就会被视为**空的**。 在整合期间移除空的 Node 要比操作非空 Node 更简单直接,Autoscaler 通常针对空 Node 整合进行优化。 在整合期间移除非空 Node 会有破坏性:Node 上运行的 Pod 会被终止,且可能需要被重新创建(例如由 Deployment 重新创建)。 不过,所有被重新创建的 Pod 都应该能够被调度到集群中的现有 Node 上,或调度到作为整合一部分而制备的替代 Node 上。 __正常情况下,整合操作不应导致 Pod 处于 Pending 状态。__ {{< note >}} Autoscaler 会预测在 Node 被制备或整合后重新创建的 Pod 将可能以何种方式调度,但 Autoscaler 不控制实际的调度行为。 因此,某些 Pod 可能由于整合操作而进入 Pending 状态。例如在执行整合过程中,出现一个全新的 Pod。 {{< /note >}} Autoscaler 配置还可以设为由其他状况触发整合(例如 Node 被创建后用掉的时间),以优化属性(例如集群中 Node 的最大生命期)。 执行整合的具体方式取决于给定 Autoscaler 的配置。 {{< note >}} 在 Cluster Autoscaler 中, 整合以前称为**缩容**。 {{< /note >}} ## Autoscaler {#autoscalers} 上述章节中所述的功能由 Node **Autoscaler** 提供。 除了 Kubernetes API 之外,Autoscaler 还需要与云驱动 API 交互来制备和整合 Node。 这意味着 Autoscaler 需要与每个支持的云驱动进行显式集成。 给定的 Autoscaler 的性能和特性集在不同云驱动集成之间可能有所不同。 {{< mermaid >}} graph TD na[Node Autoscaler] k8s[Kubernetes] cp[云驱动] k8s --> |获取 Pod/Node|na na --> |腾空 Node|k8s na --> |创建/移除支撑 Node 的资源|cp cp --> |获取支撑 Node 的资源|na classDef white_on_blue fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; classDef blue_on_white fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; class na blue_on_white; class k8s,cp white_on_blue; {{}} ### Autoscaler 实现 [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) 和 [Karpenter](https://github.com/kubernetes-sigs/karpenter) 是目前由 [SIG Autoscaling](https://github.com/kubernetes/community/tree/master/sig-autoscaling) 维护的两个 Node Autoscaler。 对于集群用户来说,这两个 Autoscaler 都应提供类似的 Node 自动扩缩容体验。 两个 Autoscaler 都将为不可调度的 Pod 制备新的 Node,也都会整合利用率不高的 Node。 不同的 Autoscaler 还可能提供本文所述的 Node 自动扩缩容范围之外的其他特性,且这些额外的特性也会有所不同。 请参阅以下章节和特定 Autoscaler 的关联文档,了解哪个 Autoscaler 更适合你的使用场景。 #### Cluster Autoscaler Cluster Autoscaler 通过向预先配置的 **Node 组**添加或移除 Node。 Node 组通常映射为某种云驱动资源组(最常见的是虚拟机组)。 单实例的 Cluster Autoscaler 将可以同时管理多个 Node 组。 在制备时,Cluster Autoscaler 将把 Node 添加到最贴合 Pending Pod 请求的组。 在整合时,Cluster Autoscaler 始终选择要移除的特定 Node,而不只是重新调整云驱动资源组的大小。 更多信息: * [文档概述](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/README.md) * [云驱动集成](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/README.md#faqdocumentation) * [Cluster Autoscaler FAQ](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md) * [联系方式](https://github.com/kubernetes/community/tree/master/sig-autoscaling#contact) #### Karpenter Karpenter 基于集群操作员所提供的 [NodePool](https://karpenter.sh/docs/concepts/nodepools/) 配置来自动制备 Node。Karpenter 处理 Node 生命周期的所有方面,而不仅仅是自动扩缩容。 这包括 Node 达到某个生命期后的自动刷新,以及在有新 Worker Node 镜像被发布时的自动升级。 Karpenter 直接与特定的云驱动资源(通常是单独的虚拟机)交互,不依赖云驱动资源组。 更多上下文信息: * [官方文档](https://karpenter.sh/) * [云驱动集成](https://github.com/kubernetes-sigs/karpenter?tab=readme-ov-file#karpenter-implementations) * [Karpenter FAQ](https://karpenter.sh/docs/faq/) * [联系方式](https://github.com/kubernetes-sigs/karpenter#community-discussion-contribution-and-support) #### 实现对比 Cluster Autoscaler 和 Karpenter 之间的主要差异: * Cluster Autoscaler 仅提供与 Node 自动扩缩容相关的特性。 而 Karpenter 的特性范围更大,还提供 Node 生命周期管理 (例如在 Node 达到某个生命期后利用中断来自动重新创建 Node,或自动将 Node 升级到新版本)。 * Cluster Autoscaler 不支持自动制备,其可以制备的 Node 组必须被预先配置。 Karpenter 支持自动制备,因此用户只需为制备的 Node 配置一组约束,而不需要完整同质化的组。 * Cluster Autoscaler 直接提供云驱动集成,这意味着这些集成组件是 Kubernetes 项目的一部分。 对于 Karpenter,Kubernetes 将 Karpenter 发布为一个库,云驱动可以集成这个库来构建 Node Autoscaler。 * Cluster Autoscaler 为众多云驱动提供集成,包括一些小众的云驱动。 Karpenter 支持的云驱动相对较少,目前包括 [AWS](https://github.com/aws/karpenter-provider-aws) 和 [Azure](https://github.com/Azure/karpenter-provider-azure)。 ## 组合使用负载自动扩缩容与 Node 自动扩缩容 {#combine-workload-and-node-autoscaling} ### 水平负载自动扩缩容 {#horizontal-workload-autoscaling} Node 自动扩缩容通常是为了响应 Pod 而发挥作用的。 它会制备新的 Node 容纳不可调度的 Pod,并在不再需要这些 Pod 时整合 Node。 [水平负载自动扩缩容](/zh-cn/docs/concepts/workloads/autoscaling#scaling-workloads-horizontally) 自动扩缩负载副本的个数以保持各个副本达到预期的平均资源利用率。 换言之,它会基于应用负载而自动创建新的 Pod,并在负载减少时移除 Pod。 如果应用负载增加,其 Pod 的平均利用率也会增加,将提示负载自动扩缩容以创建新的 Pod。 Node 自动扩缩容随之应制备新的 Node 以容纳新的 Pod。 一旦应用负载减少,负载自动扩缩容应移除不必要的 Pod。 Node 自动扩缩容应按序整合不再需要的 Node。 如果配置正确,这种模式确保你的应用在需要时始终有足够的 Node 容量处理突发负载,你也无需在闲置时为这些 Node 容量支付费用。 ### 垂直负载自动扩缩容 {#vertical-workload-autoscaling} 在使用 Node 自动扩缩容时,重要的是正确设置 Pod 资源请求。 如果给定 Pod 的请求过低,为其制备新的 Node 可能对 Pod 实际运行并无帮助。 如果给定 Pod 的请求过高,则可能对整合 Node 有所妨碍。 [垂直负载自动扩缩容](/zh-cn/docs/concepts/workloads/autoscaling#scaling-workloads-vertically) 基于其历史资源用量来自动调整 Pod 的资源请求。 你可以一起使用 Node 自动扩缩容和垂直负载自动扩缩容,以便在集群中保留 Node 自动扩缩容能力的同时调节 Pod 的资源请求。 {{< caution >}} 在使用 Node 自动扩缩容时,不推荐为 DaemonSet Pod 配置垂直负载自动扩缩容。 Autoscaler 需要预测新 Node 上的 DaemonSet Pod 情况,才能预测可用的 Node 资源。 垂直负载自动扩缩容可能会让这些预测不可靠,导致扩缩容决策出错。 {{}} ## 相关组件 {#related-components} 本节以下组件提供与 Node 自动扩缩容相关的功能。 ### Descheduler [Descheduler](https://github.com/kubernetes-sigs/descheduler) 组件基于自定义策略提供 Node 整合功能,以及与优化 Node 和 Pod 相关的其他特性(例如删除频繁重启的 Pod)。 ### 基于集群规模的负载 Autoscaler [Cluster Proportional Autoscaler](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler) 和 [Cluster Proportional Vertical Autoscaler](https://github.com/kubernetes-sigs/cluster-proportional-vertical-autoscaler) 基于集群中的 Node 个数进行水平和垂直负载自动扩缩容。 更多细节参阅[基于集群规模自动扩缩容](/zh-cn/docs/concepts/workloads/autoscaling#autoscaling-based-on-cluster-size)。 ## {{% heading "whatsnext" %}} - 阅读[负载层面的自动扩缩容](/zh-cn/docs/concepts/workloads/autoscaling/)