TT Lab
はじめる
学ぶ 学習パス コース

CKAD — Kubernetesアプリケーション開発者

プローブの設計と中断バジェット

TT Labで続きを見る

目標

3種類のプローブを、検査方式(httpGet/tcpSocket/exec)とタイミングのフィールドまで指定して作成し、Deploymentの準備状態と終了時の動作、そしてPodDisruptionBudgetを設計できるようになります。

なぜ重要なのか

プローブを付けていないDeploymentは、ローリングアップデートの安全装置がすべて無力化された状態です。maxUnavailable: 0を指定しても、コンテナが起動した直後にReadyとみなされ、初期化中のPodにトラフィックが流れ込みます。逆に、プローブを攻撃的に設定しすぎると、正常なPodが再起動を繰り返し、かえって障害を引き起こします。そのため、プローブは「付けたか」ではなく「数値を計算して付けたか」が鍵です。

livenessとreadinessを混同すると、事故が大きくなります。依存サービス(DB)が一時的に停止したときにそれをlivenessで検査すると、すべてのPodが同時に再起動を繰り返し、DBが復旧しても回復が遅れます。外部の依存先はreadinessで検査します。トラフィックを受け取らなければよいだけで、再起動する理由はありません。

startupプローブは、この2つの間の緊張を解きます。livenessにinitialDelaySeconds: 300を指定すると、運用中の障害検知も5分遅れますが、startupで300秒の予算を別に与えれば、起動後はlivenessを細かく保てます。

ステップ

  1. ネームスペースckad-obsを作成し、Pod web-liveを作成してください。イメージはnginx:1.27、livenessProbeはhttpGetでpath /healthz、port 80、initialDelaySeconds: 5、periodSeconds: 10です。
  2. Pod db-readyを作成してください。イメージはnginx:1.27、readinessProbeはtcpSocketのport 5432、initialDelaySeconds: 10、periodSeconds: 5、failureThreshold: 3です。
  3. Pod file-checkを作成してください。イメージはbusybox:1.36、command: ["/bin/sh","-c","sleep 3600"]、livenessProbeはexecでcommand: ["cat","/tmp/healthy"]、periodSeconds: 5、failureThreshold: 2です。
  4. Pod legacy-appを作成してください。イメージはnginx:1.27です。startupProbeはhttpGetのpath /startup、port 8080、failureThreshold: 30、periodSeconds: 10(= 300秒の予算)にします。同じコンテナにlivenessProbeも、httpGetのpath /healthz、port 8080、periodSeconds: 10で付けてください。
  5. Pod budget-appを作成してください。イメージはnginx:1.27、readinessProbeはhttpGetのpath /ready、port 80、initialDelaySeconds: 15です。最初の失敗から20秒以内にエンドポイントから外れるように、periodSecondsとfailureThresholdを自分で決めてください。条件はperiodSeconds × failureThreshold ≤ 20、failureThreshold ≥ 3、periodSeconds ≥ 2です。
  6. Deployment apiを作成してください。レプリカは3、ラベルはapp=api、イメージはnginx:1.27です。コンテナにreadinessProbe(httpGet /ready:8080)とlivenessProbe(httpGet /healthz:8080)を付け、terminationMessagePolicy: FallbackToLogsOnErrorを指定してください。
  7. PodDisruptionBudget api-pdbを作成してください。minAvailable: 2、selectorはapp=apiです。
  8. Deployment apiにstartupProbeを追加してください。httpGetのpath /startup、port 8080、failureThreshold: 12、periodSeconds: 5です。そして、PodのspecのterminationGracePeriodSecondsを60に設定してください。既存のreadiness/livenessプローブとレプリカ3はそのまま維持してください。

参考

HTTPのlivenessプローブを設定する

ネームスペースckad-obsを作成し、Pod web-liveを作成してください。イメージはnginx:1.27、livenessProbeはhttpGetでpath /healthz、port 80、initialDelaySeconds: 5、periodSeconds: 10です。

livenessProbe.httpGetにpathとportを指定します。プローブはコンテナの下にあり、Podレベルではありません。レスポンスコードが200–399なら成功とみなします。

TCPのreadinessプローブを設定する

Pod db-readyを作成してください。イメージはnginx:1.27、readinessProbeはtcpSocketのport 5432、initialDelaySeconds: 10、periodSeconds: 5、failureThreshold: 3です。

tcpSocketはポートだけあれば十分です。接続が確立すれば成功です。readinessは失敗しても再起動せず、エンドポイントから外れるだけです。

execプローブを設定する

Pod file-checkを作成してください。イメージはbusybox:1.36、command: ["/bin/sh","-c","sleep 3600"]、livenessProbeはexecでcommand: ["cat","/tmp/healthy"]、periodSeconds: 5、failureThreshold: 2です。

exec.commandは文字列の配列で、シェルを経由しません。終了コードが0なら成功です。ファイルの存在だけを確認するなら、わざわざシェルを呼び出す必要はありません。

startupプローブで遅い起動を包む

Pod legacy-appを作成してください。イメージはnginx:1.27です。startupProbeはhttpGetのpath /startup、port 8080、failureThreshold: 30、periodSeconds: 10(= 300秒の予算)にします。同じコンテナにlivenessProbeも、httpGetのpath /healthz、port 8080、periodSeconds: 10で付けてください。

startupプローブが成功するまで、liveness/readinessはそもそも開始しません。起動の予算はperiodSeconds × failureThresholdで計算します。このPodにはlivenessも一緒に付けます。

検知の遅延を計算して値を決める

Pod budget-appを作成してください。イメージはnginx:1.27、readinessProbeはhttpGetのpath /ready、port 80、initialDelaySeconds: 15です。最初の失敗から20秒以内にエンドポイントから外れるように、periodSecondsとfailureThresholdを自分で決めてください。条件はperiodSeconds × failureThreshold ≤ 20、failureThreshold ≥ 3、periodSeconds ≥ 2です。

最初の失敗から対処までにかかる時間は、おおよそperiodSeconds × failureThresholdです。要求された上限の中に収めつつ、failureThresholdを十分に大きくして、一時的な失敗に振り回されないようにします。正解は1つではありません。

Deploymentにプローブと終了メッセージポリシーを付ける

Deployment apiを作成してください。レプリカは3、ラベルはapp=api、イメージはnginx:1.27です。コンテナにreadinessProbe(httpGet /ready:8080)とlivenessProbe(httpGet /healthz:8080)を付け、terminationMessagePolicy: FallbackToLogsOnErrorを指定してください。

Deploymentのプローブは、spec.template.spec.containers[]の下に入ります。終了メッセージポリシーも同じコンテナレベルのフィールドで、値は2つだけなので、kubectl explainで確認してください。

PodDisruptionBudgetで自発的な中断を制限する

PodDisruptionBudget api-pdbを作成してください。minAvailable: 2、selectorはapp=apiです。

PDBはpolicy/v1で、minAvailableまたはmaxUnavailableのどちらか一方だけを使います。selectorはDeploymentではなくPodのラベルを指す必要があります。

起動の予算と終了の予算を一緒に設定する(総合)

Deployment apiにstartupProbeを追加してください。httpGetのpath /startup、port 8080、failureThreshold: 12、periodSeconds: 5です。そして、PodのspecのterminationGracePeriodSecondsを60に設定してください。既存のreadiness/livenessプローブとレプリカ3はそのまま維持してください。

前に作成したDeploymentにstartupプローブを追加し、終了の猶予時間を延ばします。terminationGracePeriodSecondsはPodのspec(spec.template.spec)レベルで、コンテナレベルではありません。既存のliveness/readinessはそのまま残します。