この記事を読んだ内容を備忘がてらまとめます。
Graceful Node Shutdown とは?
Graceful Shutdownとは「通常のShutdownと比べて丁寧に停止する機能のこと」を一般的に指します。たとえばWebサーバでGraceful Shutdownが実装されている場合は受け付けているリクエストをきちんと終了してからプロセスを停止します。
このようにDBや処理の状態を都合の良い形で終了させるために使われる機能ですが、これをKubernetes上のPodに対しても適用しようというのが元々の背景です。
ペットから家畜へと言う形でインスタンスやVMを管理する流れとなってきましたが、いまだにKubernetesではNodeを停止する前にDrainやCordonを実施しないとNode上で稼働するPodを安全に退避させることはできません。毎回そのフローをきちんと回せればよいのですが、意図しないところでNodeを停止してしまうことが往々にしてあります。
Graceful Node Shutdownを設定するとOSの停止命令が来たタイミングで一定時間の猶予をKubernetes側で管理することで、いきなりNodeを停止するのではなくPodが退避される時間を管理してその後にNodeを停止する機能です。
ここで誤解してはいけないのはNode上で稼働しているPodに対して、Podの特性に応じた終了処理を行うことは責務ではないということです。それはこれまで通り各アプリケーションのシグナルハンドリングやPreStop機能の世界の話です。
あくまでGraceful Node ShutdownはNodeが停止する前にそれらの機能が動くための時間稼ぎをする機能にほかなりません。
通常PodとクリティカルPodの話
2021/07/12現在β版なので将来どのように変化するかはわかりませんが、現在はGraceful Node Shutdownの機能としてはPodに対して2つの区分を設けています。
- Regular Pod
- Critical Pod
静的なHTMLだけを返すNginxのPodと、そのアクセスログを管理するログ転送用のFluentdのPodがあるとしましょう。このときPodの停止順序を考えると、すべてのアクセスログを転送したいのでNginx Podが停止してからFluentd Podを停止したいです。
通常のk8sの機能ではこれを実現する方法はありません。(preStop hookで自分でコードを書けばいけるけどね)
そこで使えるのが2つの区分です。Graceful Node Shutdownの動作ではまず最初にRegular Podが一斉に退避されます、続いて一定時間経過後にCritical Podが退避されます。この機構によってある程度の順番をコントロールできるようになるわけです。
ShutdownGracePeriod
: Nodeがダウンするまでの猶予期間ShutdownGracePeriodCriticalPods
: Critical Podを退避させる猶予時間(ShutdownGracePeriodより小さくする必要あり)
ShutdownGracePeriod
が30秒、ShutdownGracePeriodCriticalPods
が10秒で設定されていた場合は、まず最初にRegular Podが20秒で退避され残りの10秒でCritical Podが退避されその後Nodeが停止します。
なおこの設定はkubelet
にて設定するものになります。
Critical Podに設定する方法
priorityClassNameをsystem-cluster-critical
またはsystem-node-critical
にすることでCriticalとして扱われます。ちなみにsystem-node-critical
のほうがよりクリティカルな設定ですが、いま時点のGraceful Node Shutdownの仕組みにおいては差がないようです。