本頁說明如何在 Google Kubernetes Engine (GKE) 中使用可搶占 VM。
Spot VM 是最新版本的先占 VM。建議您改用Autopilot 叢集中的 Spot Pod,或Standard 叢集中的 Spot VM,不要使用先占 VM。GKE 會繼續支援先占 VM,這類 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 有許多相似之處,包括:
- 當 Compute Engine 需要資源來執行標準 VM 時,就會終止執行個體。
- 適用於執行無狀態、批次或容錯工作負載。
- 價格比標準 VM 低。
- 節點安全關機功能預設為啟用。不過,與 Spot 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 秒的值,不會有任何效果。先占通知發出後 30 秒,整個 VM 就會關機。
修改 Kubernetes 行為
在 GKE 上使用先占 VM 會修改 Kubernetes PodDisruptionBudgets 提供的保護措施。系統會強制回收可搶占 VM,且不適用 PodDisruptionBudgets 的保護措施。您可能會遇到比設定 PodDisruptionBudget 更高的無法使用率。
限制
- 先占 VM 不支援 Windows Server 節點集區。
- 使用先占 VM 時,您無法修改非系統 Pod 的 15 秒寬限期,以及系統 Pod 的後續 15 秒寬限期。底層的
shutdownGracePeriod和shutdownGracePeriodCriticalPodskubelet設定欄位無法變更。不過,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。
舉例來說,下列部署項目會使用 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 的節點設定 taint,這樣一來,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 節點更昂貴,因此這種行為也會增加資源消耗量。