CDNのテストをvarnishtestを使って行おう

インフラのいわなちゃんさん(@xcir)です。

先の記事ではTerraformでAkamaiを運用するということを書きました。
記事中でテストについて触れましたが、ふと考えたらCDNに対してテストを行う事例をあまり聞いたことないなと思いテストツールを公開します。

CDNのテストどうやっていますか?

CDNで複雑な処理を行うようになりテストがより重要なのは疑いもないのですが、あまりCDNに対してテストをということを聞きません。
新規に作成する場合であればCNAME切り替え前にhostsを書き換えてブラウザで確認したり、CLIで行う場合でもcurlで--resolveオプションで200なことを確認するだけというサイトも多そうです。
もちろん、PlaywrightなどでサイトのE2Eテストの一環で行っていたり、PytestやRSpecで行っているサイトもあると思いますが、今回はvarnishtestを使ってCDNのシンプルなUTを行う方法を紹介します。

varnishtestとは

10年ぐらい前にもVarnishでテストコードを書こう!という記事を書いているのでそちらも合わせ読んでほしいのですが、要はVarnishCacheのテストツールです。
非常に細かい部分のテストもできるためか、最近ではHAProxyもvarnishtest(正確には切り出したVTestですが)を使っているようです。

それでいて記述は比較的シンプルです。
弊社はVarnishCacheを長年利用しており、Varnishで処理しているドメインはすべてvarnishtestをテストを行っていることもありCDNに対しても使うのは自然でした。

varnishtestを外部に接続してテストできるようにする

ところがvarnishtestをCDNのテストツールとして使うには一苦労ありました。
そもそもがvarnishのテストツールであり、外部に接続することを(おそらく)想定していません。
接続先をIPアドレスで指定すれば可能ですが実運用で行うには厳しいです。
他にもテストclientがHTTPにしか対応しておらずHTTPSでは接続できないという問題がありました。

これらをどう解決したかというと先に触れたHAProxyです。

これはスクリプトに含まれるexample.netを対象としたサンプル定義です。

実際のテスト定義はこれだけで比較的シンプルです。他のところはhaproxyの設定です。
要はhaproxyにDNSの解決やhttpsでの接続を任せているわけです。

また最初にhostsを書き換えてブラウザでテストする例を挙げましたが、実際にテストを行う場合は本番に反映する前に実施する必要があるわけで接続先を変える必要があります。

Akamaiの場合はStaging/Productionのネットワークがあり、先にStagingに展開した後に接続先を変えてテストを行い問題がなければProductionに展開するのが一般的です。
他のCDNを使う場合でも多くの場合は少し変えたドメインで設定の確認を行い問題がなければ展開する運用が一般的でしょう。

先のHAProxyの設定ではexample.netに接続する定義はなく、その部分は${target}というマクロ定義になっています。
ここに接続先を指定することでCNAME切り替え前のCDN設定、Akamaiであれば異なるネットワークでのテスト、テストの書き方にもよりますがマルチCDNでのテストも可能です。

vtc-external-test

https://github.com/xcir/vtc-external-test

まずは動かしてみる

先ほどのテストサンプルをexample.netに対して接続して行います。

ちなみに拡張子がvtcとなっているのはvarnish test codeの略で、vtcというと実際のテストコードをさします。

試しに200のexpect部分を404にしててみました。
きちんとFAILしていることがわかります。

起動オプション

option 説明 default example
-h help - -
-v verbose表示 - -
-s コンテナに入る - -
-f docker imageのリビルドを行う - -
-n [target name] 接続先をconf.shで定義されたものを利用する default -n stg
-c [connection server] 明示的に接続先を設定する - -c example.net
-o [extra varnishtest option] varnishtestに追加のパラメータを渡す。主にマクロ定義で利用 - -o "-Dmacro=1"
[vtc_file or vtc_dir] vtc(varnish test case)ファイルかvtcが格納されているパスを指定。globや複数指定不可 tests/ tests/example.net.vtc

自分は毎回-cで接続先を指定するのが面倒だったため、次に説明するconf.shで接続先を定義しておいて

./vtc.sh -n prod tests/foo.vtc

といったように利用しています。

conf.sh

重要なのはC_[name]の変数です。
要はこれが接続先なので、Akamaiであれば

と書いておくと未指定の時はstgに接続、prodを指定すれば本番ネットワークに接続という切り替えが可能です。

書き方サンプル

先ほどのサンプルのHAProxy部分は常に固定なのでその部分はコピペしつつclient部分から書くことになります。
なお、次のVarnishのバージョンからincludeが使えるようになる(はず)ので、HAProxy部分を切り出してシンプルに書くことができるはずです。
client部も基本はステータスコードとヘッダ程度しかないのでそこまで難しくはないのですが、いくつか書き方の例をあげます。

Akamaiのデバッグヘッダを利用する

Pragmaで指定することで詳細な情報を得ることができます。

デバッグヘッダを指定することでキャッシュ対象かどうかをテストしています。

もちろん他にもキャッシュキーのチェックも可能です。
Pragmaをフルセットで指定していないのはvarnishtestの制限でヘッダが64行を超えるとエラーとなるからです。

また、割とsensitiveな情報がふくまれることがあるので素のまま出さずに特定のヘッダとセットでないと動かないように設定するのが通常です。

外部コマンドを利用してより詳細なチェックを行う(identify)

最近はサムネイルは動的に作ることが多いですが、縦長や横長画像で意図したサイズに収まっているか、フォーマットは意図している通りかといったテストを行うにはどうすればよいでしょうか?

Dockerfileにコマンド(今回はidentifyを使うのでimagemagick)を追加します。
更新後のvtc.sh初回実行時は-fオプションを付けることでimageが更新されます。

テストのポイントはwrite_body [filename]shell -match "[REGEXP]" {[command]}です。
write_bodyを使うとレスポンスをファイルに書き込むことができ、shellで任意のコマンドを実行可能です。

ホスト名を変えたい

本番ドメインはexample.netでステージングドメインはexample-stg.netの場合でvtcは同じものを使いたい場合はマクロを使うと実現できます。

${sfx}がマクロで、後はvtc.sh実行時に-Dsfx='[replacement]'を指定します。

一点注意があるのは未指定の場合はそのままの文字列(${sfx})が残るので、-stgが不要な時でも指定が必要になります。

vtcは様々な機能があるので詳細はこちらを参照してください。

 

テスト実行時の注意点

当たり前ですがCDNはキャッシュをします。
まずテストを行う場合はステージングネットワークだったり別ドメインだと思いますのでパージを行うなどしてテストを行える状態にしましょう

最後に

CDNに複雑なコードを置く以上テストを十分する必要があります。
かといってhosts書き換えでがんばったりするのはなかなか辛いですし一つの案としてvarnishtestを利用したテスト方法を紹介しました。
今回はCDNをテストするがテーマでしたが、もちろんCDN以外でもテストは可能なのでちょっとしたHTTP/S経由でUTを行いたい場合には有用だと考えています。