https://srcco.de/posts/kubernetes-liveness-probes-are-dangerous.html の和訳
Kubernetesの livenessProbe は 危険な場合があります。
明確なユースケースを持っていてその結果を理解するまで使用を避けるのをお勧めします。
このポストは、Liveness および Readiness Probeに注目し
いくつかの「Do」と「Don't」を説明します。
私の同僚である、Sandorは最近、彼が見た一般的なミスについてツイートしています。 これは、間違ったReadiness Probe/Liveness Probeの使い方を含みます。
Kubernetesを初めて使用する人がする同じ間違い:
- 存在しないreadinessProbe
- 間違ったreadinessProbe
- livenessProbe = readinessProbe
- グレースフルシャットダウンしない
- グレースフルシャットダウンが十分グレースフルじゃない。ライフサイクルフックを活用する
https://opensource.zalando.com/skipper/kubernetes/ingress-backends/#pod-lifecycle-hooks
- pre fork mode
間違った livenessProbe の設定は、高負荷環境を悪化(障害のカスケード + 潜在的な長いコンテナ/アプリケーションの再起動)させ
依存関係を巻き込んで落ちるような、その他のネガティブな結果を導く場合があります。(参考: 私の最近のk3s + ACMEのレートリミットについての記事)
Liveness Probeと外部のDBのヘルスチェックの依存関係を組み合わせることは最悪の状況です。
一つのDBのしゃっくりがあなたの全てのコンテナを再起動します!
「Liveness Probeを使用するな」という包括的な説明は、役に立ちません。そこで、Readiness ProbeとLiveness Probeが何のためにあるかを見ていきましょう。 NOTE: 次のテキストのほとんどは最初はZalando内部の開発者のドキュメントのためにまとめられました。
Kubernetesは、Liveness ProbeとReadiness Probeの二つの本質的な機能を提供しています。(※訳者注 Startup Probeも追加されました。) 本来、Liveness/Readiness Probeは、アプリケーションが意図したとおりに動作しているかどうかを確認するために、定期的にアクションを実行します。 (例としては、HTTPリクエストをしたり、TCPコネクションを開いたり、コマンドをコンテナの中で実行します)
Kubernetesは Readiness Probe を コンテナがいつトラフィックを受け入れ始めるのに準備が出来ているかを知るために使います。 Podは、コンテナのすべてが readyであるときに readyだと考えられます。(※訳者注 Podは複数のコンテナを含むため) このシグナルの使い方の一つは、どのPodがServiceのバックエンドとして使われるかを制御するためです。
Kubernetes は Liveness Probe を いつコンテナを再起動するかを知るために使います。例えば、Liveness Probeはアプリケーションは実行されているにも関わらず、先に進むことが出来ないdeadlockを捕捉する可能性があります。 そのような状態のコンテナを再起動することで、バグがあっても、アプリケーションの可用性が向上しますが、再起動は同時に、カスケード障害を引き起こすこともあります。(下を見てください)
もし、あなたがLiveness/Readiness Probeが失敗するアプリケーションへの変更をデプロイしようとしたら、ローリングデプロイは、すべてのPodがReadyになるのを待つため、ハングします。
例の Readiness Probeは /health のパスに対して、デフォルトの設定でHTTPでチェックしています。
(デフォルトの設定は、interval: 10 seconds, timeout: 1 seconds, suceess threshold: 1,failure threshold: 3)
# part of a larger deployment/stack definition
podTemplate:
spec:
containers:
- name: my-container
# ...
readinessProbe:
httpGet:
path: /health
port: 8080- HTTPエンドポイントを提供しているマイクロサービスは、トラフィックを受け取る準備が出来たことを確認するreadiness probeを必ず定義しましょう。
- Readiness probeが、実際のWebサーバのポートの準備状況をカバーしていることを確認してください。
- readiness probeが別のポートを使っているときには、メインのHTTPポートがトラフィックを受け取る準備ができている場合に、OKを返すエンドポイントにしましょう。
- readiness probeが違うポートを持っていると、メインのポートのスレッドプールの輻輳の問題が発生し、ヘルスチェックの中で反映されない可能性があります。
- (つまり、メインサーバのスレッドプールがフルになっても、ヘルスチェックはOKを返す)
- Readiness Probeは、databaseの初期化・マイグレーションを含んでいることを確認しましょう。
- これを得る一番シンプルな方法は、(e.g. FlywayのDB Migration等) 初期化が終わったあとにHTTPサーバを開始させることです。 つまり、ヘルスチェックのステータスを変える代わりに、単にマイグレーションが終わるまでWebサーバを立ち上げないでください。
- Readiness Probesは、httpGetを well-knownなヘルスチェックのエンドポイントに対して行ってください。(e.g. /health)
- Probeのデフォルトの設定を理解してください (interval: 10s, timeout: 1s, successThreshold: 1, failureThreshold: 3)
- このデフォルト値は、Podが、30sの後、not readyになることを意味しています。(ヘルスチェックが3回失敗した場合)
- 通常のトラフィックから、managementのhealth や metricsを分離するために、技術スタック(Java/Spring)でこれを許可されているならば、違うポートを使用してください。
- ただし、2番目の話は注意が必要です。
- 必要があれば、Readiness Probeを利用して、prewarming/cache loadingなどのために、コンテナが "warm"になるまで503を返すことが出来ます。
- また、1.16で導入された、startupProbeをチェックしてください。(訳者注: この用途だと、startupProbeのほうが適切)
- カスケード障害(連鎖的な障害)につながる可能性があるため、Readiness/Liveness Probeでは "外部"の依存(データストア)に依存しないでください
- e.g. statefulなRESTサービスに10個のPodがあり、それらが一つのPostgresに依存しているとする。 このとき、probeがDBコネクションに依存しているとき、もしデータベース/ネットワークがしゃっくりしたとき、10のPodがダウンします。 これは通常、必要以上に影響を悪化させます
- Spring Dataのデフォルトの挙動はDBのコネクションをチェックすることに注意してください。
- このコンテキストにおける、"外部"は同じアプリケーションの他のPodのことも意味します。つまり、probeは理想的には、連鎖的障害を防ぐために、同じクラスタの他のPodの状態に依存しないようにするべきです。
- 分散状態のアプリ(e.g. Podをまたがるインメモリキャッシュなど)では、範囲が異なる場合があります。
- 訳者注: 範囲って言ってるのは、"外部"の範囲だと思われる。
- 分散状態のアプリ(e.g. Podをまたがるインメモリキャッシュなど)では、範囲が異なる場合があります。
- あなたが次の結果と、なぜLiveness Probeが必要なのかについて理解するまで、あなたのPodではLiveness Probeを使わないでください。
- Liveness Probeは、"stuck"したコンテナを回復するのに役立ちますが、アプリケーションのことを完全に所有しているため、"stuck"したプロセスやデッドロックのようなことを期待するべきではありません。 よりよい代替案は、既知の状態に回復するために意図的にクラッシュすることです。
- 失敗している Liveness Probeはコンテナの再起動に導きます。すなわち、潜在的に負荷に関係のあるエラーの影響をより悪いものにします。コンテナの再起動はダウンタイムをまねき、(少なくともアプリが立ち上がる時間. 例: 30s) そして、より多くのエラーを引き起こし、他のコンテナによりトラフィックの負荷を流し、より多くのコンテナを失敗に導きます。
- Liveness Probeと外部の依存の組み合わせは、連鎖的障害を引き起こす最悪の状態です。一つのDBのしゃっくりが、全てのコンテナを再起動させます。
- もし、あなたがLiveness Probeを使うなら、Liveness ProbeとReadiness Probeを同じ使用に設定しないでください。
- 同じヘルスチェックをLiveness Probeに使うことが出来ますが、より高いfailureThresholdにしてください。 (e.g 3 attemptsをnot-readyにして、10 attemtsをlivenessにする)
- "exec" probeは使わないでください。ゾンビプロセスを引き起こす既知の問題があります。
- Podがトラフィックを受け取るべき時を決めるために、あなたのWebアプリのReadiness Probeを使え
- あなたが本当に必要な時だけ、Liveness Probeを使え
- Liveness/Readiness Probeの間違った利用は可用性を下げ、障害をカスケードさせることを導くことがある。
- Kubernetes docs: Configure Liveness and Readiness Probes
- Kubernetes Liveness and Readiness Probes Revisited: How to Avoid Shooting Yourself in the Other Foot
- NRE Labs Outage Post-Mortem (involves livenessProbe)
訳者注: やる気なかったので、適当翻訳
KubernetesにはPodDisruptionBudgetがあるが、probeを尊重していません。理想的には、k8sに "Podをprobeの失敗で再起動しますが、事態を悪化させないために全部は再起動しないでください"と指示できるでしょう。
訳者注: 省略