Spot 虚拟机


本页面介绍什么是 Spot 虚拟机及其在 Google Kubernetes Engine (GKE) 中的运作方式。如需了解如何使用 Spot 虚拟机,请参阅使用 Spot 虚拟机

GKE 中的 Spot 虚拟机概览

Spot 虚拟机是价格低于标准 Compute Engine 虚拟机的 Compute Engine 虚拟机 (VM) 实例。Spot 虚拟机提供与标准虚拟机相同的机器类型和选项,但不提供可用性保证。

您可以在集群和节点池中使用 Spot 虚拟机来运行无状态、批量或容错工作负载,这些工作负载可以容忍 Spot 虚拟机的临时性造成的中断。

Spot 虚拟机在 Compute Engine 需要标准虚拟机资源之前仍然可用。为了最大限度地提高成本效益,请结合使用 Spot 虚拟机与在 GKE 上运行费用经过优化的 Kubernetes 应用的最佳做法

如需详细了解 Spot 虚拟机,请参阅 Compute Engine 文档中的 Spot 虚拟机

Spot 虚拟机的优势

Spot 虚拟机和抢占式虚拟机具有诸多优势,具体如下所示:

与抢占式虚拟机(在 24 小时后过期)相比,Spot 虚拟机没有到期时间。Spot 虚拟机仅在 Compute Engine 在其他位置需要资源时终止。

Spot 虚拟机在 GKE 中的工作原理

当您创建具有 Spot 虚拟机的集群或节点池时,GKE 会创建类似于代管式实例组 (MIG) 的底层 Compute Engine Spot 虚拟机。使用 Spot 虚拟机的节点的行为类似于标准 GKE 节点,但不保证可用性。当需要使用 Spot 虚拟机所用的资源来运行标准虚拟机时,Compute Engine 会终止这些 Spot 虚拟机以在其他位置使用资源。

终止并正常关闭 Spot 虚拟机

当 Compute Engine 需要收回 Spot 虚拟机使用的资源时,系统会向 GKE 发送终止通知。Spot 虚拟机在收到终止通知 30 秒后终止。

在运行 GKE 1.20 及更高版本的集群上,kubelet 安全节点关停功能默认启用。Kubelet 会注意到终止通知,并正常终止节点上运行的 Pod。 如果 Pod 是 Deployment 的一部分,则控制器会创建并安排新 Pod,以替换已终止的 Pod。

Kubelet 为非系统 Pod 授予 25 秒时间进行安全终止,之后系统 Pod(具有 system-cluster-criticalsystem-node-critical 优先级类)将有 5 秒时间进行安全终止。

在安全 Pod 终止期间,kubelet 会为终止的 Pod 分配 Failed 状态和 Shutdown 原因。当终止的 Pod 数量达到 1000 时,垃圾回收将会清理 Pod。

您还可以使用以下命令手动删除关停 Pod:

kubectl get pods --all-namespaces | grep -i shutdown | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n

安排 Spot 虚拟机上的工作负载

GKE 会自动将 cloud.google.com/gke-spot=true 标签添加到使用 Spot 虚拟机的节点。您可以使用 Pod 规范中的 nodeSelector 字段,在使用 Spot 虚拟机的特定节点上调度特定的 Pod,如以下示例所示:

apiVersion: v1
kind: Pod
spec:
  nodeSelector:
    cloud.google.com/gke-spot: "true"

或者,您可以使用节点亲和性指示 GKE 在 Spot 虚拟机上调度 Pod,类似于以下示例:

apiVersion: v1
kind: Pod
spec:
...
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: cloud.google.com/gke-spot
            operator: In
            values:
            - true
...

您还可以使用 nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution 指示 GKE 将 Pod 放置在使用 Spot 虚拟机的节点上。不建议首选 Spot 虚拟机,因为 GKE 可能会将 Pod 调度到使用标准虚拟机的现有可行节点上。

使用污点和容忍进行安排

为避免系统中断,请使用节点污点来确保 GKE 不将关键工作负载调度到 Spot 虚拟机上。当您为使用 Spot 虚拟机的节点设置污点时,GKE 仅在这些节点上调度具有相应容忍的 Pod。

如果使用节点污点,请确保您的集群还至少有一个使用标准 Compute Engine 虚拟机的节点池。GKE 可以将使用标准虚拟机的节点池作为安全的位置来调度 DNS 等关键系统组件。

如需了解如何对 Spot 虚拟机使用节点污点,请参阅对 Spot 虚拟机使用污点和容忍

将 Spot 虚拟机与 GPU 节点池搭配使用

Spot 虚拟机支持使用 GPU。当您创建新的 GPU 节点池时,GKE 会自动向新节点添加 nvidia.com/gpu=present:NoSchedule 污点。只有具有相应容忍设置的 Pod 可以在这些节点上运行。GKE 会自动将此容忍设置添加到请求 GPU 的 Pod 上。

在创建使用 Spot 虚拟机的 GPU 节点池之前,您的集群必须至少具有一个使用标准虚拟机的非 GPU 节点池。如果您的集群只有一个使用 Spot 虚拟机的 GPU 节点池,则 GKE 不会向这些节点添加 nvidia.com/gpu=present:NoSchedule 污点。因此,GKE 可能会将系统工作负载调度到使用 Spot 虚拟机的 GPU 节点池上,这可能会导致 Spot 虚拟机中断,并且可能会增加资源消耗量,因为 GPU 节点比非 GPU 节点的成本更高。

集群自动扩缩器和节点自动预配

您可以使用集群自动扩缩程序节点自动预配功能来根据工作负载的需求自动扩缩集群和节点池。集群自动扩缩器和节点自动预配功能都支持使用 Spot 虚拟机。

Spot 虚拟机和节点自动预配

节点自动预配功能会自动在集群中创建和删除节点池,以满足工作负载的需求。当节点自动预配功能创建新的节点池以容纳需要 Spot 虚拟机的 Pod 时,GKE 会自动将 cloud.google.com/gke-spot=true:NoSchedule 污点添加到新节点池中的节点。只有具有相应容忍设置的 Pod 可以在这些节点池中的节点上运行。您必须为部署添加相应的容忍,以允许 GKE 将 Pod 放在 Spot 虚拟机上。

您可以确保 GKE 使用容忍设置以及用于过滤 Spot 虚拟机的 nodeSelector 或节点亲和性规则在 Spot 虚拟机上安排 Pod。

您还可以仅使用容忍设置,而不过滤使用 nodeSelector 或节点亲和性的 Spot 虚拟机。在这种情况下,GKE 会尝试在 Spot 虚拟机上调度 Pod。如果没有可用的 Spot 虚拟机,但已有具有容量的标准虚拟机,则 GKE 会将 Pod 调度到标准虚拟机上。

Spot 虚拟机和集群自动扩缩器

集群自动扩缩器会根据需求自动添加和移除节点池中的节点。如果您的集群具有无法放置在现有 Spot 虚拟机上的 Pod,则集群自动扩缩器会添加使用 Spot 虚拟机的新节点。

对 Kubernetes 行为的修改

在 GKE 上使用 Spot 虚拟机会修改 Kubernetes 提供的一些保证和限制条件,例如:

  • 在运行 1.20 版本之前的 GKE 的集群上,kubelet 的安全节点关停功能默认处于停用状态。GKE 会在收到 Compute Engine 的抢占通知 30 秒后为 Pod 关闭 Spot 虚拟机,不提供宽限期。

  • Spot 虚拟机的弃用是非自愿的,不在 PodDisruptionBudgets 的保证范围内。相对于已配置的 PodDisruptionBudget,遇到不可用情况的几率可能较大。

Spot 虚拟机的最佳做法

在设计使用 Spot 虚拟机的系统时,您可以使用以下准则以避免重大中断:

  • Spot 虚拟机无法保证可用性。在设计系统时,假设 GKE 可能会随时回收任何或所有 Spot 虚拟机,但无法保证新实例何时可用。
  • 无法保证在 Spot 虚拟机上运行的 Pod 可以正常关停。GKE 可能不会注意到,节点在执行回收操作之后需要几分钟时间才能完成回收,这会延迟将这些 Pod 重新调度到新节点上的操作。
  • 为了确保即使在没有 Spot 虚拟机可用的情况下系统也能处理您的工作负载和作业,请确保您的集群同时具有使用 Spot 虚拟机的节点池以及使用标准 Compute Engine 虚拟机的节点池。
  • 在添加使用 Spot 虚拟机的 GPU 节点池之前,请确保您的集群至少包含一个使用标准虚拟机的非 GPU 节点池。
  • 在运行 1.20 之前的 GKE 版本(其中 kubelet 安全节点关停功能已停用)的集群上使用 Kubernetes on GCP 节点终止事件处理脚本。当 Spot 虚拟机被抢占时,该处理脚本会正常终止您的 Pod。
  • 虽然节点名称在节点重新创建时通常不会发生变化,但 Spot 虚拟机使用的内部和外部 IP 地址可能会在重新创建后发生变化。
  • 使用节点污点和容忍机制来确保关键 Pod 不会被调度到使用 Spot 虚拟机的节点池上。
  • 不要将有状态 Pod 与 Spot 虚拟机搭配使用。StatefulSet 本身在每个索引中最多只能有一个 Pod 语义,这就导致抢占 Spot 虚拟机可能会违规,从而导致数据丢失。
  • 遵循 Kubernetes Pod 终止最佳实践

后续步骤