プリエンプティブル VM の実行


このページでは、Google Kubernetes Engine(GKE)でのプリエンプティブル仮想マシン(VM)のサポートの概要を説明します。

概要

プリエンプティブル VM は、最長持続時間が 24 時間(通常の場合)であり、可用性が保証されない Compute Engine VM インスタンスです。プリエンプティブル VM は標準的な Compute Engine VM よりも低価格であり、同じマシンタイプとオプションが用意されています。

プリエンプティブル VM は、GKE クラスタやノードプールでバッチジョブやフォールト トレラントなジョブを実行するのに使用できます。これらのジョブは、エフェメラルで可用性が保証されないプリエンプティブル VM の性質にそれほど影響されないためです。

プリエンプティブル VM について詳しくは、Compute Engine ドキュメントのプリエンプティブル VM をご覧ください。

プリエンプティブル VM の仕組み

GKE クラスタまたはノードプールによって Compute Engine VM が作成されると、それらの VM はマネージド インスタンス グループのように動作します。GKE のプリエンプティブル VM には、マネージド インスタンス グループ内のプリエンプティブル インスタンスと同じ制約が適用されます。プリエンプティブル インスタンスは、プリエンプション通知を受け取ってから 30 秒後に終了します。

さらに、これらのプリエンプティブル VM には Kubernetes ラベル cloud.google.com/gke-preemptible=true が付けられます。Kubernetes ラベルを nodeSelector フィールドで使用することで、Pod を特定のノードにスケジュールできます。

プリエンプティブル VM をフィルタリングするセレクタの例を次に示します。

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-critical または system-node-critical のもの)が正常に終了するために 5 秒の猶予が与えられます。

プリエンプティブル ノード上の Pod では、terminationGracePeriodSeconds に 25 秒を超える値を指定しないでください。これらの Pod は、プリエンプション中に 25 秒間しか与えられないためです。

プリエンプティブル ノードのシャットダウン中に kubelet が Pod を終了すると、Failed ステータスと Shutdown の理由が Pod に割り当てられます。これらの Pod は、次回のガベージ コレクションでクリーンアップされます。次のコマンドを使用して、シャットダウンされる Pod を手動で削除することもできます。

kubectl get pods --all-namespaces | grep -i shutdown | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n

Kubernetes 制約違反

GKE でプリエンプティブル VM を使用すると、一部の Kubernetes 保証が無効になります。次の制約がプリエンプティブル VM によって変更されます。

  • ノード プリエンプションは、通知なしに Pod をシャットダウンし、ノードのグレースフル シャットダウンが有効になっていない場合は、構成された Pod の猶予期間は無視されます(1.20 より前)。
  • Pod 停止予算のドキュメントでは「予算の保護は任意の強制排除のみを対象としており、利用できない状況のすべての原因を対象としていない」と記述されています。プリエンプションは任意ではありません。したがって、Pod の停止予算で指定されている使用不能状態よりも大規模な使用不能状態が発生することがあります。

ベスト プラクティス

プリエンプティブル VM では可用性が保証されないため、Compute Engine インスタンスのいずれかまたはすべてがプリエンプトされて使用できなくなる可能性があることを想定してシステムを設計する必要があります。新しいインスタンスがいつ使用可能になるかは保証されません。

さらに、プリエンプティブル VM 上で動作する Pod が常に正常にシャットダウンできるという保証はありません。ノードがプリエンプトされていることと、Pod が実行されていないことを GKE が検出するまでに数分間かかることがあります。これが原因で、新しいノードへの Pod のスケジュール変更が遅延します。

プリエンプティブル VM が使用できないときでもジョブまたはワークロードを確実に処理したい場合は、クラスタ内に非プリエンプティブル ノードプールとプリエンプティブル ノードプールの両方を作成できます。

プリエンプションの後でノードが置換される場合、ノード名は通常変更されませんが、内部と外部のプリエンプティブル VM IP はプリエンプションの時点で変更されることがあります。

プリエンプティブル VM は、StatefulSet 固有の at-most-one セマンティクスに違反し、データ損失の原因となる可能性があるので、ステートフル Pod ではプリエンプティブル VM を使用しないでください。

Node taint を使用してプリエンプティブル VM ノードへのスケジューリングを回避する

システムの中断を回避するには、Node taint を使用して、重要な Pod がプリエンプティブル VM ノードでスケジュールされないようにします。

Node taint を適用する場合は、DNS などのシステム コンポーネントを実行する標準 VM のノードプールが常に存在するように、クラスタにプリエンプティブル以外の taint が追加されていないノードも含まれるようにします。

プリエンプティブル VM が含まれるノード用に Node taint を追加する

プリエンプティブル VM が含まれるノードに対する Node taint を追加するには、次のコマンドを実行します。

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

ここで、node-name はノードの名前です。

これで、Node taint を許容する Pod だけが、このノードにスケジュールされるようになります。

容認機能を Pod に追加する

関連する容認機能を Pod に追加するには、次の要素を Pod の仕様またはオブジェクトの Pod テンプレート仕様に追加します。

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

GPU プリエンプティブル ノード taint

プリエンプティブル GPU ノードプールを追加する前に、非プリエンプティブル ノードを含むクラスタを作成する必要があります。これにより、プリエンプティブル GPU ノードプールを追加する前の時点で、DNS などのシステム コンポーネントを実行するための標準 VM からなるノードプールが常に存在するようになります。

GPU を含むプリエンプティブル ノードプールがクラスタに追加されるとき(クラスタがプリエンプティブル GPU ノードプールを使用して初めて作成される場合を含む)に、クラスタに他のノードプールがない場合には、通常の nvidia.com/gpu=present:NoSchedule taint が割り当てられません。つまり、プリエンプト時点で停止される可能性のあるプリエンプティブル ノード上で、システム Pod がスケジュールされます。これらの Pod は、GPU ノードのリソースも消費します。GPU ノードは非 GPU ノードよりも高コストであるため、キャパシティだけでなく予算も無駄に消費されることになります。

プリエンプティブル VM を含むクラスタまたはノードプールを作成する

プリエンプティブル VM を含むクラスタまたはノードプールを作成するには、gcloud コマンドライン ツールまたは Cloud Console を使用できます。

gcloud

プリエンプティブル VM を含むクラスタまたはノードプールを作成するには、--preemptible フラグを指定します。

プリエンプティブル VM を含むクラスタを作成するには、次のコマンドを実行します。

gcloud container clusters create cluster-name --preemptible

ここで、cluster-name は作成するクラスタの名前です。

プリエンプティブル VM を持つノードプールを作成するには、次のコマンドを実行します。

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

ここで

  • pool-name は、作成するノードプールの名前です。
  • cluster-name は、ノードプールのクラスタの名前です。

Console

  1. Cloud Console で Google Kubernetes Engine ページに移動します。

    Google Kubernetes Engine に移動

  2. [ 作成] をクリックします。

  3. 必要に応じてクラスタを構成します。

  4. ナビゲーション パネルの [ノードプール] で、構成するノードプールの [ノード] をクリックします。

  5. [プリエンプティブル ノードを有効にする] チェックボックスをオンにします。

  6. [作成] をクリックします。

次のステップ