GKEでプリエンティブルインスタンスを使う際の注意点をまとめる記事になります。
結論は以下となります。
- プリエンプティブにおいて、SIGTERMやpreStopを用いたGraceful Shutdownは行われていないっぽい。PodのRestartは0のままで、ただコンテナが再起動される。
- Cordon、Drainといったノードの削除のプロセスは行われない。Kuberentes的にはNodeが再起動したことも知らないのかもしれない。
マネージドKuberentesサービスとして、Googleが提供するGoogle Kubernetes Engine(以下GKE)があります。
この料金体系は、マスターノードは無料で利用でき、実際にコンテナのアプリケーションを実行するワーカーノードにのみGoogle Compute Engine(以下GCE)に基づく料金がかかるようになっています。
このGCEには、プリエンプティブルインスタンスという種類のインスタンスを選択することができ、GKEでも利用できるようになっています。
プリエンティブルインスタンスの特徴は以下のようになっています。
- 価格がおおよそ1/3に設定されている。
- 最大の起動時間が24時間で一度終了させられる。GKEでは再起動させられる。
- Googleに余剰キャパシティで起動されるいんすたんすのため、起動できない場合や途中で終了される場合がある。
おそらく、Googleの中でホスト内でCPU、Memoryの仕様の偏っているVMを、ホスト間で整理するのに使っているインスタンスなのだと思われます。
Kubernetesで通常、ノードの削除、追加を行う場合、以下のxrandr | grep -w connected | cut -d' ' -f1手順に則っています。
- NodeをCordonして、以後Podがスケジュールされないようにする。
- NodeをDrainして、起動中のPodを削除する。Deploymentなどを使っている場合、別のクラスタでそのPodがスケジュールされるようになり、Podを別のノードで移動させたようになる。
- NodeをDeleteする。
このPodの削除では、Podでは以下の手順が行われます。
- SIGTERMのシグナルが送られる。このシグナルを元に、Pod内のアプリケーションプロセスは終了の準備を行う必要がある。また、preStopフックが設定されている場合、SIGTERMのシグナルの代わりにこのコマンドが実行される。
- Podのプロセスが終了した場合、Podが削除される。
- GracePriod(初期設定は30秒)の経過後にプロセスが終了していない場合、SIGKILLのシグナルが送られ、強制的にプロセスが終了する。
このSIGTERMやpreStopを用いて、実行中のリクエストを捌き切ってから終了することを、Graceful Shutdownと呼びます。
よって、Kubernetes wayに則って、ノードの終了と、あたらいいノードへの移行を行うと考えると、NodeのCordon、Drainが行われ、PodはSIGTEMやpreStopを用いてGraceful Shutdownが行われることが期待される。
この通りの動作がプリエンティブルインスタンスで行われるかを調査した。
以下の機能をもつプログラムを作成した。
- 5秒ごとに現在時刻をログ出力する。ログ出力が途絶えた時間が、プロセスが終了した時間となる。
- SIGTERMを受け取るとログ出力する。SIGTERMが送られた時間を確認できる。
- 起動時にログ出力する。プロセスが起動した時間を確認できる。
GKEを以下のように構築した。
- プリエンプティブルのノードプールを作成し、ノードの数を2に設定した。2つのノードが作られる。
- プリエンプティブルでないノードプールを作成した。ノードの終了時にはこちらのノードプールにPodが退避されることを期待した。
このプログラムを実行するコンテナのPodのDeploymentを作成し、プリエンプティブルのノードプールで実行されていることを確認し、24時間経過してプリエンプティブルインスタンスのノードおよびPodがどのように動作するのかを、ログと、kubectlコマンドを使って確認した。
31時間経過後、kubectlでみた以下のような結果になった。
- NodeのAGEが31hになった(Deleteなどは行われていない様子)
- PodのAGEが31hになった(Drainなどは行われていない様子)
- PodのRestartは0のままだった
つまり、プリエンプティブの前後では、Nodeは同じノードとして扱われ、かつPodも同じPodとして扱われる。Podの再起動は、DeploymentによるPodの復元や、PodのRestartとは別におこなれていた。
Podのログは以下のようになっていた。
- SIGTERMが送られた形跡はなく、急にログが途絶えていた。
- 4分後、Podのプロセスが起動した。
つまり、現状プリエンプティブルインスタンスを用いたときの動作は以下のようになることがわかった。
- Podのプロセスが一時的に中断させられる。このときSIGTERMは送られず、Graceful Shutdownは行うことができない。
ということで、Graceful Shutdownを行うことはできないので、Dev環境など一時的な環境や、24時間以内に終了するバッチ処理でのみ使うようにしましょう。