2026年7月25日

2026年7月25日

Varnish のヘルスチェック設定方法|probe の書き方・状態の確認・障害時に古いキャッシュで返す方法

Varnish のヘルスチェックは、VCL に probe を定義してバックエンドに割り当てるだけで動きます。定期的にバックエンドへリクエストを送り、失敗が続いたサーバーを「sick(異常)」として振り分けから外す仕組みです。この記事では、WordPress をバックエンドにした場合の probe の書き方、ヘルスチェック用ページの作り方、varnishadm や varnishlog での状態確認、さらにバックエンドが全滅したときに古いキャッシュで応答を続ける設定までを順に説明します。

なお、オープンソースの Varnish Cache は、2025年9月の告知を経て Vinyl Cache に改称しました。2026年10月時点では、Varnish Software が Vinyl Cache をもとにした配布物を Varnish Cache の名前で提供しています。VCL の書き方は共通ですが、パッケージ名・コマンド名・設定ファイルの場所は入手した配布物で異なる場合があります。この記事は Varnish Cache の名前(varnishd・varnishadm・/etc/varnish/default.vcl)で説明するので、ほかの配布物を使っている場合は、その配布元のドキュメントで読み替えてください。

Varnish のヘルスチェックの仕組み

Varnish のヘルスチェックは、バックエンドに対して能動的にリクエストを送る方式です。利用者からのリクエストの成否とは関係なく、決められた間隔で probe が送られ、その結果の履歴で健全かどうかが判定されます。

判定に使う主なパラメーターは次の4つです。

  • .interval:probe を送る間隔
  • .timeout:1回の probe の応答を待つ時間
  • .window:判定に使う直近の probe の回数
  • .threshold:window の中で何回成功していれば健全とみなすか

たとえば window が 5、threshold が 3 なら、「直近5回のうち3回以上成功していれば healthy」という判定になります。1回の失敗ですぐ外れるわけではないので、一時的な遅延で振り分けが揺れるのを防げます。逆に、障害が起きてから外れるまでには数回分の interval がかかることも覚えておきます。

手順1:ヘルスチェック用のページを用意する

probe の送り先としてトップページを使うこともできますが、WordPress のトップページはプラグインやテーマの処理を通るため重く、キャッシュプラグインの影響で DB が落ちていても 200 を返すことがあります。DB 接続まで確認できる軽いページを用意するのがおすすめです。

WordPress のルートディレクトリ(wp-load.php と同じ場所)に healthz.php を置く例です。

<?php
// healthz.php:WordPressを最小限だけ読み込み、DB接続を確認する
define( 'SHORTINIT', true );
require __DIR__ . '/wp-load.php';

header( 'Cache-Control: no-store' );
header( 'Content-Type: text/plain; charset=utf-8' );

global $wpdb;
if ( '1' === $wpdb->get_var( 'SELECT 1' ) ) {
    http_response_code( 200 );
    echo 'ok';
} else {
    http_response_code( 503 );
    echo 'db error';
}

SHORTINIT を定義すると、WordPress は DB 接続などの最小限の初期化だけを行い、プラグインやテーマを読み込みません。そのため probe のたびに重い処理が走るのを避けつつ、PHP と DB の両方が動いているかを確かめられます。DB に接続できない場合、WordPress はエラーページを返して処理を止めるため、いずれにしても 200 以外の応答になり、Varnish 側では失敗として扱われます。

このファイルはサイト内部の情報を返しませんが、外部から叩かれる必要もありません。Web サーバー側で、Varnish のアドレスからのアクセスだけを許可しておくとよいでしょう。ファイルを追加する前には、念のためサイトのバックアップを取っておきます。

手順2:VCL に probe を定義する

既存の VCL ファイル(多くの環境で /etc/varnish/default.vcl)をバックアップしてから編集します。バックエンドが2台ある例です。

vcl 4.1;

import directors;
import std;

probe wp_health {
    .request =
        "GET /healthz.php HTTP/1.1"
        "Host: example.com"
        "User-Agent: varnish-probe"
        "Connection: close";
    .expected_response = 200;
    .interval = 5s;
    .timeout = 2s;
    .window = 5;
    .threshold = 3;
    .initial = 3;
}

backend web1 {
    .host = "10.0.0.11";
    .port = "8080";
    .probe = wp_health;
}

backend web2 {
    .host = "10.0.0.12";
    .port = "8080";
    .probe = wp_health;
}

sub vcl_init {
    new wp_cluster = directors.round_robin();
    wp_cluster.add_backend(web1);
    wp_cluster.add_backend(web2);
}

sub vcl_recv {
    set req.backend_hint = wp_cluster.backend();
}

ポイントを補足します。

  • 単純に URL だけを指定する .url = "/healthz.php"; という書き方もあります。ただし、WordPress は Host ヘッダーを見てサイトを判断し、想定外のホスト名だとリダイレクトを返すことがあるため、上の例のように .request で Host ヘッダーを含めたリクエスト全体を書くほうが確実性の高い判定になります。
  • .initial は、起動直後に「何回分成功した扱いで始めるか」を決めます。省略時は threshold より1少ない値になるため、起動直後は1回成功するまで sick 扱いです。上の例では threshold と同じ 3 にして、起動直後から healthy 扱いで始めています。バックエンドが落ちたまま Varnish を再起動すると、最初の数回の probe が失敗するまでは振り分けが続く点とのトレードオフです。
  • directors.round_robin() などのディレクターは、sick になったバックエンドを自動で振り分けから外します。

構文チェックと反映

VCL は反映前にコンパイルして確認できます。

# 構文チェック(コンパイル結果が出力されればOK)
sudo varnishd -C -f /etc/varnish/default.vcl > /dev/null

# 稼働中のVarnishに新しいVCLを読み込ませる
sudo varnishreload

varnishreload がない環境では、varnishadm vcl.load と vcl.use で切り替えるか、systemd の reload を使います。コマンドの有無はパッケージやバージョンで異なります(2026年10月現在)。

手順3:ヘルスチェックの状態を確認する

現在の状態は varnishadm で確認します。

sudo varnishadm backend.list
sudo varnishadm backend.list -p

backend.list は各バックエンドが healthy か sick かを一覧表示します。-p を付けると probe の詳細と直近の成否の履歴が表示されるので、「たまに失敗している」状態も読み取れます。

probe の結果をリアルタイムで追うには varnishlog を使います。

sudo varnishlog -g raw -i Backend_health

1行ごとに、どのバックエンドへの probe が成功したか、応答時間はどれくらいか、状態が変わったか(Back healthy / Went sick など)が記録されます。sick になり続ける場合は、次の順に確認すると原因を絞り込めます。

  1. Varnish のサーバーから curl -i -H 'Host: example.com' http://10.0.0.11:8080/healthz.php を実行し、200 が返るか
  2. 応答に timeout 以上の時間がかかっていないか(重いページを指定していないか)
  3. 301 や 302 のリダイレクトが返っていないか(Host ヘッダーや HTTPS 強制の設定が原因になりやすい)
  4. ファイアウォールで Varnish からバックエンドのポートへの通信が許可されているか

メンテナンス時に手動で切り替える

バックエンドを1台ずつ更新するときは、手動で状態を変えられます。

# web1を振り分けから外す
sudo varnishadm backend.set_health web1 sick
# probeによる自動判定に戻す
sudo varnishadm backend.set_health web1 auto

作業後に auto へ戻し忘れると、そのバックエンドは外れたままになります。作業手順書に戻す手順まで含めておくと安全です。

手順4:バックエンドが全滅したときに古いキャッシュで返す

全バックエンドが sick になると、Varnish は通常 503 を返します。キャッシュ済みのページがあれば、期限切れでもそれを返して表示を続ける「grace」の仕組みを使えます。次の vcl_recv は、手順2の vcl_recv を置き換える内容です(vcl_backend_response は既存の処理があれば、その中に1行を加えます)。

sub vcl_recv {
    set req.backend_hint = wp_cluster.backend();

    # バックエンドが健全なときは、期限切れキャッシュの利用を短く抑える
    if (std.healthy(req.backend_hint)) {
        set req.grace = 10s;
    }
}

sub vcl_backend_response {
    # 期限切れ後も最大6時間はキャッシュを保持しておく
    set beresp.grace = 6h;
}

beresp.grace で期限切れ後もキャッシュを保持する時間を決め、バックエンドが健全なときだけ req.grace を短くします。こうすると、平常時は新しいページを取りに行き、障害時だけ古いページで応答するという動きになります。この書き方は Varnish の公式ドキュメント(grace の項)の例と同じ考え方です。

req.grace は Varnish 4.0 で一度なくなり、6.0.1 の変更履歴で「復活した」と記載されている変数です。それより前の版では使えずコンパイルエラーになるため、古い版を使っている場合は、まず現行版への更新を検討してください。反映前に、手順2の varnishd -C で構文を確かめます。ログイン中のユーザーやカート・決済のページは通常キャッシュしない設定にしているはずなので、grace の効果が及ぶのはキャッシュ対象の公開ページに限られます。

grace はあくまで障害時の延命策です。ヘルスチェックの状態変化を監視ツールで検知し、早めに通知を受け取れるようにしておくことが本来の対策になります。

まとめ

  • Varnish のヘルスチェックは VCL の probe で定義し、バックエンドに .probe で割り当てる
  • interval・timeout・window・threshold で、判定の速さと揺れにくさのバランスを決める
  • WordPress には SHORTINIT を使った軽いヘルスチェック用ページを用意し、Host ヘッダー付きの .request で叩く
  • 状態は varnishadm backend.list -p と varnishlog -g raw -i Backend_health で確認する
  • grace を設定すると、全バックエンドが落ちたときにキャッシュ済みページで応答を続けられる

関連する記事:

お気軽にご相談ください

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