ELB用のSorryサーバをCloudFormationで構築 – Gezarで一発「ごめんなさい」

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

elb-failover

よく訓練されたアップル信者、都元です。以前、Amazon ELBでSorryサーバへのフェイルオーバーを実現するというエントリにて、ELB配下に正常なインスタンスが1つも無くなった時にSorryページを表示する方法をご紹介しました。

その後、Route53のヘルスチェックにELBを指定できるようになったり *1、フェイルオーバーの機能は順次強化されてきています。

このRoute53のフェイルオーバー先にはS3を指定できます。S3の可用性は非常に高いため、もうWebシステムのフェイルオーバーは完璧。…かと思いきや、実はそうでもありません。

  1. まずRoute53を使わない場合はどうしようもありません。まぁ、使えよって話ですが。
  2. S3は「あらゆるパスへのリクエストに対して同じコンテンツを返す」ということができません。強引にやろうとするとリダイレクトをする、という解決策になってしまいます。理想としては、URLはそのままコンテンツはSorryページを表示することです。
  3. S3は「503 Service Temporarily Unavailable」ステータスを返すことができません *2。しかし、Sorryページは200ステータスで返してはいけません。SorryページをGoogleにインデックスされたら、マズいですよね。

などなど。S3は、Sorryページのホスティングに使うとなると、正直まだもう一歩踏み込みが足りない気がしています。というわけで、以前ご紹介したELBフェイルオーバーのパターンは未だに有効な手段と言えます。

とは言え、先にご紹介したELBフェイルオーバーパターンは、少々のスクリプトの実装が必要ですし、気軽に使いづらいですよね。

Gezar(下座ar=ゲザる人)

惚れさせ352 「好敵手」

今さらミサワってちょっと古いっすか。古いっすね。閑話休題。この仕組みをCloudFormationテンプレートにしてみました。名付けてGezar。有事の際には、ユーザの皆様に、下座っといてくれます。

さて、ではGezarのデモをご覧下さい。

準備

まず、GezarはVPC環境が前提です。デフォルトVPCでも構いません。非VPC環境でのご利用を希望される場合等、カスタマイズについてはお問い合わせ下さい。

まず、Sorryページのコンテンツを用意します。画像やCSS等を使っても構いません。主体となるHTMLのファイル名はsorry.htmlとしてください。そして、S3のバケットを新規作成してこれらのコンテンツをアップロードします。このバケットの内容が、Sorryサーバの/var/www/html内に展開されることをイメージして、ディレクトリ構成等は工夫してください。

とりあえずデモ用に、こんなコンテンツを用意しました。

2013-10-17_1050

https://cm-sorry.s3-ap-northeast-1.amazonaws.com/sorry.html

デモ環境を構築する

続いて、そのVPC環境内に、ELBとWebサーバを構築します。各々頑張って構築していただいても構いませんが、面倒ですよね。というわけで、Gezar本体も含めてテスト環境を一発で構築するCloudFormationテンプレートも用意しておきました。

Gezarのデモを起動

1ページ目では特に記述変更する必要はありませんので、Continueで次にどうぞ。パラメータには、ECのキーペア名を与えてください。8分ほどでスタックが完成(CREATE_COMPLETE)すると思いますので、出来上がったELB *3にアクセスしてみてください。Amazon Linuxのwelcomeページが表示できたでしょうか。

2013-10-17_1148

Gezarの単体起動

ちなみに、上記はあくまでもデモ環境を構築するテンプレートです。本格的な検証用や本番用のGezar構築は下記のリンクから。同様に、1ページ目では特に記述変更する必要はありませんので、Continueで次にどうぞ。

Gezarを起動

必要なパラメータとして必要なのは以下の通りです。

  • SorryBucketに、Sorryコンテンツをアップロードしたバケット名を指定してください。
  • VpcIdに、対象となるELB及びGezarインスタンスが属するVPCのIDを指定してください。
  • SubnetIdに、Gezarインスタンスを立ち上げるサブネットのIDを指定してください。
  • LoadBalancerNameに、対象となるELB名を指定してください。
  • HealthcheckPathに、対象となるELBがWebサーバを監視しているヘルスチェックURLを指定してください。
  • InstanceTypeに、Gezarインスタンスのインスタンスタイプを指定してください。
  • KeyNameに、GezarインスタンスのSSHキーペア名を指定してください。

検証

さて、デモ用のスタックが出来上がったら、早速検証してみましょう。まず、ELBのステータスとして、1つのサーバのうち1つがヘルスチェックを通っていることを確認します。

2013-10-17_1203

その上で、WebServerにログイン *4し、サーバ異常のシミュレーションとして、httpdを落としてみます。

$ sudo service httpd stop
Stopping httpd:                                            [  OK  ]

これにより、しばらくするとWelcomeページではなくメンテナンス中を告げるページが表示されるようになります *5。ルート/だけでなく、/foo/foo/bar等のパスでも同様のページが返ることも確認してください。

2013-10-17_1221

また、これらのページではHTTPステータス200ではなく、503を返していることも確認できます。

$ curl -X GET -I http://XXXX.region.elb.amazonaws.com/foo/bar
HTTP/1.1 503 Service Temporary Unavailable
(略)

ELBは2台中1台が正常稼働している、というステータスになっています。障害が起きたWebサーバに加え、Gezarが入り込んだ形です。

2013-10-17_1220

では、再びヘルスチェックが成功するようにします。

$ sudo service httpd start
Starting httpd:                                            [  OK  ]

これにより、しばらくするとメンテナンスページからWelcomeページに戻ることが確認できるでしょう。

さて、以上の状況で、裏では何が起きていたのか確認しましょう。Gezarのログは/var/log/messagesに出力されます。

Oct 23 08:24:50 ip-X-X-X-X logger: gezar [DEBUG] 1 healty host(s) found on gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:25:02 ip-X-X-X-X logger: gezar [DEBUG] 1 healty host(s) found on gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:25:13 ip-X-X-X-X logger: gezar [DEBUG] healthy host not found on gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:25:13 ip-X-X-X-X logger: gezar [INFO] registering gezar: i-XXXXXXXX to gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:25:14 ip-X-X-X-X logger: gezar [INFO] gezar was registered successfully
Oct 23 08:25:25 ip-X-X-X-X logger: gezar [DEBUG] healthy host not found on gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:25:37 ip-X-X-X-X logger: gezar [DEBUG] healthy host not found on gezar-dem-LoadBala-XXXXXXXXXXXX
(略)
Oct 23 08:26:46 ip-X-X-X-X logger: gezar [DEBUG] healthy host not found on gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:26:57 ip-X-X-X-X logger: gezar [DEBUG] healthy host not found on gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:27:09 ip-X-X-X-X logger: gezar [DEBUG] 1 healty host(s) found on gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:27:09 ip-X-X-X-X logger: gezar [INFO] deregistering gezar: i-XXXXXXXX from gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:27:09 ip-X-X-X-X logger: gezar [INFO] gezar was deregistered successfully
Oct 23 08:27:21 ip-X-X-X-X logger: gezar [DEBUG] 1 healty host(s) found on gezar-dem-LoadBala-XXXXXXXXXXXX
Oct 23 08:27:32 ip-X-X-X-X logger: gezar [DEBUG] 1 healty host(s) found on gezar-dem-LoadBala-XXXXXXXXXXXX

以前のエントリでご紹介したログと、基本的に一緒ですね。

まとめ

というわけで、今回はCloudFormationでSorryサーバを立ててみました。既存システムがVPCベースで、ELBを使っているのであれば、組み込みは一瞬です。是非ご活用頂ければ。

ちなみに、このような「公開部品」というのは、一度リリースされたら(よほどの事がない限り)該当URLにてほぼ恒久的にアクセスできることが重要です。何か変更が必要になったら、バージョン番号を繰り上げ、別のURLから利用する、という方針が必要です。例えば、公開されたライブラリが、Maven RepositoryやRubyForgeやCPANから突然消えてしまったら、世の中の多くのプロダクトが利用できなくなってしまいますね。このCloudFormationテンプレートについても、同じようなものだと認識している次第です。

今後弊社が公開していくCloudFormationテンプレートでは、このようなポリシーに従って、多くの人に安心して安定的に使って頂けるように心がけたいと思っています。

脚注

  1. Amazon Route53の新機能 ELBをHealth Checkのターゲットにしてみた
  2. 意図せず起こる本当の障害時を除く。
  3. StackのOutputsにURLがあります。
  4. 接続コマンド例は、StackのOutputsにあります。
  5. 即座に切り替わるわけではなく、数十秒のダウンタイムが発生します。その間にELBにアクセスしてしまうと、OSその他にDNSのネガティブキャッシュが入ってしまうことがあります。その場合、Sorryページが出るまでに大きな時間が掛かっているようにも見えてしまいますが、実運用前にはその辺りも検証して頂くとよろしいかと。