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仕込んでいくのも違和感があります。。