このページでは、Google Kubernetes Engine(GKE)でプリエンプティブル VM を使用する方法について説明します。
概要
プリエンプティブル VM は、標準 VM よりも低価格で、可用性が保証されない Compute Engine VM インスタンスです。プリエンプティブル VM は、Spot VM と同様の機能を備えていますが、作成後 24 時間しか持続しません。
場合によっては、プリエンプティブル VM が 24 時間以上続くことがあります。これは、新しい Compute Engine インスタンスの起動が極度に高速であるため、別の Compute Engine VM が作成されたことを Kubernetes が認識できない場合に発生する可能性があります。基盤となる Compute Engine インスタンスの最大持続時間は 24 時間であり、想定されるプリエンプティブル VM の動作に従います。
Spot VM との比較
プリエンプティブル VM には、次のような Spot VM との多くの類似点があります。
- Compute Engine で標準 VM を実行するためにリソースが必要になると終了されます。
- ステートレス、バッチ、フォールト トレラントなワークロードの実行に適しています。
- 標準 VM よりも低価格です。
- GKE バージョン 1.20 以降を実行しているクラスタでは、グレースフル ノード シャットダウンがデフォルトで有効になっています。
- クラスタ オートスケーラーおよびノードの自動プロビジョニングと連動します。
最大有効期限がない Spot VM とは異なり、プリエンプティブル VM は作成後最大 24 時間しか持続しません。
新しいクラスタとノードプールでプリエンプティブル VM を有効にして、nodeSelector
またはノード アフィニティを使用してスケジューリングを制御できます。また、ノードがプリエンプトされたときのシステム ワークロードの問題を回避するために、taint と toleration を使用できます。
プリエンプティブル VM の終了と正常なシャットダウン
Compute Engine がプリエンプティブル VM によって使用されたリソースを再利用する必要がある場合、プリエンプション通知が GKE に送信されます。プリエンプティブル VM は、終了通知を受け取ってから 30 秒後に終了します。
デフォルトでは、クラスタはノードのグレースフル シャットダウンを使用します。kubelet は終了通知を認識し、ノードで実行中の Pod を正常に終了します。Pod が Deployment の一部である場合、コントローラは新しい Pod を作成してスケジューリングし、終了した Pod を置き換えます。
kubelet では、システム以外の Pod が正常に終了するためにベストエフォート方式で 15 秒の猶予が与えられます。その後、システム Pod(priorityClasses が system-cluster-critical
または system-node-critical
の Pod)が正常に終了するために 15 秒の猶予があります。
ノードの正常な終了中に、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
Kubernetes の動作の変更
GKE でプリエンプティブル VM を使用すると、Kubernetes によって提供される次のような保証と制約が変更されます。
Compute Engine からプリエンプション通知を受け取ってから 30 秒後に、GKE は Pod の猶予期間なしでプリエンプティブル VM をシャットダウンします。
プリエンプティブル VM の再利用は自発的なものではなく、
PodDisruptionBudgets
の保証の対象外です。構成したPodDisruptionBudget
以上に可用性が低くなる場合があります。
制限事項
- kubelet グレースフル ノード シャットダウン機能は、GKE バージョン 1.20 以降を実行しているクラスタでのみ有効になります。1.20 よりも前のバージョンの GKE では、Kubernetes on GCP Node Termination Event Handler を使用して、プリエンプティブル VM が終了されたときに、Pod を正常に終了できます。
- プリエンプティブル VM では、Windows Server ノードプールはサポートされていません。
プリエンプティブル 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 は、プリエンプティブル VM を使用するノードに、cloud.google.com/gke-preemptible=true
と cloud.google.com/gke-provisioning=preemptible
(GKE バージョン 1.25.5-gke.2500 以降を実行しているノードの場合)のラベルを追加します。Deployment で nodeSelector
を使用して、Pod をプリエンプティブル VM 上にスケジューリングするよう GKE に指示できます。
たとえば、次の 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 に Node Taints を使用する
プリエンプティブル VM を使用するノードを taint することで、対応する容認機能を備えた Pod のみが GKE によってそうしたノードに配置されるようにできます。
プリエンプティブル VM を使用するノードプールに Node Taint を追加するには、次のコマンドのように、ノードプール作成時に --node-taints
フラグを使用します。
gcloud container node-pools create POOL2_NAME \
--cluster=CLUSTER_NAME \
--node-taints=cloud.google.com/gke-preemptible="true":NoSchedule
これで、Node taint を許容する Pod だけが、このノードにスケジュールされるようになります。
関連する容認機能を Pod に追加するには、デプロイを変更して、次の記述を Pod 仕様に追加します。
tolerations:
- key: cloud.google.com/gke-preemptible
operator: Equal
value: "true"
effect: NoSchedule
GPU プリエンプティブル VM の Node Taints
プリエンプティブル VM では、GPU の使用がサポートされています。プリエンプティブル VM を使用する GPU ノードプールを追加する前に、クラスタには、プリエンプティブル VM を使用しない他のノードプールを 1 つ以上作成する必要があります。標準ノードプールがあることで、GKE は DNS などのシステム コンポーネントを安全に配置できます。
プリエンプティブル VM を使用する GPU ノードプールがある新しいクラスタを作成する場合、またはプリエンプティブル VM を使用する新しい GPU ノードプールを標準ノードプールがまだ備わっていないクラスタに追加する場合、GKE によって nvidia.com/gpu=present:NoSchedule
taint がノードに自動的に追加されることはありません。システム Pod が、GKE によってプリエンプティブル VM にスケジューリングされことはあります。この場合は、中断が発生する可能性があります。GPU ノードは、非 GPU ノードより高コストであるため、この動作によってリソースの消費も増加します。
次のステップ
- オンデマンド ノードをフォールバックとして Spot VM 上で GKE アプリケーションを実行する方法を確認する。
- GKE の Spot VM について確認する。
- taint と容認機能について確認する。