KubernetesのLivenessProbe, ReadinessProbe, StartupProbeのベストプラクティス
Podの状態を検知するための3種類のProbe(Liveness Probe、Readiness Probe、Startup Probe)の挙動、使用方法、ベストプラクティスについてまとめました。
なぜProbeが必要か
Kubernetesのデフォルトの挙動では、Pod内の全てのコンテナが起動したらトラフィックを流しめ、コンテナがクラッシュしたらPodを再起動します。これで十分な場合もありますが、そうでない場合もあります。
たとえば、アプリケーションがコンテナの起動からトラフィックを受け付けられるようになるまで時間がかかる場合、まだトラフィックを受け付けられないのにトラフィックは流れてくるので、500エラーを返してしまうことになります。
こういったことが起きないようにProbeを設定することで、いつトラフィックを流してよいのか、いつコンテナアプリケーションが起動しているのか、いつPodを再起動すればよいか、をKubernetesに指示することができます。
Probeの種類
- Liveness Probe
- コンテナをいつ再起動するかを認識します
- バグがあるPodを再起動することでアプリケーションの可用性を高める
- Readiness Probe
- コンテナがトラフィックを受け入れられる状態であるかを認識します
- トラフィックが受け入れられないPodをServiceのロードバランシングから切り離す
- Startup Probe
- コンテナアプリケーションの起動が完了したかを認識します
- Startup Probeが成功するまでは、Liveness Probeによるチェックを無効する
- v1.16でalpha、v1.18でbeta、v1.20でGA (参考: Feature Gates)
Probeのパラメータ
-
initialDelaySeconds
- コンテナが起動してから、Probeが開始されるまでの秒数。デフォルトは
0
秒。最小値は0
。
- コンテナが起動してから、Probeが開始されるまでの秒数。デフォルトは
-
periodSeconds
- Probeが実行される頻度(秒数)。デフォルトは
10秒
。最小値は1
。
- Probeが実行される頻度(秒数)。デフォルトは
-
timeoutSeconds
- Probeがタイムアウトになるまでの秒数。デフォルトは
1秒
。最小値は1
。
- Probeがタイムアウトになるまでの秒数。デフォルトは
-
successThreshold
- 一度Probeが失敗した後、次のProbeが成功したとみなされるための最小連続成功数。 デフォルトは
1
。最小値は1
。 - Liveness Probeは
1
しか設定できない
- 一度Probeが失敗した後、次のProbeが成功したとみなされるための最小連続成功数。 デフォルトは
-
failureThreshold
- Probeが失敗した場合、Probeを試行する回数。デフォルトは
3
。最小値は1
。 - Liveness Probeの場合、試行回数に到達するとコンテナを再起動する
- Readiness Probeの場合、試行回数に到達するとPodが準備できていない状態として通知される
- Probeが失敗した場合、Probeを試行する回数。デフォルトは
Readiness Probe
Readiness Probeはコンテナがトラフィックを受け入れられる状態であるかをkubeletに伝えます。 アプリケーションは起動に時間がかかる場合はReadiness Probeを定義してKubernetesのServiceからトラフィックを受信しないようにします。
(GCP Blogより引用)
Readiness Probeの挙動で重要なポイントは、Readiness Probeはコンテナの全てのライフサイクルにおいて実行されることです。つまり、Podが起動したときだけではなく、Podが起動してる間ずっと繰り返しProbeを実行し続けます。
これはアプリケーションが一時的に使えない場合(大きなファイルを読み込む場合、外部と通信を待っている場合など)を検知するためです。これにより、アプリケーションを再起動せずに、アプリケーションが再び使えるようになるまでトラフィックを止めます。アプリケーションが使える状態になったら、トラフィックを再び送りはじめます。
Liveness Probe
Liveness Probeは異常な状態のコンテナを再起動するために使います。kubeletはコンテナの状態を定期的に確認し、コンテナが異常な状態であればPodを再起動します。
プロセスが実行されている限りKubenetesはPodが正常に動作してるとみなします。Liveness Probeを設定しないと、アプリケーションは異常な状態なのにKubernetesはそれを正常な状態だとみなし、Podを再起動することなく起動し続けるといったことが起こりえます。
Liveness Probeを設定することで、アプリケーションが異常な状態であることをkubeletが検知し、Podを再起動してくれます。
(GCP Blogより引用)
Startup Probe
Startup Probeは、Podの起動時にのみ実行されるReadiness Probeです。起動に時間がかかるが、どれくらい時間がかかるか予測できないようなアプリケーションに対して有効です。
Readiness Probeでは initialDelaySeconds
を設定することで、Readiness Probeを開始するまでの時間を設定することができます。例えば、起動するとき大容量のファイルダウンロードが時々必要なアプリケーションについて考えてみます。この場合、initialDelaySeconds
は定数のため、最も時間がかかるケースに合わせて指定する必要があるので、素早く起動できた時でも遅く起動するときと同じだけの時間を待つ必要があります。また、failureThresholdthat
の値を大きくすることで起動時間の変化に対応することもできますが、こちらを大きくすると実行中のアプリケーションが異常な状態になったことを検知するのにより多くの時間がかかることになってしまうので良くないです。
Startup Probeを定義することで、起動にかかる時間の変化に適切に対応することができます。例えば、failureThreshold
を30
に、periodSeconds
を10
に設定すると、 30 * 10秒 = 300秒間はアプリケーションの起動を待ち続け、アプリケーションが素早く起動した場合はそのことを検知でき次第、Liveness Probeのチェックが開始されます。
Probeの判定方法
HTTP
kubeletがHTTPのGETリクエストを送信し、200番台か300番台のレスポンスが返ってくるかどうか確認します。
HTTP Probeのパラメータ
-
host
: 接続先のホスト(初期値: PodのIP) -
scheme
: HTTPかHTTPS(初期値: HTTP) -
path
: HTTPサーバーへアクセスする際のパス -
httpHeaders
: リクエスト内のカスタムヘッダー。認証やCORSなどに用いる。 -
port
: コンテナにアクセスする際のポートの名前または番号
TCP
kubeletはPodの中ではなく、ノードに対してコネクションを確立するProbeを実行します。TCPによるProbeは、gRPCサーバーやFTPサーバーなどHTTP通信ができない場合に有効です。
readinessProbe:
tcpSocket:
port: 21
Command
kubeletがコンテナ内で指定されたコマンドを実行し、プロセスの終了ステータスで0が返ってきたらPodが正常であるとみなします。CommandによるProbeは、HTTPサーバーではない場合、ポートを公開しない場合、または、起動したかどうかコマンドで簡単に知れる場合(設定ファイルが作成されているかどうかなど)に有効です。
readinessProbe:
exec:
command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"]
ベストプラクティス
- 古いバージョンのKubernetes(≤ 1.15)
- Readiness Probeで
initialDelaySeconds
で起動にかかる最も遅いと予測される時間を設定します。 - Readiness ProbeはPod起動中ずっと実行されるため、Readiness Probeのために軽量なエンドポイントを作成しておきます。(/healthcheckなど)
- Readiness Probeで
- 最近のバージョンのKubernetes(≥ 1.16)
- Startup Probeを設定して、変動する起動時間に対応します。
- Startup ProbeのためのエンドポイントはReadiness ProbeとLiveness Probeのためのエンドポイントと同一のもので問題ありません。(/healthcheckなど)
-
failureThreshold
について、Startup Probeは起動に時間がかかってしまった場合のために、大きめの値を設定しておきます。Readiness ProbeとLiveness Probeは必要最小限の値にします。
- Readiness ProbeとLiveness Probeは同一のエンドポイントは、特に他の利用用途がない場合は同一のエンドポイントを利用します。もし、Podが1つしかない場合(Vertical Pod Autoscalerを使ってる場合など)は、Readiness Probeは起動のためにのみ使い、Liveness ProbeでPodの状態を管理します。
- Readiness Probeはシステムの不調をチェックするためにいろいろな用途で利用できます。たとえば、アプリケーションがDBとのコネクションが切れてしまった場合、Readiness Probeを使い新しいリクエストの受付を一時的に停止し、アプリケーションがDBと再接続するまで待たせることができます。他には、新しいリクエストを受け入れる余裕のないPodをUnhealthyとしてReadiness Probeにチェックさせることで、ロードバランシングようなことをさせることも可能です。
ツール
KubernetesのProbeを設定する時に役に立つツールを紹介します。これらのツールは、すでにあるクラスタで実行させたり、CI/CDパイプライン上で実行させることで、いい感じに設定されてないワークロードへの反映を制限してくれるようです。(筆者はまだ使ったことありません)
- polaris: いい感じの分析用ダッシュボード、dangerと判定されるマニフェストが適用される場合にそれを自動的に拒否する仕組み、CLIとしても使えることが特徴
- kube-score: Helm、Kustomize、普通のYamlで利用できる静的コード解析ツール
- popeye: Kubernetesクラスターをスキャンし問題点をレポートしてくれる読み取り専用ツール
参考文献
- https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
- https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes
- https://blog.devgenius.io/understanding-kubernetes-probes-5daaff67599a
Discussion