TT Lab
はじめる
学ぶ 学習パス コース

CKAD — Kubernetesアプリケーション開発者

終了猶予も時間予算 — preStopとTERMの間

TT Labで続きを見る

一言でいうと

preStopは、終了猶予の外にあるボーナスの時間ではありません。終了対象のPodのフックと、アプリケーションのシグナル処理、残りの作業時間を、一緒に設計する必要があります。

なぜ必要なのか

readinessを付けて、preStopで少し待ったから絶対に安全だ、と考えがちです。しかし、フックのあとでプロセスがすぐに終了すれば、すでに受けたリクエストは切れることがあり、プロセスがリクエストを待っても、終了猶予が先に尽きれば終えられません。「設定を入れた」ことと「望む結果が出た」ことのあいだを埋めるのが、今回のラボの目的です。

設定がどのPodに入っているかも重要です。Deploymentテンプレートに新しく追加したpreStopは、そのテンプレートで生成されるPodの設定です。今まさに入れ替えられて落ちていく古いPodに、遡って入ったものと解釈すると、実験の比較が間違います。削除の直前に、対象PodのUIDとspec.containersのlifecycleを読んで、保存する必要があります。新しいテンプレートだけをキャプチャしたレポートは、実際に何が実行されたのかを教えてくれません。

どう動くのか

一般的なTERMによる終了の流れでは、kubeletがpreStopフックを実行し、フックが終わったあとで、コンテナのプロセスに終了シグナルを送ります。終了猶予の計算は、フックが実行される前に始まるので、フックとそれ以降の後始末を、同じバジェットの中に入れる必要があります。フックが3秒を使ったなら、その3秒がアプリケーションに別枠で加算されるわけではありません。むやみに長いsleepを入れる方法は、新しいリクエストの除外に時間を与えられますが、終了バジェットも消費します。

ここで、時間の合算を間違えることもあります。すでに開始したHTTPの作業は、フックが実行されている間も進むことがあります。したがって、全体の作業時間が10秒でフックが3秒だからといって、常に13秒の残りの作業があるわけではありません。設計するときは、フックの実行時間と、TERMのあとに実際に残る処理・後始末の時間の上限を考え、観測するときは、受け付け・削除・フック・TERM・完了の時刻を別々に残します。作業の上限がなければ、猶予を大きく増やすだけでは、安全な終了を保証できません。

今回のサーバーのgracefulモードは、TERMを受けると新しいworkリクエストを拒否し、activeが0になるまで待ってから終了します。immediateモードは、比較のために、終了コード17で即座に終わります。コード17自体が、Kubernetesの標準の終了の意味というわけではありません。ラボのサーバーが意図的に選んだ観測の目印です。正常な完了では、レスポンスの本文を最後まで送り、終了コード0を観測します。

gracefulでも、猶予が足りなければ、コンテナが強制的に終了されることがあります。今回、事前に実施した実際のVMでの検証では、猶予が足りないとき137を観測しました。しかし、現場で137だけを見て、終了猶予のせいだと断定しないでください。OOMのような他の原因も調査する必要があります。Pod watchの終了の理由、実際の猶予の設定、シグナルの前後の時刻、リクエストの結果を一緒に結び付けることが核心です。

現場での姿

kubectl deleteを実行した壁時計の時刻と、kubeletが終了の処理を始めた時刻は、正確には同じではありません。API処理、観測の伝達、ランタイムの作業にも遅延があります。そのため、「猶予が5秒だから、削除コマンドのあと正確に5秒で接続が切れるはずだ」という採点は、正常な環境でも間違えることがあります。今回のラボは、小数点以下の秒を当てさせるのではなく、受け付けられた同じリクエストの結果と終了状態を検査します。

採点の時点でPodをもう一度照会するだけでも不十分です。すでに削除されたPodはなく、終了したコンテナもランタイムから回収されている可能性があります。検証プログラムの最初の実装では、終了のあとに確認しようとして、根拠を失いました。そこで、リクエストを送る前にPod watchを開始し、最終的なコンテナの状態とDELETEDイベントを保存します。観測ファイルを読む再採点は、Podを再作成しません。同じ実験をこっそりもう一度実行すると、以前の結果を検査したことにならないからです。

次のラボですること

正常な終了の設定で猶予を減らしてリクエストを切ってみたあと、再び猶予を補って、同じ長さの作業が完了するかを確認します。理論を読んで予想した結果と、実際の観測を比較しますが、特定の1回のレスポンスを、すべての本番トラフィックの無停止の保証に拡大しないでください。リクエストの失敗のあとに自動の再試行を付けるときは、前の単元のJobの冪等性のように、業務の副作用も考慮する必要があります。

公式ドキュメント: コンテナのライフサイクルフック、Podの終了の流れ。