LoginSignup
0
0

More than 1 year has passed since last update.

php-fpmをkubernetesで運用していて、ヘルスチェックで少し失敗したこと

php-fpmの子プロセス

php-fpmのプロセスを軽くおさらい

子プロセスの数を設定してチューニングをします
staticの場合は子プロセス数固定で、pm.max_childrenで設定します
dynamicの場合は負荷に応じてプロセス数が変動しますが、最大値はstaticと同じくpm.max_childrenでの設定です

同時に処理するリクエストが増えて、子プロセスの最大値に達すると、当然それ以上子プロセスは増えないので、それ以降のリクエストは待機状態になり、処理中のものが終わってプロセスが空き次第処理されていきます

liveness/readiness

kubernetesでアプリケーションを運用する場合、基本的にはlivenessProbe/readinessProbeを設定しているはずです

方法はいくつかありますが、アプリケーションにヘルスチェックエンドポイントを作成してそこにhttpGetを設定するのがよくやるパターンかと思います
私もこの方法でphp-fpmのアプリケーションを運用していました

失敗

このアプリケーションが動作するクラスタに急激なリクエスト増加があり、HPAによるスケールが間に合わずレスポンスの遅延が起きました
この時、php-fpmは子プロセス上限数を使い切っていました
遅延はありつつも地道にリクエストを処理していたのですが、livenessProbeが失敗したことによりコンテナに再起動がかかってしまいました

ヘルスチェックの処理もひとつのリクエストの扱いになり、詰まったリクエストの中に紛れ込んで一緒に遅延してタイムアウトになったのです
ヘルスチェックがどれだけ軽い処理だったとしても、ボトルネックがプロセス数の上限で順番待ちになってしまえば関係なかったという
遅延しながらも処理はできていたのでコンテナ再起動はやめてほしかったんですけどね、設定に忠実に従った結果なので仕方ない

(処理によって必要なリソースは違うので、プロセス数の上限で管理するのがそもそも難しい…)

対応案

cpuやメモリのリソースではなくプロセス数の上限でボトルネックになるのが地味に面倒

  • プロセス数の上限を増やす
    • 詰まれば結局同じこと
    • リソースとのバランスが崩れるとそれはそれで死ぬ
  • 割り当てリソースを増やす
    • これはもちろん意味がない
  • プロセス数関係ないヘルスチェックにしたい
    • ちなみにphp-fpmのステータスページを表示するのも子プロセスが必要です

対応

1. tcpSocketでprobeを設定

    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

TCPソケットのコネクション確立で判定します
livenessはこれでもよいかも
readinessには足りないのではないかなと

2. ヘルスチェック用のプールを作成する

php-fpm.conf
[global]
; グローバル設定

[www]
; アプリケーション用のプール設定
listen = [::]:9000

[health]
; ヘルスチェック用のプール設定
listen = [::]:9001

こんな感じでプールを設定して、ヘルスチェック用ものを確保します
proxy側でヘルスチェックのpathを専用プール側に振り分ける設定も必要です
そこを分けるのは果たしてアプリケーションのヘルスチェックとしてどうなのという疑問もあります
あとはメモリ消費量がほんの少し増えます

:confused:

kubernetesでphp-fpmするの運用難しいです

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0