使用先占 VM 執行容錯工作負載

本頁面說明如何在 Google Kubernetes Engine (GKE) 中使用先占 VM。

最佳做法:

Spot VM 是最新版本的先占 VM。建議您改用 Autopilot 叢集中的 Spot Pod,或 Standard 叢集中的 Spot VM,而非先占 VM。GKE 仍支援先占 VM,其定價模式與 Spot VM 相同。

總覽

先占 VM 是 Compute Engine VM 執行個體,價格低於標準 VM,但不保證可用性。先占 VM 的功能與 Spot VM 類似,但建立後最多只能運作 24 小時。

在某些情況下,先占 VM 的運作時間可能會超過 24 小時。如果新的 Compute Engine 執行個體啟動速度過快,且 Kubernetes 無法辨識已建立不同的 Compute Engine VM,就可能發生這種情況。基礎 Compute Engine 執行個體的持續時間最長為 24 小時,並遵循預期的先占 VM 行為。

與 Spot VM 比較

先占 VM 與 Spot VM 有許多相似之處,包括:

與沒有到期時間上限的 Spot VM 不同,先占 VM 在建立後最多只能保留 24 小時。

您可以在新的叢集和節點集區啟用先占 VM、使用 nodeSelector 或節點相似度控管排程,以及使用污點和容許設定,避免節點遭先占時系統工作負載發生問題。

終止及正常關機先占 VM

當 Compute Engine 需要回收先占 VM 使用的資源時,會向 GKE 傳送先占通知。先占 VM 會在收到終止通知 30 秒後終止。

根據預設,叢集會使用安全關閉節點功能。kubelet 會注意到終止通知,並正常終止在節點上執行的 Pod。如果 Pod 屬於 Deployment 等代管工作負載,控制器會建立並排定新的 Pod,取代終止的 Pod。

kubelet 會盡可能為非系統 Pod 提供 15 秒的正常終止時間,之後系統 Pod (具有 system-cluster-critical 或 system-node-critical priorityClasses) 會有 15 秒的時間正常終止。在正常終止節點期間,kubelet 會更新 Pod 的狀態,並為終止的 Pod 指派 Failed 階段和 Terminated 原因。

非系統 Pod 的正常終止期限最長為 15 秒。在 Pod 資訊清單的 terminationGracePeriodSeconds 欄位中指定大於 15 秒的值不會有任何效果。收到先占通知後,整個 VM 會在 30 秒內關機。

修改 Kubernetes 行為

在 GKE 上使用先占 VM 會修改 Kubernetes PodDisruptionBudgets 提供的保護措施。先占 VM 的回收作業並非自願,不受 PodDisruptionBudgets 保護。服務無法使用的時間可能會超過設定的 PodDisruptionBudget。

限制

  • 先占 VM 不支援 Windows Server 節點集區。
  • 使用先占 VM 時,您無法修改非系統 Pod 的 15 秒寬限期,以及系統 Pod 的後續 15 秒寬限期。基礎 shutdownGracePeriod 和 shutdownGracePeriodCriticalPods kubelet 設定欄位無法變更。不過,Spot VM 支援修改這些設定。詳情請參閱「終止及正常關機 Spot VM」。

建立含有先占 VM 的叢集或節點集區

您可以使用 Google Cloud CLI,建立含有先占 VM 的叢集或節點集區。

如要建立具有先占 VM 的叢集,請執行下列指令:

gcloud container clusters create CLUSTER_NAME \
    --preemptible

將 CLUSTER_NAME 替換為新叢集的名稱。

如要建立含有先占 VM 的節點集區,請執行下列指令:

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

將 POOL_NAME 替換為新節點集區的名稱。

使用 nodeSelector 在先占 VM 上排定 Pod

GKE 會將 cloud.google.com/gke-preemptible=true 和 cloud.google.com/gke-provisioning=preemptible 標籤新增至使用先占 VM 的節點。您可以在部署作業中使用 nodeSelector,指示 GKE 將 Pod 排定至先占 VM。

舉例來說,下列 Deployment 會使用 cloud.google.com/gke-preemptible 標籤篩選先占 VM:

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-preemptible: "true"

對先占 VM 使用節點污點

您可以對使用先占 VM 的節點設定污點,這樣 GKE 就只能將具有對應容許條件的 Pod 放在這些節點上。

如要為使用先占 VM 的節點集區新增節點污點,請在建立節點集區時使用 --node-taints 旗標,類似於下列指令:

gcloud container node-pools create POOL2_NAME \
    --cluster=CLUSTER_NAME \
    --node-taints=cloud.google.com/gke-preemptible="true":NoSchedule

現在,只有可容忍節點 Taint 的 Pod 會排程到節點。

如要為 Pod 新增相關容許規定,請修改 Deployment,並在 Pod 規格中加入下列內容:

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

GPU 先占 VM 的節點污點

先占 VM 支援使用 GPU。在叢集中新增使用先占 VM 的 GPU 節點集區之前,請先建立至少一個不使用先占 VM 的其他節點集區。有了標準節點集區,GKE 就能安全地放置 DNS 等系統元件。

如果您建立的新叢集含有使用先占 VM 的 GPU 節點集區,或是在尚未具備標準節點集區的叢集中,新增使用先占 VM 的 GPU 節點集區,GKE 不會自動將 nvidia.com/gpu=present:NoSchedule 污點新增至節點。GKE 可能會將系統 Pod 排定至先占 VM,這可能會導致中斷。由於 GPU 節點比非 GPU 節點昂貴,這種行為也會增加資源消耗量。

後續步驟