このページでは、Spot VM の概要と Google Kubernetes Engine(GKE)での動作について説明します。Spot VM の使用方法については、Spot VM の使用に関する記事をご覧ください。
GKE における Spot VM の概要
Spot VM は標準的な Compute Engine VM より料金が低く、可用性が保証されない Compute Engine 仮想マシン(VM)インスタンスです。Spot VM は、標準 VM と同じマシンタイプとオプションを提供します。
クラスタとノードプールで Spot VM を使用して、Spot VM の一時的な性質による中断を許容できるステートレス、バッチ、またはフォールト トレラントのワークロードを実行できます。
Spot VM は、Compute Engine で標準 VM 用のリソースが必要になるまで、引き続き使用できます。費用効率を最大限に高めるには、Spot VM を、コストが最適化された Kubernetes アプリケーションを GKE で実行するためのベスト プラクティスと組み合わせて使用します。
Spot VM の詳細については、Compute Engine ドキュメントの Spot VM をご覧ください。
Spot VM の利点
Spot VM とプリエンプティブル VM には、次のような多くの利点があります。
- 標準的な Compute Engine VM より低価格です。
- これらの VM のエフェメラル(一時的)という特徴に耐性があるステートレス ワークロードとフォールト トレラント ワークロードに適しています。
- クラスタ オートスケーラーおよびノードの自動プロビジョニングと連動します。
プリエンプティブル VM は 24 時間後に期限切れになりますが、Spot VM には有効期限がありません。Spot VM は、Compute Engine が別の場所でリソースを必要とする場合にのみ終了します。
GKE における Spot VM の仕組み
Spot VM を含むクラスタまたはノードプールを作成する際に、GKE は、基盤となる Compute Engine Spot VM を作成します。これは、マネージド インスタンス グループ(MIG)のように動作します。Spot VM を使用するノードは、標準の GKE ノードのように動作しますが、可用性は保証されません。標準 VM を実行するために Spot VM で使用されているリソースが要求された場合、Spot VM は終了し、それらのリソースは別の場所で使用されます。
Spot VM の終了と正常なシャットダウン
Compute Engine が Spot VM で使用されるリソースを再利用する必要がある場合、終了通知が GKE に送信されます。Spot VM は、終了通知を受け取ってから 30 秒後に終了します。
GKE バージョン 1.20 以降を実行しているクラスタでは、kubelet グレースフル ノード シャットダウン機能がデフォルトで有効になります。kubelet は終了通知を認識し、ノードで実行中の Pod を正常に終了します。Pod が Deployment の一部である場合、コントローラは新しい Pod を作成してスケジューリングし、終了した Pod を置き換えます。
ベスト エフォート方式で、ノードプールの GKE バージョンに基づいて、kubelet は次の正常終了期間を付与します。
- 1.22.8-gke.200 より後: システム以外の Pod の場合は 15 秒。その後、(優先度が
system-cluster-critical
またはsystem-node-critical
の)システム Pod が正常に終了するまでに 15 秒かかります。 - 1.22.8-gke.200 以前: システム以外の Pod の場合は 25 秒。その後、(優先度が
system-cluster-critical
またはsystem-node-critical
の)システム Pod が正常に終了するまでに 5 秒かかります。
グレースフル ノードの終了中に、kubelet が Pod のステータスを更新し、終了する Pod に Failed
フェーズと Terminated
の理由を割り当てます。
終了した Pod 数が、100 ノード未満のクラスタの場合は 1,000、100 ノード以上のクラスタの場合は 5,000 のしきい値に達すると、ガベージ コレクションによって Pod がクリーンアップされます。
次のコマンドを使用して、終了した Pod を手動で削除することもできます。
kubectl get pods --all-namespaces | grep -i NodeShutdown | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n
kubectl get pods --all-namespaces | grep -i Terminated | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n
Spot VM でのワークロードのスケジューリング
GKE は、Spot VM を使用するノードに、cloud.google.com/gke-spot=true
と cloud.google.com/gke-provisioning=spot
(GKE バージョン 1.25.5-gke.2500 以降を実行しているノードの場合)の両方のラベルを自動的に追加します。Pod 仕様の nodeSelector フィールドを使用して、Spot VM を使用するノードで特定の Pod をスケジューリングできます。次の例では、cloud.google.com/gke-spot
ラベルを使用しています。
apiVersion: v1
kind: Pod
spec:
nodeSelector:
cloud.google.com/gke-spot: "true"
または、次の例のようにノード アフィニティを使用して、GKE に Spot VM 上の Pod をスケジューリングするよう指示することもできます。
apiVersion: v1
kind: Pod
spec:
...
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: cloud.google.com/gke-spot
operator: In
values:
- "true"
...
また、nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution
を使用して、Spot VM を使用するノードに GKE が Pod を配置するようにすることもできます。GKE は標準の VM を使用する既存の実行可能なノードに Pod をスケジューリングできるため、Spot VM を優先することはおすすめしません。
スケジューリングに taint と容認機能を使用する
システムの中断を回避するには、Node taint を使用して、GKE が重要なワークロードを Spot VM でスケジューリングしないようにします。Spot VM を使用するノードに taint を追加する際、GKE は、それらのノードで対応する toleration を持つ Pod のみをスケジューリングします。
Node taint を使用する場合は、クラスタに標準の Compute Engine VM を使用するノードプールも少なくとも 1 つ含まれるようにしてください。標準の VM を使用するノードプールは、GKE が DNS などの重要なシステム コンポーネントをスケジューリングするための信頼できる場所を提供します。
Spot VM に Node taint を使用する方法については、Spot VM に taint と toleration を使用するをご覧ください。
GPU ノードプールで Spot VM を使用する
Spot VM は GPU の使用に対応しています。新しい GPU ノードプールを作成する際は、GKE により、nvidia.com/gpu=present:NoSchedule
taint が新しいノードに自動的に追加されます。対応する容認機能を備えた Pod のみが、これらのノードで実行できます。GKE は、GPU をリクエストする Pod にこの toleration を自動的に追加します。
Spot VM を使用する GPU ノードプールを作成する前に、標準の VM を使用する既存の非 GPU ノードプールが、少なくとも 1 つクラスタに存在する必要があります。クラスタに Spot VM を持つ GPU ノードプールしかない場合、GKE はそれらのノードに nvidia.com/gpu=present:NoSchedule
taint を追加しません。その結果、GKE によって、システム ワークロードが Spot VM を持つ GPU ノードプールでスケジューリングされる場合があります。これにより、Spot VM が原因で中断が発生する可能性と、GPU ノードが非 GPU ノードより高コストであるためにリソース消費が増加する可能性があります。
クラスタ オートスケーラーとノードの自動プロビジョニング
クラスタ オートスケーラーとノード自動プロビジョニングを使用すると、ワークロードの需要に基づいてクラスタとノードプールを自動的にスケーリングできます。クラスタ オートスケーラーとノード自動プロビジョニングの両方で Spot VM の使用がサポートされています。
Spot VM とノードの自動プロビジョニング
ノードの自動プロビジョニングでは、ワークロードの需要を満たすために、クラスタ内のノードプールが自動的に作成および削除されます。nodeSelector
またはノード アフィニティを使用して Spot VM を必要とするワークロードをスケジューリングすると、ノードの自動プロビジョニングにより、ワークロードの Pod に対応する新しいノードプールが作成されます。GKE は、新しいノードプール内のノードに cloud.google.com/gke-spot=true:NoSchedule
taint を自動的に追加します。対応する toleration を備えた Pod のみが、これらのノードプール内のノードで実行できます。GKE が Pod を Spot VM に配置できるように、対応する toleration を Deployment に追加する必要があります。
tolerations:
- key: cloud.google.com/gke-spot
operator: Equal
value: "true"
effect: NoSchedule
toleration と nodeSelector
またはノード アフィニティ ルールの両方を使用して Spot VM 用にフィルタリングすることで、GKE が Spot VM 上の Pod のみをスケジューリングするようにできます。
toleration のみを使用してワークロードをスケジューリングする場合、GKE は Spot VM または容量のある既存の標準 VM に Pod をスケジューリングできます。Spot VM でワークロードをスケジューリングする必要がある場合は、toleration に加えて nodeSelector
またはノード アフィニティを使用します。詳細については、Spot VM でのワークロードのスケジューリングをご覧ください。
Spot VM とクラスタ オートスケーラー
クラスタ オートスケーラーは、需要に基づいて、ノードプール内のノードを自動的に追加または削除します。既存の Spot VM に配置できない Pod がクラスタにある場合、クラスタ オートスケーラーは Spot VM を使用する新しいノードを追加します。
デフォルト ポリシー
GKE バージョン 1.24.1-gke.800 以降では、オートスケーラーのロケーション ポリシーを定義できます。クラスタ オートスケーラーは、リソースが利用可能で、デフォルトのロケーション ポリシーが ANY
に設定されている場合に、Spot VM ノードプールのプロビジョニングを試みます。このポリシーを使用すると、Spot VM がプリエンプトされるリスクが低くなります。その他の VM タイプの場合、デフォルトのクラスタ オートスケーラー配布ポリシーは BALANCED
です。
Spot VM を使用して Standard ノードプールをアップグレードする
Spot VM を使用する Standard クラスタのノードプールがサージ アップグレードを使用するように構成されている場合、GKE は Spot VM を使用してサージノードを作成します。ただし、Spot VM では可用性が保証されないため、GKE は、Spot VM の準備が完了するのを待たずに既存のノードの閉鎖とドレインを行います。詳細については、サージ アップグレードをご覧ください。
Kubernetes の動作の変更
GKE で Spot VM を使用すると、Kubernetes によって提供される次のような保証と制約が変更されます。
- Spot VM の再利用は自発的なものではなく、
PodDisruptionBudgets
の保証の対象外です。構成したPodDisruptionBudget
以上に可用性が低くなる場合があります。
Spot VM のベスト プラクティス
Spot VM を使用するシステムを設計する際は、次のガイドラインを使用することで大規模な中断を回避できます。
- Spot VM では可用性が保証されません。システムの設計は、GKE が任意の Spot VM またはすべての Spot VM をいつでも再利用できるが、新しいインスタンスが利用可能になる保証はないという前提で行ってください。
- Spot VM が使用できないときでもワークロードと Job が確実に処理されるように、標準の Compute Engine VM を使用するノードプールと Spot VM を使用するノードプールがクラスタに混在するようにします。
- Spot VM を使用する GPU ノードプールを追加する前に、クラスタに標準の VM を使用する非 GPU ノードプールが少なくとも 1 つあることを確認します。
- ノードが再作成されてもノード名は通常は変更されませんが、Spot VM が使用する内部 IP アドレスと外部 IP アドレスは、再作成後に変更される可能性があります。
- Node taint と toleration を使用して、Spot VM を使用するノードプールに重要な Pod がスケジューリングされないようにします。
- Spot VM でステートフル ワークロードを実行するには、シャットダウンから 25 秒以内にワークロードを正常に終了できることを確認して、永続ボリューム データの破損のリスクを最小限にします。
- Kubernetes Pod 終了のベスト プラクティスに従います。
次のステップ
- ノードプールで Spot VM を使用する方法を学習する。
- クラスタの自動スケーリングを理解する。
- デプロイされたアプリのスケーリング方法を学習する。
- Compute Engine ドキュメントで Spot VM の詳細を学習する。
- GKE で Spot VM を使用してバッチ ワークロードをデプロイするチュートリアルを実施する。