AWSを使ってソーリーサーバを構築しました。割と便利だと思う…。
とてもお久しぶりです。
恵比寿のITベンチャーでサービス運営やっています。
仲間募集中です。ご興味ある方はTwitterなどでご連絡ください。
今回はAWSを使って、わりと便利なソーリーサーバを構築しましたというお話です。
構成は下の図のようになっています。
恵比寿のITベンチャーでサービス運営やっています。
仲間募集中です。ご興味ある方はTwitterなどでご連絡ください。
今回はAWSを使って、わりと便利なソーリーサーバを構築しましたというお話です。
構成は下の図のようになっています。
通信フローとしては、まずエンドユーザがELBにアクセスします。 このELBは既存のWebサービスやWebサイトをバランシングしていたものです。 諸事情によりメンテナンスしたり、ドメインを畳むことになったという話を想定しています。
そのELBに接続されていたWebサーバやアプリケーションサーバの代わりにソーリーサーバを接続します。 するとエンドユーザはソーリーサーバにアクセスしてきますよね。
ソーリーサーバはリクエストを受けたら、各ドメインに対応させたいCloudFrontへリクエストをパスします。 CloudFrontはS3のコンテンツを返すのですが、このS3に静的なソーリーページを格納しておきます。 それにより、ドメインにアクセスしてきたエンドユーザにソーリーページを見せることができます。
ポイントはソーリーサーバとCloudFrontですがやってることは簡単です。 まず、ソーリーサーバはただのNginxです。 proxy_pass を使って、特定ドメインに来たリクエストを対応するCloudFrontのドメインへパスします。 その設定は、/etc/nginx/conf.d/virtual.conf に書きました。
server {server_name example.com;if ($http_x_forwarded_proto != https) {location / {}
上記の server ディレクティブのかたまりを、ソーリーページの数だけ用意します。 1ドメイン1種類のページでよければ、3ドメインなら3つのディレクティブになります。
if文のおかげで、自動でHTTPSになります。
if文のおかげで、自動でHTTPSになります。
しかしここで一つ問題があります。 ELBごとにヘルスチェックエンドポイントが違うのです。 なのでそのままではそもそもNginxがヘルスチェックに合格せず、ELBがNginxにリクエストを渡してくれません。
それはNginxの素敵機能 empty_gif を使って解決します。 今回は /etc/nginx/nginx.conf に以下のように書きました。
http {}
これにより、どんなパスへのアクセスに対しても 1ピクセルのgifイメージを生成して返します。 そのおかげで、ELBのどんなヘルスチェックパスも合格し、めでたく InService になることができます。
残りは CloudFront ですね。
CloudFrontはソーリーページごとにインスタンスを用意する必要があります。
理由はカスタムエラーページを利用したいからです。
CloudFrontのカスタムエラーページでは、特定のHTTPステータースコードの場合、任意のステータスコードに変更することができ、さらに任意のコンテンツを表示させることができます。
これを使って、全ての403アクセスを404へ変更して、ついでにソーリーページのhtmlを表示させちゃうことができます。
理由はカスタムエラーページを利用したいからです。
CloudFrontのカスタムエラーページでは、特定のHTTPステータースコードの場合、任意のステータスコードに変更することができ、さらに任意のコンテンツを表示させることができます。
これを使って、全ての403アクセスを404へ変更して、ついでにソーリーページのhtmlを表示させちゃうことができます。
なんで403にするかというと、CloudFront + S3 でのコンテンツ配信方式で、ページが存在しない場合、CloudFront側が 403 Access Denied を返すからです。
これを404+ソーリーページにすることで、どんな存在しないURLにアクセスが来ても、自分が用意した404用のhtmlが表示されることになります。
これを404+ソーリーページにすることで、どんな存在しないURLにアクセスが来ても、自分が用意した404用のhtmlが表示されることになります。
ただし、「正しいソーリーページのパス」にアクセスされると、ステータスコードは200になってしまいます。
よほどの物好きなエンドユーザ意外はそんなことしないので、気にしないことにしました。
よほどの物好きなエンドユーザ意外はそんなことしないので、気にしないことにしました。
Nginxのコンフィグの書き方でもうちょっとCloudFrontのインスタンスを減らせる気もしますが、料金体系的にデータ転送量とリクエスト数のみで、インスタンス数による固定料金はないので、管理は面倒くさいですがこれでいいかなという感じです。
あ、あと、ACMを使って無料証明書を取得してCloudFrontに登録しています。
そのために、 sorry.example.com のような、ソーリーページ専用サブドメインを用意して、 それのワイルドカード証明書をACMから発行させてもらっています。
メールはクラスメソッドさんのブログなどを参考にしつつ、SES と S3を使って、S3 バケットにメールを受信できる様にすれば 既存のメールサーバをいじる必要がなくてよいです。
ところで何が便利なの?
まず、ステータスコードを任意に指定できます。404とか、500とか。それから、ソーリーページにhttpsが使えます。労力の割には些細なリターンのような気もしますが…。
NginxのコンフィグはGitで管理してAnsibleなどで配布できます。
1台に全部のソーリーページについて書かなきゃいけないですが、書いてしまえば、1台をマスターサーバにして楽にスケールアウトできます。
マスターサーバのコンフィグに全てのソーリーページの設定が書かれてあるので、ドメインに対して透過的なソーリーサーバが出来上がります。
どのELBにどのサーバを突っ込んでもOKということです。
コメント
コメントを投稿