このページでは、Google Kubernetes Engine(GKE)でプリエンプティブル VM を使用する方法について説明します。
概要
プリエンプティブル VM は、最長持続時間が 24 時間で、可用性が保証されない 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 秒後に終了します。
GKE バージョン 1.20 以降を実行しているクラスタでは、kubelet グレースフル ノード シャットダウン機能がデフォルトで有効になります。kubelet は終了通知を認識し、ノードで実行中の Pod を正常に終了します。Pod が Deployment の一部である場合、コントローラは新しい Pod を作成してスケジュールを設定し、終了した Pod を置き換えます。
kubelet ではベストエフォート方式で、システム以外の Pod が正常に終了するために 25 秒の猶予が与えられます。その後、システム Pod(優先順位が system-cluster-critical
または system-node-critical
のもの)が正常に終了するために 5 秒の猶予があります。
Pod が正常に終了している間、kubelet が Failed
ステータスと Shutdown
理由を終了する Pod に割り当てます。終了した Pod 数がしきい値に達すると、ガベージ コレクションによって Pod がクリーンアップされます。
シャットダウン Pod を手動で削除することもできます。使用するコマンドは、GKE クラスタが実行されているバージョンによって異なります。
1.21.3-gke.1200 以降
停止している 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
以前のバージョン
停止している Pod を手動で削除します。
kubectl get pods --all-namespaces | grep -i shutdown | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n
Kubernetes の動作の変更
GKE でプリエンプティブル VM を使用すると、Kubernetes によって提供される次のような保証と制約が変更されます。
1.20 よりも前のバージョンの GKE を実行しているクラスタでは、kubelet グレースフル ノード シャットダウ機能がデフォルトで無効になっています。Compute Engine からプリエンプション通知を受け取ってから 30 秒後に、GKE は Pod の猶予期間なしでプリエンプティブル VM をシャットダウンします。
プリエンプティブル VM の再利用は自発的なものではなく、
PodDisruptionBudgets
の保証の対象外です。構成したPodDisruptionBudget
以上に可用性が低くなる場合があります。
制限事項
- kubelet の正常なノード シャットダウン機能は、GKE バージョン 1.20 以降を実行しているクラスタでのみ有効になります。1.20 よりも前のバージョンの GKE では、GCP 上の Kubernetes ノード終了イベント ハンドラを使用して、プリエンプティブル 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
ノードラベルを追加します。Deployment で nodeSelector
を使用して、Pod をプリエンプティブル VM 上にスケジューリングするよう GKE に指示できます。
たとえば、次の Deployment では、プリエンプティブル 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 にノード taints を使用する
プリエンプティブル VM を使用するノードを taint することで、対応する容認機能を備えた Pod のみが GKE によってそうしたノードに配置されるようにできます。
プリエンプティブル VM を使用するノードプールにノード taint を追加するには、次のコマンドのように、ノードプール作成時に --node-taints
フラグを使用します。
gcloud container node-pools create POOL2_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 のノード 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 ノードより高コストであるため、この動作によってリソースの消費も増加します。