ニフクラ ブログ

ニフクラやクラウドの技術について、エンジニアが語るブログです。

できる!ソーシャルアプリ(4) オープンソースで「L7ロードバランサーも、VPNも、あるんだよ」

こんにちは、株式会社エクストーンの仲山です。
この連載では、ソーシャルアプリの企画から公開、運用までを通したTIPSを紹介します。

前回の記事では、 リリース前にあらかじめサーバの性能を見積もり、安心してリリースを迎えるために、 アプリの性能試験ツールであるJMeterを紹介しました。

今回は、クラウド環境を利用する上で必要となるL7ロードバランサーやVPNといったネットワーク構成を、 オープンソースソフトウェアを利用してを実現してみます。

ロードバランサー

まず最初に、ロードバランサー(負荷分散装置)の役目をおさらいします。

1. 負荷の分散

その名の通り、システムへのアクセスを複数のサーバに分散することで、 システム全体の性能を上げる「スケールアウト」を実現することができます。

2. 可用性の向上

どれかのサーバが障害で停止した場合には、 そのサーバを除いた他のサーバにアクセスを分散することにより、 システム全体の可用性を上げ、故障率を下げることができます。

3. 適切なサーバへの振り分け

複数のサーバにアクセスを分散させる場合に、 クッキーに含まれるセッションIDで識別したアクセス元に応じて振り分け先サーバを固定したり、 アクセス先のURLから画像ファイルのみ静的ファイル用のサーバに振り分けるなど、 アクセスの内容を判断することで、より柔軟なサーバ構成を取ることができます。

4. ソーリーページの表示

万が一全てのサーバが停止している場合や、 アクセスを振り分けたサーバから、一定時間反応が無い場合に、 ロードバランサーがアクセスへの応答を横取りし、代わりとなる「ソーリーページ」を表示することができます。 サーバ側が過負荷になってしまった場合にも、 リバースプロキシの一種として扱われることも多いです。

ニフティクラウドのロードバランサーとの違い

1.や2.までは現在のニフティクラウドで提供されているロードバランサーで実現可能です。 また、3.は接続元IPアドレスによる振り分け、 4.のソーリーページ機能はニフティさんの提供する固定の内容が利用可能です。 さらに、今後のエンハンス予定にて、 SSLへの対応が告知されました。

その一方で、ソーリーページの内容を自分のアプリに基づいた独自の内容に変更したり、 あるいはクッキーや接続先URLに基づいた細かい制御は、 現在のニフティクラウドのロードバランサーでは実現ができません。 また、あらかじめ決めた帯域設定に基づく月額課金となっているなど、 ちょっと試しに使ってみる、というのが難しい価格体系になっています。

そこで、オープンソースソフトウェアを利用して、 柔軟な設定が可能なロードバランサーを作ってみます。

nginx

nginx(公式サイト)は、 軽量かつ高性能なウェブサーバ兼リバースプロキシサーバで、 複数サーバへのリバースプロキシとして設定できるためL7ロードバランサーとして利用できます。 非同期のアーキテクチャを用いているため、少ないメモリで大量の接続を高速に捌くことができることから、 ここ数年で広く使われるようになり、2011年3月の統計で3位のシェアを占めています。 ちなみに、nginxは「えんじん えっくす」と読みます。

というわけで、早速インストールしてみます。 kernelのバージョンの都合で、EPELに含まれるパッケージがそのまま動作しないため、 動作するようにビルドしなおすインストールスクリプトを用意しました。
インストールスクリプト: install_nginx.sh

設定ファイルのポイント

nginxの一般的な設定については割愛しますが、 いくつか重要なポイントをご紹介します。

タイムアウト

とにかくソーシャルアプリはページの処理時間との戦いです。 そのため、2つの方法で処理時間をコントロールします。

1. タイムアウト時のソーリーページ
Webサーバ側が過負荷になってしまった場合にも、 「リロードしてください」だけでも一定の時間内に返すことで、 SNS側のタイムアウトペナルティを避けることができます。 そこで、nginx内でSNS側の規定時間よりも短いタイムアウトを設定し、 それを超えた場合に「ソーリーページ」を表示します。

タイムアウトが発生するポイントがいくつかあります。
・upstream 内の各server行に設定された「max_fails=1 fail_timeout=4;」
・server 内で設定された「proxy_connect_timeout 4;」「proxy_read_timeout 4;」
さらに、万が一Webサーバ側がエラーとなってしまった場合にもソーリーページを表示するために、いかの設定も入れています。
・proxy_intercept_errors on;
・proxy_next_upstream

実際にエラー時に表示する画面を定義しているのがerror_pageの部分です。 バッドノウハウ的ではありますが、 SNS側には正しくコンテンツを返せているように見せるため、 500等のエラーがあってもソーリーページ自身は200を返すようにしています。

2. 表示時間ログ
いくらソーリーページを表示できているといっても、 利用者の期待に答えられていない以上、 それを検知してアプリケーションを改善する必要があります。 そのため、resptimeという表示時間を追加したログフォーマットでログを取るようにしています。

表示時間を含むアクセスログは、 ApacheでもLogFormatの「%D」パラメータなどで利用可能ですので、 nginxに限らず取得することをおすすめします。

3. 監視用のモニタリングページ
処理時間の他にも、実際の接続数などはサーバの負荷動向を見る上で重要なパラメータです。 サーバ監視ツールMuninにはnginx用のプラグインが含まれていますので、 http://localhost/nginx_status にアクセスするとnginxのステータスが表示されるようにしています。 サーバ上からこのURLで取得できるようになっていれば、 munin-node-configure --shell コマンドで設定なしで検知してくれます。

nginxの運用

上記設定で接続先の設定の直前に「location /」などと書いてあったことからも判るように、 パス毎に接続先のサーバを変更するなどの柔軟な設定を分かりやすく行うことができます。 今回はnginxの導入とロードバランサーとして動かすための重要なポイントに絞って紹介しましたが、 時間課金のクラウド環境であればすぐに実験して使い捨てができますので、 実運用に入る前にじっくり検証してみることが可能です。

VPN

二つ目に紹介するのはVPNです。
先日、ニフティクラウド公式からも、 PFU VPNサービス for NIFTY Cloud として株式会社PFUさんが提供するVPNサービスのお知らせがありましたが、 月額利用のみであるプライベートLANオプションの利用が必須であるなど、 小さな規模で使うには不便な点があります。 そこで、これもオープンソースソフトウェアを使って手軽に構築してみます。

VPNの種別

VPNにはいくつか種類がありますが、大きく二つの軸で区別します。

拠点間VPNとクライアントVPN

これらはネットワークの形態の区別で、 既に存在する複数のネットワークの間を接続するものが拠点間VPNで、 ネットワークに対してクライアントPCがそこに接続するものがクライアントVPNです。 後者は特に、インターネット上の一般のISPに接続したクライアントから、 社内やサーバ環境のネットワークに接続するために利用することが多いです。 前述したPFU VPNサービス for NIFTY Cloudは拠点間VPNで、今回取り上げるPPTPはクライアントVPNです。

L2 VPNとL3 VPNとSSL VPN

これらは提供される仮想ネットワークの種類の区別で、 L2 VPNは、イーサネットで直接同じネットワークに接続しているように仮想ネットワークを提供します。 L3 VPNは既存のネットワークと別のIPアドレスを持つ別の仮想ネットワークを提供し、 一方(または両方)がルータとなります。 SSL VPNはちょっと毛色が異なり、仮想ネットワークという形ではなく、 HTTPやWindowsファイル共有など具体的なそれぞれのサービスごとにSSLによる暗号化通信を提供するものです。 PFU VPNサービス for NIFTY CloudやPPTPはどちらもL3 VPNとなります。 今回は取り上げませんが、同じくオープンソースのOpenVPNUT-VPNであればL2 VPNの構築も可能です。

PPTP

上記のとおりVPNにはいくつかの種類がありますが、今回は一番手軽な方法としてPPTPを利用します。 PPTPでは、接続元となるクライアントPCからサーバに対し、 暗号化された「仮想ネットワーク」を接続することができます。 また、WindowsやMacOSのような商用OSでも標準で対応しているため、 特に接続用のソフトウェアなどを導入せずに利用できます。

さっそく導入してみる

ソフトウェアの導入と設定ファイルまではインストールスクリプトを用意しました。
インストールスクリプト: install_pptpd.sh

ユーザの登録

VPN利用者のID/パスワードは独自に設定する必要があります。 /etc/ppp/chap-secret を以下のように編集してください。

# client  server  secret     IP addresses
USER1     *       PASSWORD1  172.16.0.2
PPTP接続 (Windows)

「ネットワークと共有センター」から、新しい接続を作成でき、 やや分かりづらいですが「職場へ接続します」がVPNの作成をさします。

PPTP接続 (MacOS)

ネットワーク環境設定から左下の[+]を選ぶと接続の追加ができますので、 インターフェイスはVPNを、VPNタイプはPPTPを選びます。 その後、認証設定からパスワードを入力し、 詳細タブから「すべてのトラフィックをVPN接続経由で送信」にチェックを入れます。 設定が完了したら、その画面の接続ボタンでVPNを接続します。

VPNの利用

ここまで設定が終われば、VPNを接続するとiptables等でふさがれているはずのサーバ上のサービスに接続できるほか、 サーバ側のiptablesでNATを行っているため、 このクライアントPCからインターネットへの通信が、接続先サーバのIPアドレスを経由して行われるようになります。 また、ニフティクラウドのプライベートネットワークに対しても同様ですので、 プライベートネットワークのみにポートを開けている別のサーバ上のDB等にも接続ができます。

これで、インターネット上の通信は暗号化したまま、 ニフティクラウド上のサーバ群にVPN経由でアクセスできるようになりました。

次回予告

第2回では開発環境の構築省力化のためにChef-soloを紹介しましたが、 次回はそれを受けて、 リリース環境の準備にChef-serverを使ったChefの実例を取り上げる予定です。
第5回: Chef-serverによる自動化で「手作業なんて、やるわけない」