使用 Spot 虚拟机以更低的费用运行容错工作负载


本页面介绍如何在 Google Kubernetes Engine (GKE) 集群和节点池中使用 Spot 虚拟机,以更低的费用运行容错、无状态或批处理工作负载。

概览

Spot 虚拟机是 Compute Engine 虚拟机,其价格低于标准虚拟机。Spot 虚拟机提供与标准 Compute Engine 虚拟机相同的机器类型和选项,但不保证可用性。Compute Engine 可以根据系统事件(例如标准虚拟机需要资源时)随时回收 Spot 虚拟机。

如需详细了解 GKE 中的 Spot 虚拟机,请参阅 Spot 虚拟机

Spot 虚拟机可以代替抢占式虚拟机来运行无状态、批量或容错工作负载。与抢占式虚拟机(在 24 小时后过期)相比,Spot 虚拟机没有到期时间。当 Compute Engine 需要资源运行标准虚拟机时,Spot 虚拟机会终止。

采用 Spot Pod预览版)的 GKE Autopilot 集群也支持 Spot 虚拟机。使用 Spot Pod 时,Autopilot 会自动安排和管理 Spot 虚拟机上的工作负载。

限制

准备工作

在开始之前,请确保您已执行以下任务:

  • 确保您已启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 确保您已安装 Google Cloud CLI
  • 使用以下某种方法为您的项目设置默认 Google Cloud CLI 设置:
    • 使用 gcloud init(如果您想要在系统引导下完成项目默认设置)。
    • 使用 gcloud config(如果您想要单独设置项目 ID、可用区和区域。

    gcloud init

    1. 运行 gcloud init 并按照说明操作:

      gcloud init

      如果您要在远程服务器上使用 SSH,请使用 --console-only 标志来防止命令启动浏览器:

      gcloud init --console-only
    2. 按照说明授权 gcloud CLI 使用您的 Google Cloud 帐号。
    3. 创建新配置或选择现有配置。
    4. 选择 Google Cloud 项目。
    5. 选择默认的 Compute Engine 可用区
    6. 选择默认的 Compute Engine 区域

    gcloud config

    1. 设置默认项目 ID
      gcloud config set project PROJECT_ID
    2. 设置默认的 Compute Engine 区域(例如 us-central1):
      gcloud config set compute/region COMPUTE_REGION
    3. 设置默认的 Compute Engine 可用区(例如 us-central1-c):
      gcloud config set compute/zone COMPUTE_ZONE
    4. gcloud 更新到最新版本:
      gcloud components update

    通过设置默认位置,您可以避免 gcloud CLI 中出现以下错误:One of [--zone, --region] must be supplied: Please specify location

创建启用了 Spot 虚拟机的集群

您可以使用 Google Cloud CLI 或 Google Cloud Console 在新集群上启用 Spot 虚拟机。

gcloud

如需在新集群上启用 Spot 虚拟机,请运行以下命令:

gcloud container clusters create CLUSTER_NAME \
    --spot

CLUSTER_NAME 替换为新集群的名称。

此命令会在默认节点池中创建启用 Spot 虚拟机的新集群。

控制台

如需在新集群上启用 Spot 虚拟机,请执行以下步骤:

  1. 进入控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 创建集群对话框中,点击 GKE 标准旁边的配置

  4. 在导航菜单的节点池部分中,点击要配置的节点池的名称,然后点击节点

  5. 选中启用 Spot 虚拟机复选框。

  6. 根据需要配置集群,然后点击创建

创建启用了 Spot 虚拟机的节点池

您可以使用 gcloud CLI 或控制台在新节点池上启用 Spot 虚拟机。您只能在新节点池上启用 Spot 虚拟机。您无法在现有节点池上启用或停用 Spot 虚拟机。

gcloud

如需创建启用了 Spot 虚拟机的新节点池,请运行以下命令:

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --spot

POOL_NAME 替换为新节点池的名称。

控制台

如需创建启用 Spot 虚拟机的新节点池,请执行以下步骤:

  1. 进入控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要修改的集群的名称。

  3. 点击添加节点池

  4. 在导航菜单中,点击节点

  5. 选中启用 Spot 虚拟机复选框。

  6. 根据需要配置节点池,然后点击创建

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

GKE 会将 cloud.google.com/gke-spot=true 标签添加到使用 Spot 虚拟机的节点。您可以使用 Pod 规范中的 nodeSelector 字段或节点亲和性在 Pod 规范中过滤出此标签。

在以下示例中,您将创建一个包含两个节点池的集群,其中一个节点池使用 Spot 虚拟机。然后,您可以将无状态 nginx 应用部署到 Spot 虚拟机上,并使用 nodeSelector 控制 GKE 放置 Pod 的位置。

  1. 创建新集群:

    gcloud container clusters create CLUSTER_NAME
    

    CLUSTER_NAME 替换为新集群的名称。

  2. 获取集群的凭据:

    gcloud container clusters get-credentials CLUSTER_NAME
    
  3. 创建启用了 Spot 虚拟机的节点池:

    gcloud beta container node-pools create POOL_NAME \
        --spot
    

    POOL_NAME 替换为新节点池的名称。

  4. 将以下 Deployment 清单保存为名为 hello-app.yaml 的文件:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-app
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: hello-app
      template:
        metadata:
          labels:
            app: hello-app
        spec:
          containers:
          - name: hello-app
            image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
            resources:
              requests:
                cpu: 200m
          nodeSelector:
            cloud.google.com/gke-spot: "true"
    

    在此清单中,nodeSelector 字段指示 GKE 仅在使用 Spot 虚拟机的节点上调度 Pod。

  5. 将清单应用到您的集群:

    kubectl apply -f hello-app.yaml
    
  6. 获取集群中的节点列表:

    kubectl get nodes
    
  7. 检查使用 Spot 虚拟机的节点池中的一个节点:

    kubectl describe node NODE_NAME
    

    输出内容类似如下:

    Name:               gke-spot-cluster-spot-pool-a4a9f3ee-6l6w
    Roles:              <none>
    Labels:             beta.kubernetes.io/arch=amd64
                        beta.kubernetes.io/instance-type=e2-medium
                        beta.kubernetes.io/os=linux
                        cloud.google.com/gke-boot-disk=pd-standard
                        cloud.google.com/gke-container-runtime=containerd
                        cloud.google.com/gke-nodepool=default-pool
                        cloud.google.com/gke-os-distribution=cos
                        cloud.google.com/gke-spot=true
                        cloud.google.com/machine-family=e2
                        failure-domain.beta.kubernetes.io/region=us-central1
                        failure-domain.beta.kubernetes.io/zone=us-central1-a
                        kubernetes.io/arch=amd64
                        kubernetes.io/hostname=gke-spot-cluster-spot-pool-a4a9f3ee-6l6w
                        kubernetes.io/os=linux
                        node.kubernetes.io/instance-type=e2-medium
                        topology.gke.io/zone=us-central1-a
                        topology.kubernetes.io/region=us-central1
                        topology.kubernetes.io/zone=us-central1-a
    ...
    Non-terminated Pods:          (5 in total)
      Namespace                   Name                                                         CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
      ---------                   ----                                                         ------------  ----------  ---------------  -------------  ---
      default                     hello-app-654b446b9c-c7rq8                                   0 (0%)        0 (0%)      0 (0%)           0 (0%)         20h
      kube-system                 fluentbit-gke-d27d6                                          100m (10%)    0 (0%)      200Mi (7%)       500Mi (17%)    21h
      kube-system                 gke-metrics-agent-p7t4x                                      3m (0%)       0 (0%)      50Mi (1%)        50Mi (1%)      21h
      kube-system                 kube-proxy-gke-preempt-cluster-default-pool-a4a9f3ee-6l6w    100m (10%)    0 (0%)      0 (0%)           0 (0%)         4d22h
      kube-system                 pdcsi-node-m84bt                                             0 (0%)        0 (0%)      20Mi (0%)        100Mi (3%)     21h
    ...
    Events:                      <none>
    

    GKE 仅在使用 Spot 虚拟机的节点上调度您的 Pod。

对 Spot 虚拟机使用污点和容忍

最佳做法是让创建的集群中存在至少一个没有 Spot 虚拟机的节点池。您还可以使用节点污点和相应的容忍设置来指示 GKE 避免将 DNS 等系统工作负载放置在使用 Spot 虚拟机的节点上。

  1. 如需向使用 Spot 虚拟机的节点池添加节点污点,请在创建节点池时使用 --node-taints 标志,类似于以下命令:

    gcloud container node-pools create POOL_NAME \
        --node-taints=cloud.google.com/gke-spot="true":NoSchedule
    
  2. 如需向 Pod 添加对应的容忍,请修改部署并将以下内容添加到 Pod 规范中:

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

    GKE 仅将具有容忍设置的 Pod 调度到污点节点上。

后续步骤