

 **帮助改进此页面** 

要帮助改进本用户指南，请选择位于每个页面右侧窗格中的**在 GitHub 上编辑此页面**链接。

# EKS 自动模式中的成本优化
<a name="auto-cost-control"></a>

EKS 自动模式可通过合并、装箱以及调整大小来持续集群的优化计算成本。但某些工作负载配置可能会妨碍这些优化。本主题介绍了成本优化的工作原理，可能妨碍成本优化的因素，以及如何配置集群来保持成本效益。

## EKS 自动模式如何优化成本
<a name="_how_eks_auto_mode_optimizes_cost"></a>

EKS 自动模式通过以下机制来降低计算成本：
+  **装箱**：在将容器组调度到节点上时，EKS 自动模式会选择与聚合资源请求高度匹配的实例类型，从而尽可能减少未使用的容量。
+  **整合**：EKS 自动模式会定期评估正在运行的节点，并在可以在数量更少或成本更低的实例上运行工作负载时将替换或移除节点。
+  **调整大小**：EKS 自动模式会随着工作负载的缩减，将容器组整合到较小的节点上，并终止利用不足的实例。

这些优化可持续运行，不需要人工干预。但是，某些容器组注释和 NodePool 配置可能会阻止整合生效。

## 内置节点池和成本护栏
<a name="_built_in_node_pools_and_cost_guardrails"></a>

内置的 `general-purpose` 和 `system` 节点池已经强制执行多项成本保护默认配置：
+  **实例系列仅限于 C、M 和 R 类型**：不允许使用加速型（P、G、Inf、Trn）或特殊实例类型。
+  **仅限按需容量**：不使用竞价型实例，这可以避免中断导致的流失，但也意味着无法享受竞价型实例成本节省。
+  **第 5 代或更高版本**：排除了成本效益较低的旧实例代系。

即使仅使用内置节点池，也已经开始享受这些护栏机制。创建不继承这些限制的**自定义节电池**时，本主题中关于[排除实例系列](#_exclude_instance_families_for_cost_control)和[限制实例大小](#_constrain_instance_sizes)的指南最为相关。

但即使是内置节点池，以下部分也同样适用：
+  [哪些因素会阻止整合](#_what_blocks_consolidation)：无论节点是由哪种节点池预调配的，`do-not-disrupt` 注释和限制性 PDB 都会阻止整合。
+  [将节点池限制作为成本上限](#_use_nodepool_limits_as_a_cost_ceiling)：内置节点池未配置 `limits` 资源。如果工作负载可能会大幅度扩展，请考虑创建具有限制的自定义节点池，而不要依赖无限制的内置池。
+  [节点生命周期和成本](#_node_lifecycle_and_cost)：节点替换覆盖会适用于所有节点，包括由内置池预调配的节点。


| 护栏 | 内置节点池 | 自定义节点池 | 
| --- | --- | --- | 
| 加速型实例排除 | 强制实施 | 您必须配置 | 
| 实例大小限制 | 未设置 | 您必须配置 | 
| 资源 `limits`（CPU/内存上限） | 未设置 | 您必须配置 | 
| 仅按需型实例 | 强制实施 | 您需要选择（竞价型/按需型） | 
| 整合保护（`do-not-disrupt`/PDB） | 由您负责 | 由您负责 | 

## 哪些因素会阻止整合
<a name="_what_blocks_consolidation"></a>

当 EKS 自动模式确定中断某个节点会违反工作负载的可用性要求时，系统将会阻止整合。以下配置会阻止整合：

### `do-not-disrupt` 注释
<a name="_the_do_not_disrupt_annotation"></a>

只要注释的节点组在节点上运行，`karpenter.sh/do-not-disrupt` 注释就会指示 EKS 自动模式保留该节点。这样将会阻止合并、替换或终止该节点，即使该节点利用率不足。

```
metadata:
  annotations:
    karpenter.sh/do-not-disrupt: "true"
```

**重要**  
 **成本影响：**当容器组带有 `do-not-disrupt` 注释时，该容器组运行的节点将免于合并。这意味着：  
无论实际利用率如何，该节点都将继续以当前实例大小运行。
即使工作负载需求减少，该节点上的 vCPU 和内存使用率仍可能保持较高状态。
如果跨多个节点的多个容器组带有此注释，则集群范围的合并会大幅减少，从而导致成本持续更高。
`do-not-disrupt` 注释是一种可用性机制。该机制不会考虑成本。仅将其用于执行中断会导致数据丢失或大量返工的工作负载，例如，长时间运行的批处理作业或没有检查点的状态进程。

 **可考虑的替代方案**：
+  **容器组中断预算（PDB）**：使用 PDB 来控制中断速率，而不是完全阻止。借助 PDB 功能，可以在执行合并的同时确保始终有最低数量的副本可用。
+  **短暂运行的工作负载**：对于 CI/CD 运行器和生成代理，允许中断并依赖 CI 系统的内置重试逻辑，而不是使用 `do-not-disrupt`。
+  **限时注释**：仅在关键操作持续期间执行 `do-not-disrupt`，然后在操作完成后以编程方式将其删除。

### 容器组中断预算（PDB）
<a name="_pod_disruption_budgets_pdbs"></a>

如果 PDB 将 `maxUnavailable: 0` 或 `minAvailable` 设置为等于当前副本数量，这实际上会阻止受影响的容器组的所有合并。请检查 PDB 设置，确保其至少允许一次中断一个容器组。

## 将节点池限制作为成本上限
<a name="_use_nodepool_limits_as_a_cost_ceiling"></a>

节点池 `limits` 规定了一个节点池可以预调配的总计算资源硬上限。达到此限制后，EKS 自动模式将停止为该节点池启动新节点。即使容器组处于待处理状态，也会发生这种情况。

将 `limits` 作为成本护栏使用，尤其是为不适合无限扩展的非生产、测试或爆增性工作负载提供服务的节点池。

```
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: ci-runners
spec:
  template:
    spec:
      nodeClassRef:
        group: eks.amazonaws.com
        kind: NodeClass
        name: default
      requirements:
        - key: "eks.amazonaws.com/instance-category"
          operator: In
          values: ["c", "m"]
  limits:
    cpu: "500"
    memory: 1000Gi
```

在此示例中，`ci-runners` 节点池在其预调配的所有节点上合计不能使用超过 500 个 vCPU 或 1000 GiB 内存。超过此限制的容器组将处于 `Pending` 状态，直到释放相关容量为止。

**提示**  
按照预期最大爆增容量加节点替换所需缓冲区来设置 `limits`。定期检查节点池利用率，并根据工作负载模式的变化调整限制。

## 排除实例系列以控制成本
<a name="_exclude_instance_families_for_cost_control"></a>

默认情况下，EKS 自动模式会从多种实例类型中进行选择，以尽可能提高调度的灵活性。对于不需要专用硬件的工作负载，请限定要使用的实例系列，以防止启动昂贵的实例类型。

### 排除加速型实例
<a name="_exclude_accelerated_instances"></a>

如果工作负载不会请求 GPU 或加速器资源，请从节点池中排除加速型实例系列。这样可以防止在容量受限期间选择加速型实例。

```
spec:
  template:
    spec:
      requirements:
        - key: "eks.amazonaws.com/instance-category"
          operator: In
          values: ["c", "m", "r"]
```

通过指定仅限计算优化型、通用型和内存优化型类别，可以将加速型（P、G、Inf、Trn）和其他专用实例系列排除在选择范围之外。

### 实例选择如何与容量限制相互作用
<a name="_how_instance_selection_interacts_with_capacity_constraints"></a>

在正常的实例选择期间，EKS 自动模式会降低加速型实例类型和特殊实例类型的优先级。但在持续发生启动失败后，EKS 自动模式将从任何剩余的可用实例类型启动，以优先保证工作负载的可用性。例如，当所有首选实例类型的 EC2 服务配额暂时用完时，就会发生这种情况。

为避免这种回退行为，请在节点池要求中显式规定仅使用工作负载所需的实例类别。当首选类型不可用且您的节点池配置不允许使用其他类型时，容器组将保持在 `Pending` 状态，而不会调度高成本的实例。

### 限制实例大小
<a name="_constrain_instance_sizes"></a>

除限制实例系列外，您还可以限制节点池中的最大实例大小。通过限制实例大小，可以限制任何无法合并的单个节点的成本风险。例如，即使工作负载很小，被 `do-not-disrupt` 注释阻止的节点也无法缩减。

在节点池要求中使用 `eks.amazonaws.com/instance-cpu` 标签来限制最大实例大小：

```
requirements:
  - key: "eks.amazonaws.com/instance-cpu"
    operator: Lte
    values: ["32"]
```

此配置将会阻止 EKS 自动模式在此节点池中启动大于 32 个 vCPU 的实例。

要识别现有集群中的优化机会，请检查正在运行的最大实例。如果大型节点一直被阻止合并，则该空闲容量的每节点成本会相应更高。

## 适用于爆增性工作负载的推荐模式
<a name="_recommended_patterns_for_bursty_workloads"></a>

CI/CD 管道、批处理作业和临时运行器会建立“爆增然后空闲”模式，这种模式需要特定的配置才能保持成本效益。

### 适用于爆增性工作负载的推荐默认设置
<a name="_recommended_defaults_for_bursty_workloads"></a>


| 配置 | 建议 | 
| --- | --- | 
|  `do-not-disrupt`  | 不要使用 CI/CD 运行器。而应依赖 CI 系统的重试和排队机制。 | 
| 节点池 `limits`  | 根据预期最大并发量加上节点替换重叠所需缓冲区来设置 CPU/内存上限。 | 
| 实例类别 | 限定为 `c` 和 `m` 系列。为非 GPU 工作负载排除加速型实例系列（P、G、Inf、Trn）。 | 
| 实例大小 | 考虑限定使用中等实例大小（例如 4–32 个 vCPU），以限制任何被阻止合并的单个节点的成本风险。 | 
| 合并时效 | 使用默认的 `consolidateAfter` 设置。避免设置会在运行器完成后保持容量爆增的长延迟。 | 
| 容量类型 | 将竞价型实例实例用于容错型运行器。对于会在执行期间保持状态的生成代理，可与按需型实例合并。 | 

### 示例：CI 运行器节点池
<a name="_example_ci_runner_nodepool"></a>

```
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: ci-runners
spec:
  template:
    spec:
      nodeClassRef:
        group: eks.amazonaws.com
        kind: NodeClass
        name: default
      requirements:
        - key: "eks.amazonaws.com/instance-category"
          operator: In
          values: ["c", "m"]
        - key: "eks.amazonaws.com/instance-cpu"
          operator: Lte
          values: ["32"]
        - key: "karpenter.sh/capacity-type"
          operator: In
          values: ["spot", "on-demand"]
  limits:
    cpu: "500"
    memory: 1000Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 30s
```

此配置：
+ 限定使用高成本效益的实例系列
+ 节点池总容量上限为 500 个 vCPU
+ 允许激进合并（移除容器组后 30 秒合并）
+ 同时允许竞价型和按需型容量。

## 节点生命周期和成本
<a name="_node_lifecycle_and_cost"></a>

当节点偏离所需规范（例如，在新的自动模式 AMI 发布后）或节点生命周期接近到期时，EKS 自动模式会通过有序中断来替换节点。在有序替换期间：
+ 新的替换节点已启动并准备就绪。
+ 按照容器组中断预算将容器组从旧节点中耗尽。
+ 旧节点和替换节点会短时间同时运行。

对于具有大型节点或多个节点的集群，这种重叠可能会导致成本周期性增加。为了尽可能减少影响：
+  **检查中断预算**：确保您的中断预算能够及时耗尽节点。限制性预算会延长新旧节点运行的重叠期。
+  **合理调整实例大小**：使用较小的实例可以降低重叠期的绝对成本。
+  **缩短节点的最大生命周期**：使用较短的过期值（例如 7 天）可以更频繁地执行较小的替换。这可以确保随着时间推移更均匀地分摊成本，而不是集中产生成本。

有关节点生命周期的更多信息，请参阅[了解 Amazon EKS 自动模式的托管式实例](automode-learn-instances.md)。