运行抢占式虚拟机


本页面简要介绍了 Google Kubernetes Engine (GKE) 对抢占式虚拟机 (VM) 的支持。

概览

抢占式虚拟机是 Compute Engine 虚拟机实例,通常最多可存在 24 小时,并且不提供任何可用性保证。抢占式虚拟机的价格低于标准 Compute Engine 虚拟机,并提供相同的机器类型和选项。

您可以在 GKE 集群或节点池中使用抢占式虚拟机来运行对抢占式虚拟机的临时性、无保证性不太敏感的批处理或容错作业。

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

抢占式虚拟机的工作原理

当 GKE 集群或节点池创建 Compute Engine 虚拟机时,这些虚拟机的行为类似于托管实例组。GKE 中的抢占式虚拟机受到与托管实例组中的抢占式实例相同的限制。抢占式实例在收到抢占通知 30 秒后终止。

此外,这些抢占式虚拟机还被赋予了 Kubernetes 标签 cloud.google.com/gke-preemptible=true。Kubernetes 标签在 nodeSelector 字段中可用于将 Pod 调度到特定节点

以下是过滤抢占式虚拟机的示例选择器:

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

Kubernetes 抢占式节点

在运行 1.20 或更高版本的抢占式 GKE 节点上,默认情况下会启用 kubelet 安全关停节点功能。因此,kubelet 会检测抢占,并安全终止 Pod。

系统会尽最大努力为用户 Pod 提供 25 秒的宽限期(通过 terminationGracePeriodSeconds 请求),然后将为系统 Pod(具有 system-cluster-criticalsystem-node-critical 的 Pod)留出 5 秒钟的时间,供其安全终止。

对于抢占式节点上的 Pod,请勿为 terminationGracePeriodSeconds 指定超过 25 秒的时间,因为这些 Pod 在抢占期间仅接收 25 秒。

突破 Kubernetes 限制

在 GKE 上使用抢占式虚拟机会使一些 Kubernetes 保证失效。抢占式虚拟机会修改以下限制:

  • 节点抢占会关闭 Pod,而不会另行通知,并且如果未启用安全关停节点功能(在 1.20 之前未启用),则会忽略已配置的 Pod 宽限期
  • 根据 Pod 中断预算文档,“预算只能防范自愿退出,不能防范导致不可用的所有原因。”抢占并不是自愿的,因此实际的不可用性可能会高于 Pod 中断预算中指定的不可用性。

最佳做法

由于抢占式虚拟机没有可用性保证,因此您在设计系统时,应该假设任何或所有 Compute Engine 实例可能都会被抢占并变得不可用。无法保证新实例何时可用。

此外,无法保证在抢占式虚拟机上运行的 Pod 可以始终正常关停。GKE 可能需要几分钟时间才能检测到节点已被抢占并且 Pod 不再运行,这会延迟将 Pod 重新调度到新节点。

如果要确保即使抢占式虚拟机不可用,也能处理作业或工作负载,则可以在集群中创建非抢占式和抢占式节点池。

尽管节点名称在抢占后被替换时通常保持不变,但内部和外部抢占式虚拟机 IP 地址可能会在抢占后更改。

请勿将抢占式虚拟机与有状态 Pod 搭配使用,因为它们可能会违反 StatefulSet 固有的最多一项语义,并可能导致数据丢失。

使用节点污点来避免调度到抢占式虚拟机节点

为避免系统中断,请使用节点污点来确保关键 Pod 不会被调度到抢占式虚拟机节点上。

如果您应用了节点污点,请确保您的集群还具有不可抢占的无污点节点,这样您就始终可以使用节点池中的标准虚拟机来运行 DNS 等系统组件。

污染抢占式虚拟机的节点

如需为具有抢占式虚拟机的节点添加节点污点,请运行以下命令:

kubectl taint nodes node-name cloud.google.com/gke-preemptible="true":NoSchedule

其中,node-name 是节点的名称。

现在,只有能容忍节点污点的 Pod 才会被调度到该节点。

向 Pod 添加容错

如需向 Pod 添加相关容错,请将以下内容添加到 Pod 的规范或对象的 Pod 模板规范中:

tolerations:
- key: cloud.google.com/gke-preemptible
  operator: Equal
  value: "true"
  effect: NoSchedule

GPU 抢占式节点污点

在添加抢占式 GPU 节点池之前,您应该先创建具有非抢占式节点的集群。这样可以确保在添加抢占式 GPU 节点池之前,始终有标准虚拟机的节点池可用来运行 DNS 等系统组件。

在集群中添加具有 GPU 的抢占式节点池时,如果集群中没有其他节点池(包括最初创建具有一个抢占式 GPU 节点池的集群情况),则系统不会分配常规 "nvidia.com/gpu":NoSchedule 污点。这意味着系统 Pod 将调度到抢占式节点上,这些节点在被抢占时可能会中断。这些 Pod 还会消耗 GPU 节点上的资源。这样不仅会浪费容量,而且会浪费资金,因为 GPU 节点比非 GPU 节点昂贵。

创建具有抢占式虚拟机的集群或节点池

您可以使用 gcloud 命令行工具或 Cloud Console 创建具有抢占式虚拟机的集群或节点池。

gcloud

您可以通过指定 --preemptible 标志来创建具有抢占式虚拟机的集群或节点池。

如需创建具有抢占式虚拟机的集群,请运行以下命令:

gcloud container clusters create cluster-name --preemptible

其中,cluster-name 是要创建的集群的名称。

如需创建具有抢占式虚拟机的节点池,请运行以下命令:

gcloud container node-pools create pool-name --preemptible \
    --cluster cluster-name

其中:

  • pool-name 是要创建的节点池的名称。
  • cluster-name 是节点池的集群的名称。

控制台

  1. 转到 Cloud Console 中的 Google Kubernetes Engine 页面:

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 根据需要配置集群。

  4. 在导航窗格的节点池下方,对于您要配置的节点池,请点击节点

  5. 选中启用抢占式节点复选框。

  6. 点击创建

后续步骤