かみやんの技術者ブログ

主にプログラムの話です

AWSでの3種類のネットワーク構成

先日、アイビスのサーバの引っ越しがありました。引っ越しは毎度毎度大変です。データセンターに置いていたサーバ群ですが、大変なのでやりたくないですが、引っ越しをせざる負えない事情がありまして、データセンターからAWSサーバ40台の引っ越しをしました。
AWSは、受託開発では経験があるものの自社サービスでは初めて。僕も大急ぎで勉強して、晴れてAWSデビューです。

システム開発は、企画、要件定義、設計、実装、試験、運用とありますが、どれも楽しいですね。ものづくり万歳!。今回は、ネットワークアーキテクチャのお話です。ネットワークアーキテクチャを考えるとき、拡張性はあるか?可用性はあるか?負荷に耐えられるか?運用しやすいか?コストを下げるにはどうするか?と色々考える必要があって楽しいですね。

AWSの話の前に、まずは一般的な三層モデルの解説から。

クライアント(Webブラウザまたはアプリ)からApacheへ接続して、その後ろにAP(アプリケーションサーバ)があり、APからDBに接続という形。うちの自社製品は基本JavaなのでWebアプリケーションはTomcat上で動いています。
Apache-Tomcat連携しているのは、本来は静的コンテンツはApacheが返し、動的コンテンツはAPが返すためであり、一般に静的コンテンツはTomcatが返すよりApacheが返す方が速いためです。
また、Apacheのバーチャルホスト機能を使うためにも先頭にApacheがいます。バーチャルホスト機能は、複数のWebサービスを1台のホストで処理するために必要で負荷が高くないサービスが複数ある場合は、Apache1台に複数サービスを集約してコストを削減します。例えばDNSサーバの設定で、www.example1.jpとwww.example2.jpの2つのドメインを同じIPに設定し、そのホストにApacheを立てて、ブラウザからのリクエストのドメインを見て、振り分け先のAPを切り替えるという形で使います。
3つ目の理由として、mod_rewriteがあります。mod_rewriteは機能が強力過ぎて悪魔のようなモジュールと一部で言われていますが、URLを正規表現でマッチさせて、マッチしたらAPへフォワードするときにURLを書き換えて転送させることができます。例えば、

http://d.hatena.ne.jp/kamiyan2/20121006

というリクエストをフロントのApacheが受け付けたときに、正規表現で「kamiyan2」と「20121006」をマッチさせて、

http://d.hatena.ne.jp/entry.jsp?uid=kamiyan2&eid=20121006

のようにURLを書き換えて、APに転送させることができます。
RESTfulが流行っていますが、それ以前に検索に引っかかりやすくするために同じリソースを指すならPATHに含めましょうというところですね。
4つ目の理由として、図に「LB」と書いてあるようにロードバランサとしてのApacheですね。mod_proxy_ajpとかmod_proxy_http、mod_jkなどを使ってAPを増やして分散処理をします。

その1:最小サービス(AP + DB)


AWSへの引っ越しで最も負荷の小さいサービスは、EC2を1台、RDSを2台(他のサービスと共有)としました。しかもEC2は、マイクロインスタンス(月額約$19)。DBは、RDSのミディアムインスタンス(月額約$172)。RDSミディアムインスタンスは負荷の割にオーバースペックになっていますが、これは他のサービスとの共有で使うために大き目になっています。もう1台RDSは、リードレプリカです。このリードレプリカには、APからのアクセスはしておらず、単なるバックアップ目的です。ファイルにバックアップを取って運用だと障害時に復旧に時間がかかるのでレプリケーションしています。年々サーバ側のデータは増えていく時代なので、バックアップからの復旧前提のシステムは、やるべきではないでしょう。
ちなみに上図のアイコンはAmazonが配布しているアイコンで、ネットワーク図を書くには欠かせないアイコンです。こういう標準化をしているところは、Amazonのよいところですね。
なおEC2インスタンスは、Terminateするとインスタンスストレージに保存した情報は消えます。ストレージの情報が消えないようにするにはインスタンスストレージでなくEBS(有料)を使うとお金は余分にかかるけど、ちょっと安心です。
うちのシステム群では、LBやAPで使っているのは基本はキャッシュで、重要な情報は保存していないのでEBSは使いませんでした。
また、別途AMI(イメージファイル)から起動するとプライベートIPもグローバルIPも動的に決められてしまうので、注意が必要です。なおTerminateではなく、stop/startやrestartではIPは変わらないので大丈夫です。Terminateは、停止というよりは、破棄ですね。OSが起動しなくなった、reboot依頼が効かない、SSHで入れなくなったなどのときに使うようですが、今のところそのような事態になったことはないです。
IPに関しては、EIPでグローバルIPを固定IP化しました(ほぼ無料)。ちなみにEIPは初期設定では5件までしか作成できません。これ以上欲しい場合は、Amazonへ連絡する必要があります。グローバルIPが貴重だからでしょうかね(うちは今のところ5件以内で済んでいます)。

その2:スタンダードサービス(CDN+LB+AP+DB)


標準的なネットワーク構成となったのは、 http://ibispaint.com 。ibisPaintは、静止画を大量にレスポンスするため事前にCloud Flare(無料CDNサービス)を追加していました。Cloud Flareは、fladdictさんのエントリーで紹介されていたので早速入れました。
AWSでは、WAN接続のデータ通信でも課金されるため、データ量を抑える必要がありますが、静的コンテンツをCDNサーバがレスポンスしてくれるため、AWS側のサーバ群までリクエストが来る量が減りコスト削減になります。ibispaintの実績ではトラフィックの60%を削減できました。通信量のみならずDB負荷も下がりました。また、CDNサービスは世界中にコンテンツキャッシュサーバがあるので、クライアントの近くのサーバが応答するようになっていて、応答が早くなる効果もあります。ibisPaintは、USやオーストラリア、アラブ、タイ、韓国、台湾などからもアクセスがあるので少しはレスポンスタイム削減にも役立っているかもしれません。なおCloud Flareを使うと、クライアントから最寄りのコンテンツキャッシュサーバにアクセスを振るために、DNSサーバはCloud Flareのものになります。また、動的コンテンツも含めいったんCloud Flareのサーバを経由してリクエストが自分のサーバに届きます。CDNサービスはAWSでもあるのですが、有料であるためCloud Flareを利用しました。無料でこれだけのサービスを受けられるとは驚愕です。
CDNの次に、ELB(ロードバランサ、月額約$18)を置きました。データセンターのころは、Apache mod_proxy_ajpによるバランシングでしたが、せっかくAWSに引っ越したということでELBを使いました。ELBにはSSHでログイン等はできずAWSのWebUIなどから設定します。ELBの管理はほとんどお任せ状態で、ELBに障害が発生した場合も、勝手に他のホストで継続するようで、固定IPではありません。そのため、CDNからELBのホストへの参照はドメイン名での参照(DNSの設定でCNAME)になります。今のところELBでの障害は経験してませんが。
ELBの後ろにAPサーバを設置。このEC2は、Apache-Tomcatの両方を同じホストにいれました。データセンターのころは、Apacheは主にロードバランサとして使っていたので、ApacheTomcatを同居させることはなかったのですが、AWSでは同居させることにしました。ApacheからTomcatへの接続では、Apache側の設定でTomcatを指定する必要がありますが、別のEC2インスタンスの場合、EC2インスタンスを新規に立てる度に、プライベートIPが決まり、その度にApache側の設定ファイルを編集しなければならないのは、手間が大きいと判断し、Apache-Tomcatを同居させて、Apache側設定ファイルでは、Tomcatのホストをlocalhostとすることで、APの追加作業が楽になるようにしました。本当は、Apache自体をなしにして、ELBからTomcatへ直でつなぎたかったのですが、mod_rewriteを使っており、ELBにはmod_rewrite相当の機能がなかったので、Apache-Tomcatとなりました。この辺り、将来新しいサービスを設計するときは、mod_rewrite不要なフレームワークを使っていきたいなと思います。上図では、4層モデルにみえますが、Apache-Tomcatと2プロセスがあるので、5層モデルになってしまっています。
EC2のインスタンスは、スモールインスタンス(月額約$66)を2台としました。ibisPaintはDB負荷やトラフィックは大きいもののAPの仕事はほとんどないので、APのCPU負荷は低いですが、可用性(サービス停止回避)のために2台にしています。
RDSの負荷は高いですが、今のところAPからDBへの接続はマスターのみで、レプリカは相変わらずバックアップ用です。間もなく参照系クエリをレプリカへも振ることになるでしょう。RDSは、ラージインスタンス(1台あたり月額約$345)を使っています。
ちなみにibisPaintの投稿された作品(静止画など)は、すべてDBに保存しているため、バックアップに数時間、リストアに数日かかるため、もはやバックアップとリストアという選択肢はほぼないに等しいです。
また、データセンターからAWSへの引っ越しでは、バックアップしてリストアでの引っ越しでは、サービス停止時間が長すぎるため、必要最低限のテーブルだけバックアップとリストアをして(その間だけ短時間サービス停止)、メインの大量のデータは、徐々にデータセンターからAWSへバッチで移動させて、バッチでのデータ移動中は、AWSのDBにデータがなければデータセンターにリクエストを振る(フォワーディング)ようにAPのプログラムを書き換えて、引っ越しをしました。
大きなデータが数日かけて、ゆっくりと移動してゆく様は、なんともかっこいいですね。

その3:DNSラウンドロビン+自社製LB+AP+DB


今回紹介する最後のネットワーク構成です。
こちらのサービスでは、ELBは使わずに自社製のロードバランサを使いました。理由は、ELBではステッキーセッション(同じユーザからのリクエストは同じAPに振る機能)のセッションキーとしてCookieしか使えず、このサービスはガラケーからのアクセスもあるためセッションキーはURLに埋め込んであるためです。i-modeブラウザが長らくCookie非対応だったためやむなくURLに埋め込んであります。なお、Apacheのmod_proxyなどのロードバランサ機能を使わず自社製となっているのは、単にこのシステムを立ち上げるときに、mod_proxyがまだなく、mod_jkかmod_jk2しかなく、また、それらが不安定であったために開発しました。おかげでWebUIでの負荷係数の変更やAP追加や切り離しができたりと使い勝手は良いです。
さらにこのシステムでは、リクエスト頻度が高いためLBを2台をEC2(スモールインスタンス、月額約$66)+EIP(固定IP)で建てて、DNSラウンドロビンで2台に振り分けています。
その後ろのAPは上図では3台ですが実際には16台となっています。APは一部ハイCPUエクストララージ(月額約$547)です。EC2インスタンスは初期設定ではアカウントにつき20台までしか追加できません。それ以上はAmazonへ問い合わせをする必要があります。恐らく後払いシステムなので与信不足とならないようにではないかと思います。
LBからAPの参照は現状hostsファイルにAPを書くことで対応していますが、この辺りはスクリプト等を書いて、自動化したいところです。

RDSの注意事項

RDS(MySQL)は、SSHでログインできません。mysqlコマンド等でアクセスすることはできます。また、my.cnfの設定ファイルの項目と同様の設定が、AWSのWebUIから設定できます。しかし、my.cnf設定項目の一部は設定不可になっているので注意です。特にtimezoneの指定ができず、APから接続開始時にセッション内変数で変更してアクセスするか、AP側のプログラムを修正する必要があります。
あとSSHでログインできないのでスローログとかも出せません。正確には、ログファイルとして出力させることができないので、テーブルに出力させることになります(現状、まだ試していない)。
2013/03 追記 AWSのアップデートでログの閲覧のWebUIとAPIが追加されました。

価格はどうなの?

現状、コストの内訳は、

といった感じで圧倒的にEC2でコストがかかっています。割とAPのCPU負荷が高いシステムというのもあると思いますが、現状は余分目にAPを立てているので高いというのがあります。これでデータセンターと同額程度のため、ここからチューニングをして台数を減らせば、半分ぐらいになるのではないかなとみています。また、現状の契約はオンデマンドインスタンスですが、リザーブインスタンスの契約に変えればさらに1/3ですむので、データセンターよりかなり安くなると思います。サーバを増やすのも減らすのも実サーバより手間が少ないのでかなり気楽に調整できるのがいいですね。

さいごに

サーバ40台の引っ越し、サブシステムも含めると20くらいあるシステム。大変な難題プロジェクトなので、緊張の連続でした。とてもハードルが高い作業でしたが、チームメンバー全員猛烈な勢いで勉強し(全員AWS未経験)、上級のネットワークエンジニアと、これがいいんじゃないか、ダメか?とネットワークアーキテクチャについて議論をしつつ、調査、修正、作業手順書作成、実行、試験を短時間でやりとげ、心すり減らしつつも大変有意義でした。
これから自動化スクリプトや、事故が起きたときを想定したマニュアル作りと、復旧訓練、サービス監視のチューニングや、コスト削減のためのチューニングがありますが、またノウハウをコツコツと貯めていきたいと思います。
クラウドに移ってやはりスケールアウトもスケールアップも楽になったのは気が楽ですね。
引っ越しプロジェクト、とても貴重な経験です。
需要があればサービス監視についてのエントリも書こうと思います。

――
アプリ受託開発、Webシステム受託開発も行っています。以下自社製品。
URL:ibisMail Freeのダウンロード、レビューはこちら
URL:ibisMail for iPhoneのダウンロード、レビューはこちら
URL:ibisMail for iPadのダウンロード、レビューはこちら
URL:ibisPaintのダウンロード、レビューはこちら サイトは、ibispaint.com
ご意見ご要望はTwitterから: @kamiyan