Kubernetes における Probe とは何か
Kubernetes の Probe は kubelet が定期的にコンテナの状態を診断する仕組みで、以下の 3 種類があります。
| Probe の種類 | 役割 | 失敗時の挙動 |
|---|---|---|
| Liveness Probe | アプリケーションが生きているか(デッドロックしていないか)を確認 | Pod(コンテナ)を 再起動 する |
| Readiness Probe | アプリケーションがリクエストを処理できるかを確認 | Service(EndPoints)から 除外 する |
| Startup Probe | アプリケーションの起動が完了したかを確認 | 完了するまで他の Probe を無効化し、失敗し続けると再起動 する |
kubelet は Probe の定義に従ってコンテナをチェックし、その結果に基づいてアクションを実行します。
Probe の動作フロー図
各 Probe がどのような順序で機能するかを理解することは非常に重要です。特に Startup Probe が設定されている場合、それが成功するまで他の Probe は動きません。
Liveness / Readiness / Startup の違い
| Liveness Probe | Readiness Probe | Startup Probe | |
|---|---|---|---|
| 目的 | アプリケーションの故障(Deadlock 等)検知 | トラフィック受け入れの可否判断 | 起動完了までの保護 |
| 失敗時のアクション | コンテナの再起動 | Service(EndPoints)からの削除 | コンテナの再起動 |
| 実行タイミング | コンテナ稼働中(Startup 完了後) | コンテナ稼働中(Startup 完了後) | コンテナ起動直後のみ |
| 代表的なエンドポイント |
/healthz(軽量) |
/ready(依存チェック含む場合あり) |
/healthz または /startup
|
| ユースケース | メモリリーク、デッドロックからの復旧 | DB 接続確立待ち、初期データロード待ち | Java / Rails 等の起動が重いアプリケーション |
Readiness Probe と Startup Probe が分かれている理由
Readiness Probe があれば、起動完了も判定できるのではと思うかもしれませんが、これらが分かれているのには明確な理由があります。
起動が遅いアプリケーションの再起動ループの防止
例えば Java(Spring Boot)や Rails、巨大な ML モデルをロードするアプリケーションは、起動に数十秒〜数分かかることがあります。
もし Startup Probe がなく、Liveness Probe しかなかった場合、次のような問題が発生することがあります。
- アプリケーション起動開始
- まだ準備中なのに Liveness Probe が実行される
- タイムアウトで失敗判定
- 誤ってコンテナが再起動される
- 1 に戻って永遠に起動しない(CrashLoop)
initialDelaySeconds を使って「起動するまでの予測時間」だけ待機する方法もありますが、固定値での設定には以下の課題があります。
- 設定が短すぎる場合:ノードが高負荷な場合等、環境要因で起動が少しでも遅れると、準備中に Liveness Probe が失敗し、再起動ループ(CrashLoopBackOff)に陥る
- 設定が長すぎる場合:アプリケーションが早く起動しても、設定した時間が経過するまで監視が始まらず、無駄な待機時間が発生する可能性がある
Startup Probe を利用すると、最大でこれくらい待つ(failureThreshold * periodSeconds)という十分な猶予(ワーストケース)を確保しつつ、起動が完了次第、即座に Liveness / Readiness Probe へ移行する(ベストケース)ことが可能です。
これにより、環境毎の起動時間のばらつきを吸収し、誤検知の防止と素早いサービスインを両立できます。
Readiness Probe はトラフィック制御に専念する
Readiness Probe の役割は、コンテナが現時点でリクエストを受けられるかどうかを判断することに関心があります。もし起動完了の判定(Startup Probe)とトラフィック制御(Readiness Probe)を混同すると、以下のような問題に遭遇する可能性があります。
- 起動中の誤検知
起動処理中に Readiness Probe が動くと、まだ準備できていないのに Service に組み込まれてしまうリスクがある(設定次第)
- Liveness との干渉
Startup Probe が成功するまで Liveness Probe を止めておく機能は、Startup Probe 固有のもの
各 Probe の最適な設定例
HTTP Probe の場合
一般的な Web アプリケーション向けの構成は次のようになります。
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
# Liveness は軽量なエンドポイントを叩くこと
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 3
# DB 接続確認等を含めても良いが、重すぎないように注意する
startupProbe:
httpGet:
path: /healthz # Liveness Probe と同じパスでも可
port: 8080
failureThreshold: 30 # 30回 × 10秒 = 最大300秒(5分)待機
periodSeconds: 10
起動が遅いアプリケーション
Java や Rails 等の起動に時間が掛かるレガシーアプリケーションの場合、startupProbe の failureThreshold を大きく設定して時間を稼ぎます。
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 120 # 最大10分待機(5秒 120回)
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
initialDelaySeconds: 0 # Startup Probe があるので 0 で OK
HTTP を話さないコンポーネント
gRPC / DB / Redis 等の場合、TCP ソケットの確立をもって正常とみなします。
livenessProbe:
tcpSocket:
port: 50051 # gRPC ポート
periodSeconds: 10
readinessProbe:
tcpSocket:
port: 50051
periodSeconds: 5
コマンド実行による Exec Probe
HTTP も TCP も使えない、あるいはバッチ処理のような場合、内部コマンドの終了コード(0 か否か)で判定します。
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
アンチパターンと改善策
よくある失敗設定とその対策をまとめました。
Liveness Probe で DB 接続確認を行ってしまう
多くの開発者がやりがちな間違いとして、Liveness Probe のエンドポイント内でデータベースへの接続確認(例:SELECT 1)を含めてしまうことが挙げられます。データベースに繋がらないならアプリケーションは死んでいるも同然と考えがちですが、これは危険な設定です。
- 問題点:共倒れ(Thundering Herd)のリスク
もしデータベースが一時的な過負荷やメンテナンスで瞬断した場合、全ての Pod の Liveness Probe が同時に失敗します。その結果、Kubernetes は全ての Pod を一斉に再起動させます。DB が復旧したタイミングで、再起動した大量の Pod が一斉に接続しに行くと、DB にさらなる負荷がかかり、再びダウンさせてしまう(共倒れ)を引き起こす可能性があります。
- 改善案:Liveness はプロセス生存確認に留める
Liveness Probe はアプリケーションプロセスが稼働しているか、デッドロックしていないかだけの確認(例:/healthz)に留めるべきです。DB 接続等の外部依存の確認は、必要であれば Readiness Probe で行うか、あるいはアプリケーションのログやメトリクス監視で検知する方針が安全です。
Startup Probe を使わず initialDelaySeconds だけに頼る
Startup Probe が導入される前は、livenessProbe の initialDelaySeconds(初回実行までの待機時間)を長めに設定することで、起動中の再起動を防いでいましたが、現在では推奨されていません。
- 問題点:固定値による不確実性
initialDelaySeconds は固定値です。アプリケーションの起動時間は、ノードの負荷状況や外部サービスの応答速度によって変動します。設定が短すぎれば起動中に再起動ループに入り、長すぎれば起動完了後も監視が始まらず、万が一の故障検知が遅れます。
- 改善案:Startup Probe の導入
起動時間のばらつきを吸収できる Startup Probe を必ず導入します。これにより、起動完了までは Liveness Probe が動かないことが保証され、かつ起動完了後は即座に監視がスタートします。
Probe のタイムアウト設定が短すぎる
Probe の timeoutSeconds のデフォルト値は 1 秒です。これは多くのアプリケーションにとって厳しすぎる設定です。
- 問題点:一時的な負荷による誤検知
アプリケーションロジック自体は正常でも、GC の発生中や、一時的なネットワーク遅延、ノードの高負荷時において、応答が 1 秒を超えることは珍しくありません。タイムアウトが短すぎると、こうした一時的な遅延を障害と誤検知し、不要な再起動(Liveness Probe)や切り離し(Readiness Probe)が発生し、かえってシステムを不安定にさせます。
- 改善案:タイムアウト値と閾値の調整
timeoutSeconds は少なくとも 2〜5 秒程度に設定するか、failureThreshold(失敗許容回数)を適切に増やす(デフォルト 3 回)ことで、一時的な遅延を許容するようにします。
Readiness Probe の処理が重すぎる
Readiness Probe は、Pod が稼働している間、設定した間隔(periodSeconds)で絶えず実行され続けます。
- 問題点:パフォーマンスへの悪影響
もし Readiness Probe の中で重い SQL クエリや外部 API への同期リクエストを行っていると、Probe 自体がアプリケーションのリソースを浪費し、本来のユーザトラフィック処理を阻害することになりかねません。
- 改善案:チェック処理の軽量化
Readiness Probe のチェック処理は極力軽量に保つべきです。もし重いチェックが必要な場合は、バックグラウンドで非同期にチェックを行い、Probe のエンドポイントはその結果(フラグやキャッシュされたステータス)を返すだけにする設計パターンを検討します。
まとめ
Kubernetes の Probe はアプリケーションの可用性と信頼性を維持するための機能で、以下の 3 種類があります。
- Liveness Probe:アプリケーションが「死んでいないか」を監視し、異常時は 再起動 して復旧を試みる
- Readiness Probe:アプリケーションが「準備できているか」を監視し、準備未完了時は トラフィックを遮断 してエラーを防ぐ
- Startup Probe:アプリケーションが「起動するまで」他の Probe を待機させ、起動中の誤検知による再起動ループ を防ぐ
これらを適切に組み合わせることで、Kubernetes の Self-healing 機能を最大限に引き出し、運用負荷を下げつつ、安定したサービス提供が可能になります。まずはシンプルな設定から開始して、アプリケーションの特性に合わせて調整していくことをお勧めします。