概要
既存のアプリケーションサーバをファイル等でメンテナンスモードに切り替えるのではなく、メンテナンスモード専用のサーバを構築する方法です。いわゆるソーリーページを返すだけのサーバですね。 LBにメンテナンスサーバを追加して、アプリケーションサーバをLBの分散先から外すことでメンテナンスモードに移行します。
既存のサーバに手を加えずにメンテナンス機能を追加する必要があり構築しました。
実装
といってもNginxの設定のみです。こんな感じです。
server {
listen 80;
root /usr/share/nginx/html;
location = /healthcheck {
empty_gif;
access_log off;
break;
}
error_page 503 @maintenance;
location @maintenance {
internal;
if ($host ~* api) {
return 503 "{}";
}
rewrite ^(.*)$ /503.html break;
break;
}
return 503;
}
それぞれ見ていきます。
ヘルスチェック
location = /healthcheck {
empty_gif;
access_log off;
break;
}
メンテナンスページは503で返しますが、LBからのヘルスチェックは成功ステータスで返してやる必要があります。
empty_gif
はNginxがメモリ上に保持している1x1ピクセルの透過GIFを返すモジュールです。
Module ngx_http_empty_gif_module
メンテナンスページ
error_page 503 @maintenance;
503ステータスを名前付きロケーション @maintenance
に内部リダイレクトしています。
location @maintenance {
internal;
if ($host ~* api) {
return 503 "{}";
}
rewrite ^(.*)$ /503.html break;
break;
}
メンテナンスページの名前付きロケーションです。
内部リダイレクト専用のロケーションなのでお行儀よくinternal
を書いています。internal
が記述されたロケーションは外部から直接アクセスすることはできません。
今回のシステムはホスト名によってJSON APIか通常Webかを判断しており、APIホストへのリクエストであれば503ステータスで空オブジェクトのJSONを返すようにしています。
今回はたまたまそんな感じでしたが、example.com/api/v1/foobar
のようにパスで分岐させているならif ($uri ~* ^/api)
、ちゃんとヘッダをつけてくれるなら if ($http_accept ~* json)
みたいな感じにすればOKです。
そして、すべてのパスに対してメンテナンスサーバを表示させたいのですべてのパスを/503.html
に書き換えています。
503
return 503;
ヘルスチェック以外のすべてのリクエストに対して503を返してメンテナンスページを表示します。
503.html
今回は専用のメンテナンスページを用意したので、/usr/share/nginx/html/503.html
にHTMLを置いておきます。