KubernetesでRollingUpdateするためのPodの安全な終了

◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【5/21開催】Azure OpenAI ServiceによるRAG実装ガイドを公開しました
生成AIを活用したユースケースで最も一番熱いと言われているRAGの実装ガイドを公開しました。そのガイドの紹介をおこなうイベントです!!
https://tech-lab.connpass.com/event/315703/

あけましておめでとうございます、サイオステクノロジー技術部 武井です。本日は元旦です。今年最初のブログは、KubernetesでRollingUpdateするためにPodを安全に終了するために必要な設定を書きます。

Pod終了までのシーケンス

Podが終了するためのシーケンスは以下のようになります。

  1. kubetctlが、Podを終了するためのリクエストをAPI Serverに送信する。
  2. kubeletが、Pod終了のリクエストをAPI Server経由で受け取り、Podの終了処理を開始する。
  3. 「サービスからPodを除外する処理」と「preStop(オプション)+SIGTERMをPodに送信する」という2つの処理を同時に開始する。これらの処理は完全に非同期で行われる
  4. 事前に定義したterminationGracePeriodSeconds秒以内に3の処理が終わらなかった場合、PodにSIGKILLが送信されて、強制的に終了される。

Apacheで安全に停止する場合

これらの特性を考えて、RollingUpdateするためにApacheをgracefulに停止する方法(ユーザーのリクエストを途中で切断することなく安全に停止する)を考えてみます。

まず、先の3で説明したように最終的にはSIGTERMが送信されますが、ApacheはSIGTERMを受け取ると、https://httpsd.apache.org/docs/2.4/en/stopping.htmlに以下に記載されているとおり、ユーザーがリクエストを送受信している途中でもブチッと切られてしまいます。

Sending the TERM or stop signal to the parent causes it to immediately attempt to kill off all of its children. It may take it several seconds to complete killing off its children. Then the parent itself exits. Any requests in progress are terminated, and no further requests are served.

これを防ぐために、preStopを使います。これを使うと、Podを際に任意の処理を定義することが出来ます。このpreStopを使ってApacheをgracefulにシャットダウンします。

その一連の処理を図解すると以下の通りとなります。

Screen Shot 2019-12-30 at 10.28.27

最初にご説明したように、Podは停止のリクエストを受け取ったとき、まずサービスから除外する処理を行います。これによりiptablesの設定が変更されて、該当のPodにリクエストが届かないようになります。

ただし、サービスから除外する処理が終わる前にApacheのgraceful shutdownが始まってしまうと、ユーザーのリクエストが切断されてしまう恐れがあるので、サービスから除外する処理が終わるであろう時間(だいた3秒位)待ちます。

そして、サービス除外の処理によって、停止対象のPodにリクエストが振られなくなるなったら、apachectl –k graceful-stopによって、Apacheをgracefulにシャットダウンします。

そのあと30秒ほど待ちます。Apacheのリクエストタイムアウトの設定が30秒だったと仮定します。Apacheのgraceful shutdownは非同期で行われるので、ここで30秒待たないと、ユーザーのリクエストが終わる前にSIGTERMが送信されて、バチッと切られてしまいます。

terminationGracePeriodSecondsについては、Podの終了処理がこの値で定義した秒数以内に終わらないとSIGKILLが送信されて、これまたバチッと切られてしまいますので、サービス除外の処理(3秒)+ユーザーのリクエストタイムアウト(30秒)=33秒にちょっとプラスアルファして40秒としています。

この設定であればPodは安全に停止しますので、完全なRollingUpdateが実現出来ます。

preStopはマニフェストに以下のように定義しました。

lifecycle:
  preStop:
    exec:
      command: ["sh", "-c", "sleep 3; apachectl -k graceful-stop; sleep 30"]

まとめ

RollingUpdateと一言で言っても、いろいろな設定が必要になります。これ以外にもreadinessProbeなどの設定も必要ですので、KubernetesでRollingUpdateするのはかなり手間ですが、バージョンアップの際にユーザー影響無しで無停止で更新できるRollingUpdateは非常に便利ですので、是非、参考にして頂けたらと思います。

アバター画像
About 武井 宜行 269 Articles
Microsoft MVP for Azure🌟「最新の技術を楽しくわかりやすく」をモットーにブログtech-lab.sios.jp)で情報を発信🎤得意分野はAzureによるクラウドネイティブな開発(Javaなど)💻「世界一わかりみの深いクラウドネイティブ on Azure」の動画を配信中📹 https://t.co/OMaJYb3pRN
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

3人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる