varnishのresolves to too many addressesを解決する

TLDR

varnishの仕様

varnishでは基本的にバックエンドとの対応付けは1対1が基本であり、複数IPなどには対応することができない。 (注:ドメインなどを記載した場合はコンパイル(起動)時にDNSを引いた際のIPアドレスを利用しているっぽい) つまりbackendに"s3-ap-northeast-1.amazonaws.com"のような複数のAレコードを持つようなものを指定しようとすると、resolves to too many addressesと怒られる1

varnishのドキュメントやggってみるとgotoというライブラリが出てくるが、これはシェアウェアのバンドルなので利用できない。

調べてみるとgotoとは別にlibvmod-dynamicというモジュールがあったのでこちらを利用する。 libvmod-dynamicはバックエンドに接続する際にDNSを引くという動作をする。つまりDNSレコードが変わるような環境でも利用できる。 また、複数のレコードがある場合にも問題なく利用できる。

環境

OS: Amazon Linux 2

varnish: 6.0.10(yumからインストール)

構成としてはALBでSSL終端しVarnishが受けて各種バックエンドやS3などに振り分けるといったもの(画像書くのが面倒だった)。 varnishはリバースプロキシとして利用しており読み替えでs3を呼び出す。 s3は静的ファイルが主においてありcssなどを要求する際に利用される。

s3のDNSのAレコードは8つあり、しかもおよそ5秒ごとに変更されるためTTLを長めにしてしまうとアクセスできなくなるので注意(2022/10/28現在)。

構築

  1. 必要なライブラリを追加する sudo yum install getdns-devel varnish-libs-devel
  2. リポジトリにアクセスし、varnishのバージョンと同じブランチを選択する。今回は6.0。
  3. CodeをクリックしDownload ZIPのリンクをコピー
  4. wget する。今回はwget https://github.com/nigoroll/libvmod-dynamic/archive/refs/heads/6.0.zip
  5. unzip unzip 6.0.zip
  6. ディレクトリに入りmake&install
./autogen.sh
./confugure
make
  1. 問題なくmakeできたらsudo make install
  2. 完了を確認したらvclの設定へ

varnish vmod-dynamicの使い方

基本的にはsrc/vmod_dynamic.vccに書いてあるのでそれを見て設定する。 今回は以下のように設定した。

s3.vcl

import dynamic;

probe www_probe {
    .window = 5;
    .initial = 7;
    .threshold = 3;
    .interval = 5s;
}

acl www_acl {
    "0.0.0.0/0";
}

sub vcl_init {
    new s3 = dynamic.director(
        port = "80",
        probe = www_probe,
        whitelist = www_acl,
        ttl = 1s);
}

default.vcl

set req.backend_hint = s3.backend("s3-ap-northeast-1.amazonaws.com");

ここで重要なのは、whitelistの設定である。

vmod_dynamic.vccには「ACLに一致する名前解決結果のみが使用される」と記載があるので、これを記載しないと動作しないようである。 今回はAWSがAWSIPからランダムに(実際はラウンドロビンか何か)IPを変更しているため設定値を0.0.0.0/0としている2が、利用IPの範囲が決まっていれば192.168.0.0/31のように範囲指定すべきである。 設定例では"192.168"/24;となっているのだがこの場合は"192.168.0.0/24"となるんだろうか…?この書き方なら/16が適切な気がするんだけども。

また、TTLは基本的にはDNSの設定値と同様か少し小さい値を設定しておけば良い。 今回はAWSの設定に振り回されないように1secにしてあるが、普通は5mでも1hでもいいと思う。

反映

sudo systemctl restart varnishで反映させる 再起動してもいいかも。

気になること

  • ドキュメント記載の"192.168"/24;を設定したときの許可範囲
  • www_probeの各パラメータの適切さがそもそもわかっていない
    • varnishのドキュメントとlibvmod-dynamicのドキュメントではinitialの定義が違うんだけどlibvmod-dynamicが間違ってる?

varnishわからないことだらけなので誰か教えて下さい。。。


  1. ちなみに2022/10/20辺りではこのようなエラーが出なかったのだが、varnishがアップデートしたのかAWSDNSが変わったのか原因はわからなかった
  2. ドキュメントには0.0.0.0/0にするとIPv4に限定できると書いてある