2026年7月1日

2026年7月1日

KubernetesのLiveness・Readiness・Startup Probeの設定|役割の違いと再起動ループを防ぐ値の決め方

KubernetesのProbeは、コンテナが「生きているか」「リクエストを受けられるか」を定期的に確かめる仕組みです。Livenessは失敗するとコンテナを再起動し、Readinessは失敗するとServiceの振り分け先から外し、Startupは起動が終わるまで他の2つを待たせます。この記事では、3つの役割の違い、YAMLの書き方と各パラメーターの意味、WordPressのようなPHPアプリでの設定例、Probeが原因の再起動ループやサービス断の調べ方を説明します。

内容は、Kubernetesの現行のサポート対象の版(2026年10月現在)で共通して使える項目に絞っています。

3つのProbeの違い

Probe 失敗したときに起きること 確かめたいこと
livenessProbe コンテナを再起動する プロセスが固まっていないか
readinessProbe ServiceのEndpointから外す(再起動はしない) 今リクエストを受けてよいか
startupProbe 成功するまで他のProbeを止める。失敗が続くと再起動する 起動処理が終わったか

いちばん大事なのは、Livenessは「再起動すれば直る状態」だけを検知するという点です。データベースが落ちたときにLivenessが失敗する作りにすると、アプリ側には問題がないのに全Podが再起動を繰り返し、データベースが戻っても起動が重なって復旧が遅れます。外部の依存先の状態は、再起動をしないReadinessで扱うか、アプリ内のエラー処理に任せます。

Readinessは、起動直後だけでなく動作中も判定され続けます。一時的に負荷が高いPodを振り分け先から外し、回復したら戻す、という使い方ができます。

なお、Dockerfileの HEALTHCHECK はKubernetesでは使われません。KubernetesではProbeを別に定義します。

確認方法の種類

  • httpGet:指定したパスとポートにHTTPリクエストを送り、ステータスコードが200以上400未満なら成功です。
  • tcpSocket:指定ポートにTCP接続できれば成功です。中身の処理までは確かめません。
  • exec:コンテナ内でコマンドを実行し、終了コードが0なら成功です。毎回プロセスが起動するため、間隔が短いと負荷になります。
  • grpc:gRPCのヘルスチェックの仕組みに対応したサーバー向けです。

httpGetでは、3xxのリダイレクトも成功として扱われます。WordPressはサイトURLと違うホスト名でアクセスされるとリダイレクトを返すことがあり、その場合は実際のページの表示を確かめないまま成功になることがあります。確かめたい内容に応じて、パスを選ぶか、httpHeaders で Host を指定します。

パラメーターの意味

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 0
  periodSeconds: 10
  timeoutSeconds: 1
  successThreshold: 1
  failureThreshold: 3

上の値はすべて既定値です。

  • periodSeconds:確認の間隔(秒)。
  • timeoutSeconds:応答を待つ時間(秒)。既定の1秒は、負荷がかかったPHPアプリには短すぎることがあります。
  • failureThreshold:何回続けて失敗したら「失敗」とみなすか。
  • successThreshold:失敗の後、何回続けて成功したら「成功」に戻すか。LivenessとStartupでは1しか指定できません。
  • initialDelaySeconds:コンテナ起動から最初の確認までの待ち時間。起動の遅いアプリにはこの値を大きくするより、startupProbeを使うほうが適しています。

再起動までの時間は、おおよそ periodSeconds × failureThreshold です。既定値なら約30秒の間、応答がないか遅い状態が続くと再起動されます。この値が短すぎると、一時的な負荷の山で再起動が起き、残ったPodに負荷が集中してさらに再起動が起きる、という連鎖になります。

WordPress(Apache版イメージ)での設定例

containers:
  - name: wordpress
    image: wordpress:6-php8.3-apache
    ports:
      - containerPort: 80
    startupProbe:
      httpGet:
        path: /healthz.php
        port: 80
      periodSeconds: 5
      failureThreshold: 30
    readinessProbe:
      httpGet:
        path: /healthz.php
        port: 80
      periodSeconds: 10
      timeoutSeconds: 3
      failureThreshold: 3
    livenessProbe:
      tcpSocket:
        port: 80
      periodSeconds: 20
      timeoutSeconds: 5
      failureThreshold: 3

考え方は次のとおりです。

  • startupProbe:5秒 × 30回 で、起動に最大150秒の猶予を与えます。初回起動でファイルの展開に時間がかかる場合も、Livenessに再起動されません。
  • readinessProbe:PHPが動いてデータベースに接続できるかを見ます。データベースが落ちたらPodは振り分け先から外れますが、再起動はされません。
  • livenessProbe:Apacheがポートで応答するかだけを見ます。PHPやデータベースの問題で再起動しないよう、軽い確認にとどめています。

トップページをProbeのパスにすると、確認のたびにWordPress全体が読み込まれ、プラグインの処理やデータベースへの問い合わせが走ります。Podが多いほど負荷が積み上がるため、確認用の軽いファイルを用意します。例えば次のような healthz.php です。WordPress本体を読み込まずに、データベースへの接続だけを確かめます。

<?php
// healthz.php: Readiness用。WordPressは読み込まず、DB接続だけを確認する
$host = getenv( 'WORDPRESS_DB_HOST' );
$user = getenv( 'WORDPRESS_DB_USER' );
$pass = getenv( 'WORDPRESS_DB_PASSWORD' );
$name = getenv( 'WORDPRESS_DB_NAME' );

mysqli_report( MYSQLI_REPORT_OFF );
$db = @mysqli_connect( $host, $user, $pass, $name );
if ( ! $db ) {
	http_response_code( 503 );
	exit( 'db-unavailable' );
}
mysqli_close( $db );
http_response_code( 200 );
echo 'ok';

このファイルはエラーの詳細を返さず、外部から呼ばれても情報が漏れないようにしています。それでも外部に公開する必要はないため、Ingressやウェブサーバーの設定で外からのアクセスを拒否しておくと安全です。パスワードをファイル(_FILE 形式の変数)で渡している構成では、読み取り方をそれに合わせて変えてください。

PHP-FPM版のイメージを使い、nginxを別コンテナにしている場合は、PHP-FPMのコンテナにはtcpSocketでポート9000を確かめるLiveness、nginxのコンテナにはhttpGetのReadinessを置く、という分け方が一般的です。

失敗したときの調べ方

Probeが原因の不具合は、次の順に見ていきます。

kubectl get pods -l app=wordpress
kubectl describe pod <Pod名>
kubectl logs <Pod名> --previous
kubectl get endpointslices -l kubernetes.io/service-name=wordpress

describe pod の Events に、失敗の理由が記録されます。よく見るものを起きやすい順に挙げます。

  1. **Readiness probe failed: ... context deadline exceeded などのタイムアウト**:応答が timeoutSeconds に間に合っていません。負荷の高い時間帯だけ出るなら、timeoutSeconds を延ばすか、Probeのパスを軽くします。
  2. **Liveness probe failed: HTTP probe failed with statuscode: 500 などの異常なステータス**:アプリが動いていてもエラーを返しています。Livenessで見ている内容が重すぎないか、外部の依存先を含んでいないかを見直します。
  3. **connection refused**:ポートがまだ開いていないか、ポート番号の誤りです。起動直後だけなら、startupProbeがないか猶予が短すぎます。
  4. **RESTARTS が増え続ける**:--previous で前回のコンテナのログを見ると、Probeによる再起動か、アプリ自身の異常終了かを見分けられます。Events に「Container ... failed liveness probe, will be restarted」があれば前者です。

Readinessが失敗しているPodは、EndpointSliceの一覧で準備未完了として扱われ、振り分け先から外れます。全Podが外れると、Service経由のアクセスはすべて失敗し、Ingressなどから503が返ります。サービス断が起きたときは、まず全Podが同時にReadinessに失敗していないか(共通の依存先が落ちていないか)を確かめてください。

まとめ

  • Livenessは再起動、Readinessは振り分けからの除外、Startupは起動完了までの猶予。目的に合わせて使い分ける。
  • Livenessに外部の依存先を含めない。データベースの状態はReadinessで扱う。
  • 既定の timeoutSeconds: 1 はPHPアプリには短いことがある。再起動までの時間は periodSeconds × failureThreshold で見積もる。
  • 起動の遅いアプリは initialDelaySeconds を延ばすよりstartupProbeを使う。
  • Probeのパスは軽く、外部に公開しない。失敗時は describe pod の Events と logs --previous で原因を分ける。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲