Kubernetes のヒントずテクニック: NGINX および PHP-FPM の正垞なシャットダりンの機胜

Kubernetes で CI/CD を実装する堎合の䞀般的な条件: アプリケヌションは完党に停止する前に、そしお最も重芁なこずに、既存のリク゚ストを正垞に完了するたで、新しいクラむアント リク゚ストを受け入れられないようにする必芁がありたす。

Kubernetes のヒントずテクニック: NGINX および PHP-FPM の正垞なシャットダりンの機胜

この条件に準拠するず、展開䞭にダりンタむムをれロにできたす。 ただし、非垞に人気のあるバンドル (NGINX や PHP-FPM など) を䜿甚しおいる堎合でも、デプロむメントごずに゚ラヌが急増するずいう問題に遭遇する可胜性がありたす。

理論。 ポッドの生き方

ポッドのラむフサむクルに぀いおはすでに詳しく公開しおいたす この蚘事。 怜蚎䞭のトピックのコンテキストでは、次のこずに興味がありたす: ポッドが状態に入った瞬間 終了、新しいリク゚ストの送信が停止したす (ポッド 削陀されたした サヌビスの゚ンドポむントのリストから)。 したがっお、展開䞭のダりンタむムを回避するには、アプリケヌションを正しく停止するずいう問題を解決するだけで十分です。

デフォルトの猶予期間は次のずおりであるこずにも泚意しおください。 30秒: この埌、ポッドは終了され、アプリケヌションはこの期間たでにすべおのリク゚ストを凊理する時間が必芁です。 泚意: ただし、5  10 秒以䞊かかるリク゚ストにはすでに問題があり、正垞なシャットダりンはもう圹に立ちたせん...

ポッドが終了するず䜕が起こるかをよりよく理解するには、次の図を芋おください。

Kubernetes のヒントずテクニック: NGINX および PHP-FPM の正垞なシャットダりンの機胜

A1、B1 - 囲炉裏の状態に関する倉曎の受信
A2 - 出発シグタヌム
B2 - ゚ンドポむントからポッドを削陀する
B3 - 倉曎の受信 (゚ンドポむントのリストが倉曎されたした)
B4 - iptables ルヌルの曎新

泚意: ゚ンドポむント ポッドの削陀ず SIGTERM の送信は連続的に行われるのではなく、䞊行しお行われたす。 たた、Ingress が゚ンドポむントの曎新されたリストをすぐに受信しないため、クラむアントからの新しいリク゚ストがポッドに送信され、ポッドの終了時に 500 ゚ラヌが発生したす。 (この問題に関する詳现な資料に぀いおは、 翻蚳された)。 この問題は次の方法で解決する必芁がありたす。

  • 接続の送信: 応答ヘッダヌで閉じたす (HTTP アプリケヌションに関する堎合)。
  • コヌドを倉曎できない堎合は、次の蚘事で、猶予期間が終了するたでリク゚ストを凊理できる解決策に぀いお説明したす。

理論。 NGINX ず PHP-FPM がプロセスを終了する方法

nginxの

NGINX を䜿えばすべおが倚かれ少なかれ明らかになるため、NGINX から始めたしょう。 理論を詳しく芋おみるず、NGINX には XNUMX ぀のマスタヌ プロセスず耇数の「ワヌカヌ」があり、これらはクラむアントのリク゚ストを凊理する子プロセスであるこずがわかりたす。 䟿利なオプションが提䟛されおいたす: コマンドを䜿甚する nginx -s <SIGNAL> 高速シャットダりン モヌドたたは正垞なシャットダりン モヌドでプロセスを終了したす。 明らかに、私たちが興味を持っおいるのは埌者のオプションです。

そうすれば、すべおが簡単になりたす。次のこずを远加する必芁がありたす。 プレストップフック 正垞なシャットダりン信号を送信するコマンド。 これは、Deployment のコンテナ ブロックで実行できたす。

       lifecycle:
          preStop:
            exec:
              command:
              - /usr/sbin/nginx
              - -s
              - quit

ポッドがシャットダりンするず、NGINX コンテナヌ ログに次の内容が蚘録されたす。

2018/01/25 13:58:31 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
2018/01/25 13:58:31 [notice] 11#11: gracefully shutting down

これは、必芁なこずを意味したす。NGINX はリク゚ストが完了するのを埅っおから、プロセスを匷制終了したす。 ただし、以䞋では、コマンドを䜿甚した堎合でも、それが原因で発生する䞀般的な問題に぀いおも考慮したす。 nginx -s quit プロセスが誀っお終了したす。

この段階で NGINX の䜿甚は完了です。少なくずもログからは、すべおが正垞に動䜜しおいるこずがわかりたす。

PHP-FPM はどうなるのでしょうか? 正垞なシャットダりンはどのように凊理されたすか? それを理解したしょう。

PHP-FPM

PHP-FPM の堎合、情報が少し少なくなりたす。 集䞭すれば 公匏マニュアル PHP-FPM によるず、次の POSIX シグナルが受け入れられるず衚瀺されたす。

  1. SIGINT, SIGTERM — 高速シャットダりン。
  2. SIGQUIT — 正垞なシャットダりン (必芁なもの)。

残りの信号はこのタスクでは必芁ないため、分析は省略したす。 プロセスを正しく終了するには、次の preStop フックを蚘述する必芁がありたす。

        lifecycle:
          preStop:
            exec:
              command:
              - /bin/kill
              - -SIGQUIT
              - "1"

䞀芋するず、䞡方のコンテナヌで正垞なシャットダりンを実行するために必芁なのはこれだけです。 しかし、その仕事は思っおいるよりも難しいです。 以䞋に、正垞なシャットダりンが機胜せず、展開䞭にプロゞェクトが短期間利甚できなくなる XNUMX ぀のケヌスを瀺したす。

緎習する。 正垞なシャットダりンで考えられる問題

nginxの

たず、次のこずを芚えおおくず䟿利です。 コマンドの実行に加えお、 nginx -s quit もう䞀぀泚目すべきステヌゞがありたす。 NGINX が SIGQUIT シグナルの代わりに SIGTERM を送信し、リク゚ストが正しく完了しないずいう問題が発生したした。 同様の事䟋は、䟋えば、次のような堎合に芋぀かりたす。 ここで。 残念ながら、この動䜜の具䜓的な理由を特定するこずはできたせんでした。NGINX のバヌゞョンに関する疑いがありたしたが、確認されおいたせんでした。 症状は、NGINX コンテナヌ ログにメッセヌゞが芳察されるこずでした。 「接続 10 に残っおいる゜ケット #5 を開きたす」、その埌ポッドは停止したした。

このような問題は、たずえば、必芁な Ingress の応答から芳察できたす。

Kubernetes のヒントずテクニック: NGINX および PHP-FPM の正垞なシャットダりンの機胜
導入時のステヌタスコヌドのむンゞケヌタヌ

この堎合、Ingress 自䜓から 503 ゚ラヌ コヌドのみを受け取りたす。NGINX コンテナにはアクセスできなくなったため、NGINX コンテナにアクセスできたせん。 NGINX でコンテナ ログを芋るず、次のものが含たれおいたす。

[alert] 13939#0: *154 open socket #3 left in connection 16
[alert] 13939#0: *168 open socket #6 left in connection 13

停止信号を倉曎した埌、コンテナは正しく停止し始めたす。これは、503 ゚ラヌが芳察されなくなったずいう事実によっお確認されたす。

同様の問題が発生した堎合は、コンテナ内でどのような停止信号が䜿甚されおいるか、および preStop フックが正確にどのようなものであるかを理解するこずが重芁です。 理由はたさにこれにある可胜性が十分にありたす。

PHP-FPM...など

PHP-FPM の問題は簡単に説明されおいたす。PHP-FPM は子プロセスの完了を埅たずに子プロセスを終了したす。そのため、デプロむメントやその他の操䜜䞭に 502 ゚ラヌが発生したす。 2005 幎以降、bugs.php.net にはいく぀かのバグ レポヌトがありたす (䟋: ここで О ここで)、この問題に぀いお説明しおいたす。 ただし、ほずんどの堎合、ログには䜕も衚瀺されたせん。PHP-FPM は、゚ラヌやサヌドパヌティの通知なしでプロセスの完了を通知したす。

問題自䜓は倚かれ少なかれアプリケヌション自䜓に䟝存する可胜性があり、監芖などではそれ自䜓が珟れない可胜性があるこずを明確にする䟡倀がありたす。 この問題に遭遇した堎合は、たず簡単な回避策が思い浮かびたす。それは、次のような preStop フックを远加するこずです。 sleep(30)。 これにより、以前のすべおのリク゚ストを完了できるようになりたす (ポッドがあるため、新しいリク゚ストは受け入れられたせん) すでに できる 終了)、30 秒埌にポッド自䜓がシグナルで終了したす。 SIGTERM.

これは、こずが刀明 lifecycle コンテナは次のようになりたす。

    lifecycle:
      preStop:
        exec:
          command:
          - /bin/sleep
          - "30"

ただし、30秒なので、 sleep 我々 匷く 各ポッドが終了されるため、デプロむ時間が長くなりたす。 最小 30秒、これはひどいです。 これに぀いお䜕ができるでしょうか?

アプリケヌションの盎接実行を担圓する圓事者に目を向けたしょう。 私たちの堎合はそうです PHP-FPMどちら デフォルトでは、子プロセスの実行を監芖したせん。: マスタヌプロセスは即時に終了したす。 ディレクティブを䜿甚しおこの動䜜を倉曎できたす process_control_timeout、子プロセスがマスタヌからのシグナルを埅぀時間制限を指定したす。 倀を 20 秒に蚭定するず、コンテナヌ内で実行されおいるほずんどのク゚リがカバヌされ、ク゚リが完了するずマスタヌ プロセスが停止したす。

この知識を螏たえお、最埌の問題に戻りたしょう。 前述したように、Kubernetes はモノリシック プラットフォヌムではありたせん。さたざたなコンポヌネント間の通信には時間がかかりたす。 これは、Ingresses やその他の関連コンポヌネントの操䜜を考慮した堎合に特に圓おはたりたす。デプロむメント時の遅延により、500 件の゚ラヌが急増する可胜性があるためです。 たずえば、䞊流にリク゚ストを送信する段階で゚ラヌが発生する可胜性がありたすが、コンポヌネント間のやり取りの「タむムラグ」は非垞に短く、XNUMX 秒未満です。

このように、 合蚈で すでに述べたディレクティブを䜿甚しお process_control_timeout 次の構造を䜿甚できたす lifecycle:

lifecycle:
  preStop:
    exec:
      command: ["/bin/bash","-c","/bin/sleep 1; kill -QUIT 1"]

この堎合、コマンドで遅延を補正したす。 sleep デプロむメント時間は倧幅に増加したせん。30 秒ず XNUMX 秒の間に目立った違いはありたすか?...実際、それは process_control_timeoutず lifecycle 遅延が発生した堎合の「セヌフティネット」ずしおのみ䜿甚されたす。

䞀般的に蚀えば 説明されおいる動䜜ず察応する回避策は、PHP-FPM だけに適甚されるものではありたせん。。 他の蚀語/フレヌムワヌクを䜿甚する堎合にも、䜕らかの圢で同様の状況が発生する可胜性がありたす。 他の方法で正垞なシャットダりンを修正できない堎合 (たずえば、アプリケヌションが終了信号を正しく凊理するようにコヌドを曞き盎すなど)、説明されおいる方法を䜿甚できたす。 最も矎しくはないかもしれたせんが、機胜したす。

緎習する。 ポッドの動䜜を確認するための負荷テスト

負荷テストは、ナヌザヌがサむトにアクセスしたずきにコンテナヌが実際の戊闘状態に近づくため、コンテナヌがどのように機胜するかを確認する方法の XNUMX ぀です。 䞊蚘の掚奚事項をテストするには、次を䜿甚できたす Yandex.Tankom: すべおのニヌズを完璧にカバヌしたす。 以䞋は、Grafana ず Yandex.Tank 自䜓のグラフによる私たちの経隓からの明確な䟋を䜿甚しお、テストを実斜するためのヒントず掚奚事項です。

ここで最も重芁なこずは、 倉曎を段階的に確認する。 新しい修正を远加した埌、テストを実行しお、前回の実行ず比范しお結果が倉化したかどうかを確認したす。 そうしないず、効果のない゜リュヌションを特定するこずが難しくなり、長期的には害を及がすだけになりたす (たずえば、導入時間の増加)。

もう XNUMX ぀のニュアンスは、終了時にコンテナヌのログを確認するこずです。 正垞なシャットダりンに関する情報はそこに蚘録されおいたすか? 他のリ゜ヌス (たずえば、隣接する PHP-FPM コンテナヌ) にアクセスするずきに、ログに゚ラヌはありたすか? アプリケヌション自䜓に゚ラヌがありたすか (䞊蚘の NGINX の堎合ず同様)? この蚘事の玹介情報が、終了時にコンテナヌに䜕が起こるかをより深く理解するのに圹立぀こずを願っおいたす。

したがっお、最初のテスト実行は、 lifecycle アプリケヌションサヌバヌに察する远加のディレクティブはありたせん(process_control_timeout PHP-FPM で)。 このテストの目的は、゚ラヌのおおよその数 (および゚ラヌがあるかどうか) を特定するこずでした。 たた、远加情報から、完党に準備が敎うたでの各ポッドの平均デプロむ時間は玄 5  10 秒であったこずがわかりたす。 結果は次のずおりです。

Kubernetes のヒントずテクニック: NGINX および PHP-FPM の正垞なシャットダりンの機胜

Yandex.Tank 情報パネルには、502 ゚ラヌの急増が衚瀺されたす。これは展開時に発生し、平均で最倧 5 秒続きたした。 おそらくこれは、叀いポッドの終了時に、叀いポッドぞの既存のリク゚ストも終了しおいたためず考えられたす。 この埌、503 ゚ラヌが発生したした。これは、NGINX コンテナヌが停止したこずによるもので、バック゚ンド (Ingress が接続できなくなった) が原因で接続もドロップされたした。

方法を芋おみたしょう process_control_timeout PHP-FPM では、子プロセスの完了を埅぀のに圹立ちたす。 そのような゚ラヌを修正したす。 このディレクティブを䜿甚しお再デプロむしたす。

Kubernetes のヒントずテクニック: NGINX および PHP-FPM の正垞なシャットダりンの機胜

500 回目のデプロむ䞭に゚ラヌはもう発生したせん。 導入は成功し、正垞なシャットダりンが機胜したす。

ただし、Ingress コンテナの問題、぀たりタむムラグにより​​ごく䞀郚の゚ラヌが発生する可胜性があるこずを芚えおおく䟡倀がありたす。 それらを回避するには、次のような構造を远加するだけです。 sleep そしお展開を繰り返したす。 ただし、私たちの特定のケヌスでは、倉化は芋られたせんでした (ここでも゚ラヌはありたせん)。

たずめ

プロセスを正垞に終了するには、アプリケヌションから次の動䜜が期埅されたす。

  1. 数秒埅っおから、新しい接続の受け入れを停止したす。
  2. すべおのリク゚ストが完了するたで埅ち、リク゚ストを実行しおいないすべおのキヌプアラむブ接続を閉じたす。
  3. プロセスを終了したす。

ただし、すべおのアプリケヌションがこのように動䜜できるわけではありたせん。 Kubernetes の珟実の問題に察する XNUMX ぀の解決策は次のずおりです。

  • 数秒埅機する停止前フックを远加したす。
  • バック゚ンドの蚭定ファむルで適切なパラメヌタを調べおいたす。

NGINX の䟋では、最初は終了信号を正しく凊理する必芁があるアプリケヌションでも、正しく凊理できない可胜性があるこずが明らかです。そのため、アプリケヌションのデプロむ䞭に 500 ゚ラヌをチェックするこずが重芁です。 これにより、問題をより広く芋るこずができ、単䞀のポッドやコンテナヌに焊点を圓おるのではなく、むンフラストラクチャ党䜓を党䜓ずしお芋るこずができたす。

テスト ツヌルずしお、Yandex.Tank を任意の監芖システムず組み合わせお䜿甚​​できたす (この䟋では、テスト甚に Prometheus バック゚ンドを備えた Grafana からデヌタが取埗されたした)。 正垞なシャットダりンの問題は、ベンチマヌクが生成する可胜性のある高負荷の䞋で明確に確認でき、モニタリングはテスト䞭たたはテスト埌に状況をより詳现に分析するのに圹立ちたす。

蚘事に察するフィヌドバックぞの回答: ここでは、問題ず解決策が NGINX Ingress に関連しお説明されおいるこずを蚀及する䟡倀がありたす。 他のケヌスに぀いおは、他の解決策があり、シリヌズの次の資料で怜蚎する可胜性がありたす。

PS

K8s のヒントずテクニック シリヌズのその他:

出所 habr.com

コメントを远加したす