ipvsadmとkeepalived を使って Railsサーバーを負荷分散

ipvsadmとkeepalived を使って Railsサーバーを負荷分散

ipvsadmとkeepalived を使って Railsサーバーを負荷分散

ipvsadmとkeepalived を使って Railsサーバーを負荷分散 へのコメントはまだありません

Railsのアプリケーションを作ったはいいが、過負荷になった時にどうスケールしてよいか分かっていなかったので、検証環境を作って試してみることにした。高価なハードウェアの負荷分散装置なんて買って試すわけにもいかないので、Linuxの負荷分散システム(LVS)を利用して環境を構築してみることにする。用意する機器は以下となる。

・Railsのアプリケーションが動作するPC 2台
・負荷分散(LVS)を実装するPC 1台
・DBサーバー用PC 1台
・検証用PC1台
・ブロードバンドルーター1台

実際には仮想化環境なんかも使えるので、三台ぐらいPCがあれば、なんとかなります。動きゃいいという前提ですので、古いPCでも全然OK。ネットワーク構成は以下のような感じ。ごく普通の市販のブロードバンド配下にローカルネットワークが構成されていて、その内の1台がLVS(PCLVS)、残り2台がRailsサーバー(PCRails1、PCRails2)、RailsサーバーのどちらかにDBサーバー機能(PCRails1)も付与する。

ローカルLAN以外の環境に検証用のPCを1台(PCTest)を配置するが、実際には検証用PCもローカルLAN内に配置して、SoftEtherVPNを使ってローカルネットワーク外からアクセスする環境を作ります。

LVS

具体的なテストは、検証用PCから ブロードバンドルーターに割り当てられたGlobalIPに向けて HTTPリクエストを送り、ブロードバンドルーターに設定されたNAT情報に基づきリクエストがLAN内のPCLVSへ転送される。PCLVSでは、設定されたアルゴリズム、転送先に基づきリクエストを転送する。最終的にリクエストを処理するRailsサーバー(PCRails1 or PCRails2)は、通常通りリクエストを処理し、PCLVSを介さずに直接検証用クライアントへレスポンスを返す、という流れです。

では、それぞれのPCにセットアップしたOSや設定情報なんかを記載していきたいと思います。

ブロードバンドルーターの設定

ブロードバンドルーターの設定画面にログインし、80番ポートへやってきたリクエストを、PCLVS(192.168.1.100)へ転送するように設定する。既に80番ポートを別の用途で利用している場合などは、1080とか2080とか適当な公開ポートを設定し、そのポートへ来たリクエストを PCLVSの80番に転送するように設定する。設定が出来たら、たいていルーターの再起動が必要なので、再起動してやってください。

Railsサーバーの設定

Railsの実行環境は Ubuntuで実装した。これは別にWindowsでも構いませんが、後でちょっと小細工をしますので、Linux系の方がよろしいかと。
最終的には Passengerなどを使ってApacheにホストさせたRailsアプリにアクセスさせたいが、いきなりそこまで行くにはちょっと敷居が高いので、Apacheを入れて、テストページを表示させて、負荷分散処理の成否を確認したいと思います。Railsサーバーへの負荷分散は後述します。

HTMLの中身はApacheにアクセスしたこと、ホスト名がPCRails1であることが、理解できれば何でもOKです。

ついでにRailsのテストページも作っておきます。
(Railsのプロジェクトフォルダが、/home/yourname/workspace/railsapp/ )

HTMLの中身はRailsにアクセスしたこと、ホスト名がPCRails1であることが、理解できれば何でもOKです。

この2つのファイルを PCRails1とPCRails2に作成してください。
で、apacheを再起動します。

Linux負荷分散(LVS) の設定 〜 ipvsadm

今回は CentOS 6.5を利用しましたので、その手順を記載します。
・まずは、ごく普通にMinimalインストールなんかでOSのセットアップを行なってください。私はVirtualBoxのVM環境にCentOSをセットアップしました。HDDは3G、RAM512MBぐらいで十分です。

NIC eth0 を eth0 と eth0:0 に分割し、それぞれに固定IPアドレスを割り当てます。

実際に外部からの仮想ターゲットとなるNIC eth0:0 の設定

ネットワークを再起動し、ifconfigで、設定が正しく反映されているかを確認します。

では、負荷分散機能を提供する ipvsadmとkeepalived などをインストールしましょう。Keepalivedはバージョン違いで動作に不具合が出ることもあるそうですが、CentOS 6.5の環境ではデフォルトのrpmで問題なく動作しました。

インストールが終わったら以下のコマンドで負荷分散設定を確認します。
当然、何もセットされていません。

仮想ターゲットNIC(192.168.1.100) にアルゴリズム rr(ラウンドロビン)を設定し、負荷分散をONにします。

実際のサービスを提供するリアルサーバー(Railsサーバー、PCRails1とPCRails2)のIPアドレスを DRで登録します。

以下のコマンドで、設定が有効になっているか確認してください。

最初は ipvsadmで転送ポートまで指定できるのかと思っていましたが、いろいろ試した結果、うまく動作しません。とりあえず、今はPort80に来たリクエストを素直にリアルサーバーのPort80へ転送するという事にしておきます。

検証用PCの設定

モバイル環境などがあれば、直接その環境を利用してテストすればOKです。モバイル環境が手元にない場合は、LAN内に配置した検証用PCにSoftEtherVPNをインストールし、VPN Gate経由で擬似的にインターネット側からブロードバンドルーターのGlobal IPへアクセスします。
セットアップ方法はたいして難しくもないので、本家サイトのマニュアルなんかを参照ください。

では、検証用PCのコンソールを起動し、以下のコマンドを発行してみます。

残念ながら応答なしです。
原因は LVSであるCentOSでパケットフィルタリングがかかっていて、80番Portがふさがっているためです。LVSのコンソールから、以下のコマンドを実行し、ポートを開放します。

更にパケットフォワードの設定をしておきます。

さぁ、検証用PCのコンソールで以下のコマンドを発行してみます。

コマンドを発行するたびに、別々のサーバーから応答が帰ってきていることが確認できました!!
これで最低限の負荷分散機能は完成です。

Linux負荷分散(LVS) の設定 〜 keepalived

既に keepalivedのインストールは完了しているので、設定ファイルの変更を行います。

1つのファイルですが、前半部分と後半部分に分けて説明します。

前半

■LVSに対しての設定
・LVSの種別・・・MasterではなくBackupに
・負荷分散対象となるNICインターフェイス・・・ eth0
・負荷分散対象となるIPアドレス・・・ 192.168.1.100

後半
ここでLVSに対しての設定と、リアルサーバーに対しての設定を行います。

■LVSに対しての設定
・負荷分散対象となるIPアドレス 192.168.1.100
・負荷分散対象となるポート 80
・ヘルスチェック間隔 6 秒
・負荷分散のアルゴリズム rr (ラウンドロビン)
・負荷分散の種類 DR (ダイナミックルーティング)
・ごめんなさいサーバー 192.168.1.100:1080 LVS自体にapacheを導入し、そこにメンテナンス中を示すHTMLを作成

■リアルサーバーに対しての設定
・リアルサーバーのIPアドレス 192.168.1.22 or 192.168.1.25
・リアルサーバーのポート 80
・重み付け 1
・応答なしの時はweightをゼロに inhibit_on_failure
・ヘルスチェックに用いるプロトコル HTTP_GET
・ヘルスチェック対象となるURL /health_check.html
・ヘルスチェック対象となるポート 3000

KeepAlivedは LVSPCからリアルサーバーに対して HTTP_GETでヘルスチェックを行います。この時Railsが生きているかどうかを確認したいので connect_port に 3000を指定して、Railsのプロジェクトフォルダ/public/health_check.htmlにアクセスします。Passengerを使っているときは 80番ポートのままで良いので、ヘルスチェック対象となるページのURLをPassengerで定義したApacheの仮想フォルダとしてやればOKでしょう。

ipvsadmとkeepalivedの再起動 (順番守ってください)

リアルサーバーの設定調整

これでほぼOKなのですが、この設定のままでは、LVSPC(192.168.1.100:80)に飛んできたパケットがそのままリアルサーバーに転送されることになり、リアルサーバー側で自分宛(192.168.1.22 or 192.168.1.25)のパケットではないという理由で破棄されてしまうことがあります。これを防ぐためにリアルサーバー側に細工をしてやります。

実際に何をやっているかというと、宛先が LVSPC(192.168.1.100:80)のパケットを 自分宛のパケットとみなし port 3000へリダイレクトするという事を行なっています。

ここでようやく 80番ポートではない別のポートへ処理を転送できました。
Railsの公開にはPassenger等を利用することが前提で、Passengerなら 80番ポートでOKなのですが、テストなので WEBrickで動作しているRailsのポートへパケットを転送してやることにより、負荷分散を実現します。

この設定はリブートのたびになくなりますので、どこかに仕込んでおいてやってください。Ubuntuでiptablesの設定ノウハウがないので、あしからず。

追記
arpの設定をします。詳しくはよくわかっておりません。今後研究します。

動作検証1

負荷分散の状況は以下のコマンドで確認できます。

片方のサーバーを殺してしばらく待ってみてから、以下のコマンドを実行すると、死んでいるサーバーのWeightが0になっていることが確認できます。
(死んだサーバーを起こしてやると、めでたく1に戻ります。)

また、実際に検証用クライアントから接続テストを行い、片方が死んでいる場合は、生きている方のサーバーへのみアクセスが行われることを確認してみてください。

動作検証2

全てのリアルサーバーがダウンしている場合、今のままでは応答なしとなってしまいます。ここで、keepalived.confに設定した sorryserverの設定を活かしてみましょう。sorryserverはとりあえず、LVSにapacheを導入し、そこにメンテナンス中を示すページを作ることで対応します。また LVSの80は利用されているので、とりあえず別のポート(1080)で公開することにします。

LSVPCにて

バーチャルサーバーの設定

apache再起動

実際にリアルサーバーを全てダウンさせて、メンテナンス中ページが表示されるか確認してみてください!

以上 お疲れ様でした。


About the author:

Related Posts

Leave a comment

Back to Top