Open8

Rails x k8s Health チェック

HiroVodkaHiroVodka

k8s で運用する Rails アプリケーションにHealthチェックエンドポイントを追加しようと思ったので、そもそもHealthチェックって?みたいなところから色々調べてみた

HiroVodkaHiroVodka

k8s (EKS)でデプロイされているアプリに対して行われるヘルスチェックは

  • ALB の healthcheck
    • Ingress で指定するエンドポイント
  • livenessProbe
  • ReadinessProbe
  • (StartupProbe)
    • 今回は考慮しない
HiroVodkaHiroVodka

k8s のドキュメントで liveness と readiness の使い分けが載ってる
https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-lifecycle/#container-probes

livenessProbe
コンテナが動いているかを示します。 livenessProbeに失敗すると、kubeletはコンテナを殺します、そしてコンテナはrestart policyに従います。 コンテナにlivenessProbeが設定されていない場合、デフォルトの状態はSuccessです。

readinessProbe
コンテナがリクエスト応答する準備ができているかを示します。 readinessProbeに失敗すると、エンドポイントコントローラーにより、ServiceからそのPodのIPアドレスが削除されます。 initial delay前のデフォルトのreadinessProbeの初期値はFailureです。 コンテナにreadinessProbeが設定されていない場合、デフォルトの状態はSuccessです。

HiroVodkaHiroVodka

コンテナが動いている is Railsサーバーが起動しているということで良いと思うので、liveness で使用するヘルスチェックエンドポイントは 単純に Status: 200 を返すだけで良さそう

コンテナがリクエスト応答する準備ができているかに関してもRailsサーバーが起動していれば良さそうな気はする
ただ、

正常に動作してないアプリに、リクエスト飛ばすなってことみたい

も考慮すると、依存するミドルウェアとか DB の接続に関してもチェックした方がよさそう
なので Readiness で使用するヘルスチェックエンドポイントは、DB, redis のチェックも行う

HiroVodkaHiroVodka

ALBのヘルスチェックに関してはPodがReady になった後(Readiness 成功後)、にALBから実行されるため、再度 Readiness と同様のチェックは必要ないはず
仮にDB や redis が落ちてる場合は、Readiness が失敗して該当 Pod へのルーティングは行われないので、大丈夫
なので ALB のヘルスチェックも単なる疎通確認で 200 を返すだけでよさそう

HiroVodkaHiroVodka

ちなみに、アプリケーションのDB接続やミドルウェア接続等を確認するヘルスチェックは DeepHealthCheck って呼ばれてるらしい
https://aws.clouddesignpattern.org/index.php/CDP_Deep_Health_Checkパターン.html

ちなみに、DeepHealthCheck の運用はしっかり考えた方が良いぞって記事
https://encore.dev/blog/horror-stories-k8s

例えば DeepHealthCheck に認証サーバーの疎通確認を含めると、そのサーバーが死んだらその他サービスも全部死んでしまう
これはこれで正しいかもしれないが、もっと影響範囲を少なくできるかも?みたいな話
運用するプロダクトによって『準備完了(Readiness)』の定義はしっかり検討しよう

HiroVodkaHiroVodka

ヘルスチェックのレスポンスのフォーマットに関しては、標準化したいねみたいな話自体はあったっぽい
https://blog.frankel.ch/healthcheck-http-apis/

ただ、結局のところ進んでなさそう

k8s で ヘルスチェックする場合はレスポンスのステータスコードを参照するので、レスポンスボディを検証するのは大変そう?
一応 command 使えるので、自前で実装するのはできそうな気がする

なので成功した場合は 200, 失敗は 503 返す実装で良さそう

一応、外向けに何のチェックをしているのか分かりやすくするなら、レスポンスボディに何らかの情報を付与すれば良さそう