Skip to content

Instantly share code, notes, and snippets.

@wreulicke
Last active May 14, 2024 14:04
Show Gist options
  • Select an option

  • Save wreulicke/4a8252f01218ab04676a8aac7db81aac to your computer and use it in GitHub Desktop.

Select an option

Save wreulicke/4a8252f01218ab04676a8aac7db81aac to your computer and use it in GitHub Desktop.
LIVENESS PROBES ARE DANGEROUSの和訳

https://srcco.de/posts/kubernetes-liveness-probes-are-dangerous.html の和訳

Liveness Probe は 危険

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内部の開発者のドキュメントのためにまとめられました。

Readiness and Liveness Proves

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になるのを待つため、ハングします。

Example

例の 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

DOs

  • 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のほうが適切)

DON'Ts

  • カスケード障害(連鎖的な障害)につながる可能性があるため、Readiness/Liveness Probeでは "外部"の依存(データストア)に依存しないでください
    • e.g. statefulなRESTサービスに10個のPodがあり、それらが一つのPostgresに依存しているとする。 このとき、probeがDBコネクションに依存しているとき、もしデータベース/ネットワークがしゃっくりしたとき、10のPodがダウンします。 これは通常、必要以上に影響を悪化させます
  • Spring Dataのデフォルトの挙動はDBのコネクションをチェックすることに注意してください。
  • このコンテキストにおける、"外部"は同じアプリケーションの他のPodのことも意味します。つまり、probeは理想的には、連鎖的障害を防ぐために、同じクラスタの他の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は使わないでください。ゾンビプロセスを引き起こす既知の問題があります。

Summary

  • Podがトラフィックを受け取るべき時を決めるために、あなたのWebアプリのReadiness Probeを使え
  • あなたが本当に必要な時だけ、Liveness Probeを使え
  • Liveness/Readiness Probeの間違った利用は可用性を下げ、障害をカスケードさせることを導くことがある。

Further Reading

Update 2019-09-29 #1

訳者注: やる気なかったので、適当翻訳

KubernetesにはPodDisruptionBudgetがあるが、probeを尊重していません。理想的には、k8sに "Podをprobeの失敗で再起動しますが、事態を悪化させないために全部は再起動しないでください"と指示できるでしょう。

Update 2019-09-29 #2

訳者注: 省略

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment