ComputeClass 方面的最佳实践

平台工程师可以使用自定义 ComputeClasses 以声明方式配置 节点设置和后备优先级,供 Google Kubernetes Engine (GKE) 在 自动扩缩期间用于创建节点。您可以根据特定策略和工作负载要求创建 ComputeClass。本文档提供了在集群中设计和实现 ComputeClass 的最佳实践。您应当已熟悉 自定义 ComputeClass。 如需查看所有 GKE 最佳实践的汇总概览,请参阅 GKE 最佳实践

ComputeClass 设计

以下部分提供了在集群中设计和实现 ComputeClass 的最佳实践,这些实践基于最大程度提高可获取性和性能等目标。ComputeClass 可与手动创建的节点池和自动创建的节点池搭配使用。

根据策略设计每个 ComputeClass

设计每个 ComputeClass,以满足工作负载、团队或组织的特定目标。利用 ComputeClass 的后备行为以及选择手动创建的节点池和自动创建的节点池的能力,优先考虑某些结果,例如减少手动开销或提高调度性能。 以下部分介绍了常见策略。

提高可获取性并减少手动开销

如需将节点池创建委托给 GKE,请仅在 ComputeClass 中使用自动创建的节点池。自动扩缩器会根据硬件可用性、Pod 资源要求和可用区容量配置节点。此策略无需手动创建和调整节点池,并可以减少与闲置、未使用的节点容量相关的费用。

提高调度性能并微调节点

如需微调优先级最高的节点并减少调度延迟时间,请在 ComputeClass 中混合使用手动创建的节点池和自动创建的节点池。这种混合策略可减少 Pod 等待 GKE 创建新节点池的频率。由于优先级最高的节点池是手动创建的,因此您可以微调硬件以满足 Pod 的确切要求。

混合策略按优先级顺序在 ComputeClass 中包含以下类型的节点池:

  1. 手动创建的节点池:这些节点池具有您希望大多数 Pod 在其上运行的确切 规范。使用特定节点标签、节点污点、容量预留或特殊配置(例如 kubelet 参数)配置这些节点池。创建这些节点池时,请使用您估计 Pod 需要的尽可能多的节点。在 ComputeClass 中,为这些节点池分配最高优先级。
  2. 自动创建的节点池:作为后备措施,使用 ComputeClass 请求仍针对 Pod 进行了优化的其他节点池。为这些自动创建的节点池分配比手动创建的节点池更低的优先级。

以下示例 ComputeClass 使用了这种混合策略:

apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
  name: hybrid-class
spec:
  nodePoolAutoCreation:
    enabled: true
  priorities:
  - nodepools: ['manual-pool1']
  - machineFamily: n4
    minCores: 16
    minMemoryGb: 64
  whenUnsatisfiable: DoNotScaleUp

当您部署使用此 ComputeClass 的工作负载时,GKE 会将 Pod 放置在 manual-pool1 中的可用节点上。仅当手动创建的节点池没有可用容量时,GKE 才会创建新的节点池。 当手动创建的节点池中现有节点的数量增加时,调度延迟时间会缩短,因为 GKE 不需要频繁创建新节点。

明确定义最后的伸缩行为

whenUnsatisfiable 字段用于控制在 GKE 无法满足 ComputeClass 中任何优先级规则的要求时会发生什么情况。为避免版本升级后出现意外行为,请在每个 ComputeClass 中明确为此字段指定一个值。设置值有助于 ComputeClass 用户了解在工作负载中选择该 ComputeClass 时会发生什么情况。此字段的建议值取决于工作负载的类型,如下所示:

  • 通用工作负载:如果您的工作负载可以在任何机器 系列上运行,请指定值 ScaleUpAnyway。如果与 ComputeClass 中的优先级规则匹配的节点不可用,GKE 会扩容使用集群默认机器系列的节点。
  • 需要专用硬件的工作负载:对于依赖于特定硬件(例如 GPU 或某些 Compute Engine 机器系列)的加速器或高性能计算工作负载,请指定值 DoNotScaleUp。如果与 ComputeClass 中的优先级规则匹配的节点不可用,则 Pod 会一直处于 Pending 状态,直到资源可用为止。这种方法可防止 Pod 在不兼容的硬件上运行。

如需了解详情,请参阅定义未应用优先级规则 时的伸缩行为

为大多数工作负载设置集群级默认 ComputeClass

如果大多数工作负载具有相同的硬件要求,请为集群配置 默认 ComputeClass。GKE 会将默认 ComputeClass 应用于未明确选择 ComputeClass 的任何工作负载。通过设置默认 ComputeClass,应用运维人员无需更改节点选择器或在各个 Pod 中手动请求特定节点池和硬件。如果您设置了集群级默认 ComputeClass,请勿为集群中的现有节点池添加其他 ComputeClass 的节点标签和污点。在为集群级默认 ComputeClass 进行调度期间,GKE 会忽略具有其他 ComputeClass 的节点标签或节点污点的任何节点池。

为命名空间设置默认 ComputeClass 以分隔租户

除了集群级默认 ComputeClass 之外,您还可以设置默认 ComputeClass 用于特定命名空间。如果您有多租户环境,或者想要分隔在专用硬件上运行的工作负载,请为这些命名空间配置默认 ComputeClass。为防止系统 Pod 在 GPU 节点等专用硬件上运行,请添加通用 ComputeClass 作为系统命名空间的默认 ComputeClass。

在 Autopilot 模式下运行低交互工作负载

如果您有不需要手动交互或管理的工作负载,请使用 ComputeClass 在 Autopilot 模式下运行这些工作负载。即使您有 Standard 集群,也可以在任何 ComputeClass 中启用 Autopilot 模式。GKE 会在全代管式节点上运行选择 Autopilot ComputeClass 的工作负载,这些节点实现了 GKE Autopilot 的安全、伸缩和结算功能。如需了解详情,请参阅 Autopilot 模式 GKE Standard 中的工作负载

有状态工作负载

以下部分提供了最佳实践,以减少依赖于持久性数据的有状态工作负载中的中断或意外行为。

停用主动迁移

主动迁移会自动将 Pod 移至 ComputeClass 中优先级较高或有能力运行未调度的 DaemonSet Pod 的新节点。在主动迁移期间,GKE 会终止现有节点上的 Pod,并在优先级较高的节点上创建新 Pod。如果您有依赖于本地持久性存储空间中的数据的工作负载,将 Pod 移至新节点可能会导致中断,因为 Pod 会失去对持久性数据的访问权限。为避免此问题,请为用于有状态工作负载的 ComputeClass 停用主动迁移。

使用 StorageClass 提高调度可靠性

使用 StorageClass 可通过以下方式提高有状态工作负载的调度可靠性:

  • 仅在创建 Pod 后创建卷:如果您使用动态卷 预配,请在 StorageClass 的 volumeBindingModeWaitForFirstConsumer字段中指定值。此卷绑定模式可防止在 GKE 创建使用相应 PersistentVolumeClaim 的 Pod 之前创建 PersistentVolume。 GKE 会在运行 Pod 的节点所在的同一可用区中预配 PersistentVolume。
  • 使用拓扑感知型 StorageClass:如果您的 ComputeClass 跨越多个 机器系列(例如 C4 和 C3),请使用启用了自动磁盘类型选择的 StorageClass,并且仅在支持您指定的磁盘类型的节点上进行调度。您可以使用内置的 dynamic-rwo StorageClass 或自定义 StorageClass。这样,您的有状态工作负载就可以在多个 Compute Engine 实例代系上运行,因为集群自动扩缩器会动态选择兼容的磁盘类型。

可获取性

以下部分提供了有关如何提高 ComputeClass 可获取性的最佳实践,以便 Pod 在 Pending 状态下花费的时间更少。

请求机器系列,而不是机器类型

您可以在 ComputeClass 优先级规则中请求 Compute Engine 机器系列或特定机器类型。除非您严格依赖于特定机器类型,否则请使用 machineFamily field 选择机器系列。在伸缩操作期间,GKE 可以创建使用该机器系列中任何可行机器类型的节点,这提高了 Pod 在您最偏好的节点配置上运行的可能性。

为需求量大的硬件使用容量预留

如果您的工作负载依赖于需求量大的硬件(例如 TPU 或高性能 GPU),请为硬件创建 Compute Engine 容量预留,并在 ComputeClass 中使用这些预留。容量预留提高了硬件在您的区域或可用区中可用的可能性,这有助于您提高资源可获取性。如需在 ComputeClass 中使用预留而不影响后备行为,请使用 SpecificAnyThenFail 预留亲和性。如果您使用 AnyBestEffortAutomatic 亲和性,并且没有可用的预留容量,则 Compute Engine 可能会绕过 ComputeClass 优先级规则,并回退到按需硬件。如需了解详情,请参阅使用预留的可用区级 资源

至少一小时内不使用新的预留

集群自动扩缩器会将有关容量预留的信息存储在缓存中。当您创建新的容量预留时,自动扩缩器可能需要长达一小时的时间才能发现该预留。创建预留后,请至少等待一小时,然后再在工作负载中使用该预留。如果您在自动扩缩器将预留存储在缓存中之前部署了使用该预留的工作负载,则自动扩缩操作可能会失败。

安全

以下部分提供了有关如何提高集群中 ComputeClass 安全性的最佳实践。这些措施非常重要,因为 ComputeClass 可用于创建和配置使用昂贵或存货有限的硬件的节点。有意或无意的误用可能会导致工作负载中断、计划外的资源使用费以及配额耗尽。

限制对 ComputeClass 配置的 API 访问权限

工作负载可以使用 ComputeClass 创建运行专用硬件(包括 GPU 和 TPU)的节点。将创建、修改和删除 ComputeClass 的访问权限限制为与可以在集群中创建、修改和删除节点的同一正文。如需控制对 ComputeClass 的访问权限,请使用 RBAC 政策

按命名空间限制 ComputeClass 可用性

GKE 客户通常按 Kubernetes 命名空间分隔不同的团队或工作负载类型。ComputeClass 是一种集群级资源,这意味着默认情况下,任何命名空间中的任何工作负载都可以选择任何 ComputeClass。为避免有意或无意的滥用,请使用 ValidatingAdmissionPolicies 控制每个命名空间中的工作负载可以选择的 ComputeClass 集。例如,您可以阻止 Web 前端命名空间中的 Pod 选择创建加速器的 ComputeClass。验证您的 ValidatingAdmissionPolicies 是否检查以下常见配置:

  • 检查所有选择字段 :工作负载可以使用 Pod 规范中的 nodeSelectornodeAffinitytolerations 字段选择 ComputeClass。为避免意外选择 ComputeClass,请在 ValidatingAdmissionPolicy 表达式中检查所有这些字段。
  • 检查通配符容忍绕过 :明确阻止或验证通配符容忍(例如,没有键的 operator: Exists 容忍)。这些通配符选择器可以涵盖大多数节点污点,包括 ComputeClass 污点。
  • 检查所有工作负载控制器:配置政策的 matchConstraints以涵盖所有工作负载控制器资源(例如 DeploymentStatefulSetDaemonSetJobCronJob)。请勿将 检查范围限定为仅Pod资源。

如需了解详情,请参阅限制修改和选择 ComputeClass的访问权限。

可靠性

以下部分提供了有关如何提高 ComputeClass 的自动扩缩和 Pod 迁移可靠性的最佳实践,这降低了中断或 Pod 卡住的风险。

防止使用冲突的节点选择器

Pod 中的节点选择器会影响 GKE 放置这些 Pod 的位置,并且在 Autopilot 模式下或使用节点池自动创建时,可能会触发在集群中创建新节点池。如果您有选择 ComputeClass 的 Pod,并使用节点选择器请求与 ComputeClass 配置冲突的节点,则 GKE 可能根本不会调度这些 Pod。

例如,假设有一个 ComputeClass 仅请求按需实例。如果 Pod 选择该 ComputeClass 并在节点选择器中选择 Spot 虚拟机,则 GKE 无法调度该 Pod,因为 ComputeClass 和节点选择器相互冲突。为避免此问题,请使用 ValidatingAdmissionPolicies 等方法来防止选择 ComputeClass 的 Pod 同时选择系统节点标签。如需了解详情,请参阅 用于系统节点标签的节点选择器

测试对主动迁移和自动扩缩设置的所有更改

ComputeClass 中的主动迁移和自动扩缩设置直接影响 GKE 终止 Pod 的频率,以执行将 Pod 移至更偏好的硬件和整合未充分利用的节点等任务。 对现有 ComputeClass 中的这些设置进行修改可能会导致意外的工作负载中断。在对现有 ComputeClass 中的这些设置应用任何修改之前,请在预演环境中测试这些更改。 您还可以使用注解来保护关键工作负载在 伸缩期间免遭逐出。

在集群升级之前测试 ComputeClass CRD 更新

GKE 会定期更新 ComputeClass CustomResourceDefinition (CRD),以添加字段、修改字段行为和修复问题。字段添加和修改通常会在特定的 GKE 版本中生效。在将生产集群升级到新的次要版本或补丁版本之前,请按照以下准则检查对 CRD 的更改是否会导致工作负载问题:

使用 PodDisruptionBudgets 提高工作负载可用性

导致 Pod 逐出的 ComputeClass 操作(例如主动迁移) 会遵循任何已配置的 PodDisruptionBudgets。例如,您可以将推理 Deployment 配置为具有 PodDisruptionBudget,该预算要求超过 70% 的 Pod 可用。在主动迁移期间,如果 Pod 逐出违反了该预算,则 GKE 不会逐出该 Pod。 为以下工作负载指定 PodDisruptionBudgets:

  • 无状态工作负载,例如推理 Deployment。
  • 复制的有状态工作负载,例如高可用性数据库应用。

请勿依赖 PodDisruptionBudgets 来保护需要运行完成、只有一个实例或依赖于本地持久性数据的工作负载。指定一个预算,该预算在工作负载可用性之间取得平衡,并允许升级等功能完成。

保护关键工作负载免遭逐出

如果您有工作负载,其中每个 Pod 都必须运行完成才能被 终止,请将 cluster-autoscaler.kubernetes.io/safe-to-evict: "false" 注解添加到 Pod 规范中。此注解可防止 GKE 在自动扩缩操作期间逐出 Pod。使用此注解来保护无法容忍中断的 Pod,例如单实例有状态工作负载和长时间运行的批处理作业。

最佳实践摘要

本文档提供了以下 ComputeClass 最佳实践:

后续步骤