koukiblog

たぶんweb系の話題

KubernetesでPodが終了するときのフロー

ここにかいてあることの個人的なまとめ cloud.google.com

まとめ

アプリケーションはSIGTERMで正常に終了する必要がある

終了フロー

1. PodをTerminating状態にして、Serviceのendpointから削除する

まず、PodはTerminating状態になり、Serviceのendpointから削除されます。コンテナは稼働し続けたまま、新しいトラフィックは入ってこなくなる。

2. preStop Hookの実行

preStop Hookが実行される。外部のアプリケーションを実行しているときなど、SIGTERMで正しく終了出来ない場合はこちらを使う。

3. PodにSIGTERMシグナルの送信

PodにSIGTERMが送信される。k8sは、SIGTERMシグナルで、アプリケーションが正常に終了することを期待している。ここでいう正常終了とは、graceful shutdownのことで、SIGTERMで処理中のプロセスを停止させてしまう場合、処理が途中で打ち切られてしまう可能性が常に発生してしまいます。

4. grace periodを待つ

kubernetesは、2, 3の経過にかかわらず、定められたgrace periodの間、コンテナの停止を待っている。grace periodのデフォルトは30秒で、Pod毎に変更することが可能。

PodのspecにterminationGracePeriodSeconds を指定する

5. SIGKILLを送信し、Podを削除

grace periodの間待ってもコンテナが停止しない場合、SIGKILを送信して強制的に停止させる。そのあと、Podを削除する

まだよくわからないこと

https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods 上記ページの記載だと、1のServiceからの削除と、2,3のPod停止処理が同時に行われると書いてある。

つまり、SIGTERMシグナルが送信されたあとに新しいトラフィックが流れる可能性があるが、それはk8sの仕様ということ。ときどき、prestopでsleepしてる対応を見かけるのだが、これが現実的に起きうる頻度なのかが不明。

SIGTERM受け取ったら新しいリクエストは処理しないのが正常なように思えるし、だからといって全てのPodのprestopにsleep仕込んでいくのも違和感があります。。