Quantcast
Channel: IDCF テックブログ
Viewing all articles
Browse latest Browse all 169

IDCFクラウドでkeepalivedを使ったLVS構築(2)

$
0
0

こんにちは、ソリューションアーキテクト部の金杉です!

前回は、IDCFクラウドでkeepalivedを使ったLVSを構築しました。LVSの主な二つの機能を振り返ってみると、

  1. バランシングしているサーバーのヘルスチェック
  2. VRRPを用いたロードバランサーの冗長化

などがありますね。機能1は前回のブログで紹介させて頂いたので、今回は機能2の部分、VRRPを用いてLVSを冗長構成にしてみたいと思います。そしてバランシングするサーバーの特徴に基づいた、2種類の構築方法を紹介します!

f:id:toshimi727:20160226100744p:plain
▲今回構築する構成

仮想マシンの準備

CentOS 6.6の仮想マシンで構築します。バランシングするリアルサーバー(WebやDBなど)2台とバーチャルサーバー(LVS)2台、計4台の仮想マシンを以下のスペックで作成します。「台数」選 択の部分で、"4"を選択すると一気に作れてしまいます★

マシンタイプ             Light.S1
 イメージ               CentOS 6.6 64-bit
 ボリューム              そのまま
 SSH Key                作成
 仮想マシン台数            4
 ネットワークインターフェース     そのまま
 詳細情報・仮想マシン名        LB, LB-backup, Real1, Real2,
 詳細情報・プライベートIPアドレス   自動設定

仮想マシンは、それぞれSSHできるように「IPアドレス」の設定をしておいてください。 もしリアルサーバーが公開用であれば、80番ポートのファイアウォールだけあけておいて、ポートフォワードルールは記入しないでください。後ほど新しいルールを記入します。

詳しくは、めちゃ楽ガイドをご参照ください!

 

今回の構成

今回は、Figure 1のような構成になります。仮想ルーターの下にLB(マスターロードバランサー)、LB-backup(バックアップロードバランサー)、Real1、Real2(リアルサーバー)が同じセグメントに設置されています。仮想ルーターのIPアドレスが公開用のIPアドレスになります。

一方、LBがバランシングする時の様子がFigure 2になります。LVSを冗長化することが今回の目的なので、LVSはLBとLB-backupの二台になります。LB-backupは、LBが万が一落ちてしまった場合バックアップとして動作する役割を持っています。中身はLBとほぼ同じです。

f:id:toshimi727:20160226100917p:plainf:id:toshimi727:20160226100943p:plain

普段、マスターロードバランサーとバックアップロードバランサーはセットになっていて、仮想的に1台のロードバランサーとして動作します。マスターに問題が発生した時、バックアップがマスターに昇格し、処理を代行します。このように、同じLANで複数台のルーターを1つに束ねる仕組みをVRRP(Virtual Router Redundancy Protocol)と呼び、自動的な切り替えをフェイルオーバーと言います。

右の図で見ると、LBとLB-backupは仮想的に1台のロードバランサーとして扱われます。なので、リクエストを一括で受けとるため、VIP(Virtual IP)と言う複数台のLVSを代表する仮想的なIPアドレスが必要となります。VIPを使うことによって、サービスへのリクエストはVIP宛となり、SSHなどのLVS単体へのリクエストは、サーバーの実IP宛のままで大丈夫です。イメージしやすくするには、VRRPによって束ねられているロードバランサー達を1つの仮想ロードバランサーと見て、そしてVIPはその仮想ロードバランサーのIPアドレスと想像すると良いかもしれません。

この肝心なVRRPですが、インフラの環境によってはサポートされていない場合が多いです。ですがIDCFクラウドではVRRPが使用できて、そしてVIPを取得する方法が、なんと二つもあります★共通の手順が多いのですが、構築される環境の特徴に応じて「Step1. VIPの取得」の部分を手順1と手順2に分けて紹介します。

  • バランシング対象がWeb等といった、トラフィックが仮想ルーター経由でくる場合→手順1
  • バランシング対象がDB等といった、トラフィックが内部サーバー経由でくる場合→手順2

手順がわかれる主な理由は、IDCFクラウドの仕様にあります。とても簡単な話ですが、仮想マシンが直接外部と通信する場合、仮想ルーターを経由するので、ポートフォワードを設定する必要があります。ポートフォワードをする場合はAPIでIPアドレスを取得する必要があり、具体的な方法は手順1で紹介されています。一方、リアルサーバーが内部サーバーのみと通信する場合、ポートフォワードは必要ありません。この場合、LVSの構築は比較的簡単で、その方法が手順2で紹介されています。

Step1. VIPの取得

【共通手順】

使用できるIPアドレスの確認

VIPとして使うIPアドレスの確認をします。IDCFクラウドのポータル画面より、左メニューバー「ネットワーク」、ターゲットのネットワーク名、「IPアドレス一覧」をクリックします。

f:id:toshimi727:20160226101311p:plain

手順1の場合

ここに表示されている仮想マシンやルーターに割当済みのIPアドレスと、「割当範囲外」のIPアドレスを除いたすべてのIPアドレスがVIPとして割当可能です。VIPはDHCPで取得することも可能ですが、今回は10.5.0.100を指定して使おうと思います。【手順1】の部分へお進みください。

手順2の場合

「割当範囲外」のIPアドレスがすべてVIPとして指定できるのですが、「利用不可」と書かれている最後の10個のIPアドレスだけはIDCFクラウド側で使用するため割当はできません。なので、この例では「利用不可」の10.5.7.235〜10.5.7.254を除いた範囲で選びましょう!特に決まりはないですが、今回は10.5.4.100を使います。では、【手順2】の部分へお進みください。

【手順1】仮想ルーター経由トラフィック用のLVS

トラフィックが仮想ルーターからくる場合は、下の図のような構成になります。Webなどの公開用サーバーをバランシングする時は、基本このような構成を取ります。リクエストは仮想ルーターを通過したら、直接ロードバランサーのVIP宛に届きます。そしてバランシング処理が済んだあと、再度このVIPよりリアルサーバーへ転送されます。

f:id:toshimi727:20160226101337p:plain

VIPの取得はAPI経由で行います。APIはハードルが高そうに見えますが、何回か使ううちにAPIのファンになっていく方が多いです(笑)。実際私もそうでした!IDCFクラウドではCloudStackのAPIがそのまま使えるので、なじみがある方もいらっしゃるかもしれませんね!IPアドレスの値は、先ほど確認した10.5.0.100をスタティックで付与します。APIに関しては、API Referencesをご参照ください!

コマンドラインツールのインストール APIを利用するにあたって、コマンドラインツールのインストールが必要になります。インストールするサーバーは、同じアカウント内のどのサーバーでもかまいません。APIのGetting Started ガイドに沿って「簡単な使い方:Step4」までを実行して頂いても良いですし、以前上野がご説明した「IDCFクラウド APIを利用した仮想マシンの作成からSSH接続まで」の「Step3」まで実行することでも実装できます。

APIでVIPを取得いよいよ準備はOKです。VIPをマスターロードバランサーLBのNICに追加する作業を行います。

<code>[root@LB ~]# cloudstack-api listVirtualMachines -t displayname,id</code>
<code>+-------------+--------------------------------------+</code>
<code>| displayname |                  id                  |</code>
<code>+-------------+--------------------------------------+</code>
<code>| LB          | a2fa6425-aacc-4aba-bb84-e486a41e1c9e |</code>
<code>| LB-backup   | bb4095f1-c6b1-4646-8e89-762cd26a53d2 |</code>
<code>| Web1        | 785020c1-4d3b-4bb4-84c4-c9abe8da9ccb |</code>
<code>| Web2        | ea2f2045-64b5-4f70-9201-e0a6aa9c81c5 |</code>
<code>+-------------+--------------------------------------+</code>
 
<code># 仮想マシンLBのNIC idを表示</code>
<code>[root@LB ~]# cloudstack-api listNics --virtualmachineid a2fa6425-aacc-4aba-bb84-e486a41e1c9e -t ipaddress,id</code>
<code>+------------+--------------------------------------+</code>
<code>| ipaddress  |                  id                  |</code>
<code>+------------+--------------------------------------+</code>
<code>| 10.5.0.133 | d555c213-3ede-4bb4-96bd-d1ce6c475852 |</code>
<code>+------------+--------------------------------------+</code>
 
<code># 仮想マシンLBのNICにセカンダリIPアドレスを指定して割り当てる</code>
<code>[root@LB ~]# cloudstack-api addIpToNic --nicid d555c213-3ede-4bb4-96bd-d1ce6c475852 --ipaddress 10.5.0.100</code>

<code># もう一度仮想マシンLBのNICの情報を表示</code>
<code>[root@LB ~]# cloudstack-api listNics --nicid d555c213-3ede-4bb4-96bd-d1ce6c475852 --virtualmachineid a2fa6425-aacc-4aba-bb84-e486a41e1c9e</code>
<code>{</code>
<code>  "listnicsresponse": {</code>
<code>    "count": 1,</code>
<code>    "nic": [</code>
<code>    {</code>
<code>      "gateway": "10.5.0.1",</code>
<code>      "id": "d555c213-3ede-4bb4-96bd-d1ce6c475852",</code>
<code>      "ipaddress": "10.5.0.133",</code>
<code>      "isdefault": true,</code>
<code>      "macaddress": "02:00:56:df:00:0f",</code>
<code>      "netmask": "255.255.252.0",</code>
<code>      "networkid": "15616765-d713-4ff3-bba3-a1c71a46d9bf",</code>
<code>      "secondaryip":</code>
<code>      {</code>
<code>        "id": "f2ff97fe-ecfd-4e01-ab34-9b17cbce16f9",</code>
<code>        "ipaddress": "10.5.0.100"</code>
<code>      }</code>
<code>    }</code>
<code>    ]</code>
<code>  }</code>
<code>}</code>

APIでポートフォワードルールを記入

<code>[root@LB ~]# cloudstack-api listPublicIpAddresses -t ipaddress,id</code>
<code>+----------------+--------------------------------------+</code>
<code>|   ipaddress    |                  id                  |</code>
<code>+----------------+--------------------------------------+</code>
<code>| 210.140.68.220 | 0c5cc05a-26d5-4539-9c7a-0f935291f71d |</code>
<code>+----------------+--------------------------------------+</code>
 
<code># VIPを指定してポートフォワードルールを記入</code>
<code>[root@LB ~]# cloudstack-api createPortForwardingRule --ipaddressid 0c5cc05a-26d5-4539-9c7a-0f935291f71d --privateport 80 --protocol tcp --publicport 80 --virtualmachineid a2fa6425-aacc-4aba-bb84-e486a41e1c9e --vmguestip 10.5.0.100</code>
<code>{</code>
<code>  "createportforwardingruleresponse": {</code>
<code>    "jobid": "dfc3d84e-c9e6-47d3-9f50-4fc4b2c25493",</code>
<code>    "id": "dfc3d84e-c9e6-47d3-9f50-4fc4b2c25493"</code>
<code>  }</code>
<code>}</code>

注意点 API経由で取得したsecondary IPの扱いには、2つ注意点がございます。 ※東日本リージョンのみの注意点となります。

  1. Secondary IPはポータルからの管理ができないので、ご自身での管理となります。なので誤って仮想マシンを削除してしまわないよう気を付けましょう!
  2. Secondary IPをグローバルIPアドレスとスタティックNATした場合、APIでスタティックNATを解除してから仮想マシンを削除するようにしてください。スタティックNATの設定解除せず、そのまま仮想マシンを削除してしまうとシステム側からスタティックNATが削除できなくなってしまいます。

【手順2】内部サーバー経由トラフィック用のLVS

トラフィックが内部サーバーからくる場合、下の図のような構成になります。DBなどの非公開用サーバーをバランシングするとき、よく取られる構成です。リクエストはWebサーバーなどの内部サーバーからロードバランサーのVIP宛に届きます。そしてバランシング処理が済んだあと、再度このVIPよりリアルサーバー1かリアルサーバー2へ転送されます。

f:id:toshimi727:20160226101354p:plain

このような構成の場合、VIPの取得はとても簡単です。VIPをあらかじめ決めておく事以外、特に設定の必要もありません!IPアドレスの値は、先ほど確認した10.5.4.100を使います。

注意点 VIPとして指定されたIPアドレスは、ポータルから管理ができないので、ご自身の管理となってしまいます。なのでIPアドレスが重複しないよう気を付けてください。

Step2. keepalivedの準備

LVSの設定をしていきます。もし前回の記事に沿って設定されているかたは「LVSの設定」部分から続けて下さい。

必要なパッケージをダウンロード

<code>[root@LB ~]# yum -y install ipvsadm keepalived</code>

自動起動の設定

<code>[root@LB ~]# chkconfig --list keepalived</code>
<code>keepalived  0:off  1:off  2:on  3:on  4:on  5:on  6:off</code>

パケット転送の設定

<code>net.ipv4.ip_forward = 1 (0から1へ変更)</code>
<code>[root@LB ~]# sysctl -p</code>
<code>net.ipv4.ip_forward = 1 (変更されていればOK)</code>

LVSの設定 keepalivedはデフォルトでipvsadmをラップしているので、LVSの設定はkeepalivedのコンフィグを編集して行います。マスターとバックアップ両方のコンフィグを記入する必要がありますが、priorityの値だけは異なるように設定してください。

<code># vrrp_instance [お好きな名前]で複数設定が可能です</code>
<code>vrrp_instance VI_1 {</code>
<code>  # マスター、バックアップのいずれか</code>
<code>  state MASTER</code>
<code>  # 監視するインターフェース</code>
<code>  interface eth0</code>
<code>  # VRIDは任意の数値で良いが</code>
<code>  # 同じセグメントの他のVRIDとかぶらないように設定する</code>
<code>  # 例:仮想ルーターのVRIDや追加ネットワークのVRID</code>
<code>  virtual_router_id 1</code>
<code>  # マスターとバックアップで必ず違う値にする</code>
<code>  # 例:マスター:300、バックアップ1:200、バックアップ2:100</code>
<code>  priority 100</code>
<code>  # VRRP信号を送る間隔</code>
<code>  advert_int 1</code>
<code>  # VIPを指定、手順2の場合は10.5.4.100</code>
<code>  virtual_ipaddress {</code>
<code>    10.5.0.100 dev eth0</code>
<code>  }</code>
<code>}</code>
<code># LVSの設定</code>
<code>virtual_server 10.5.0.100 80 {</code>
<code>  # ヘルスチェック間隔</code>
<code>  delay_loop 3</code>
<code>  # 分散方式はround robinを使う</code>
<code>  lb_algo rr</code>
<code>  # パケット転送の方法はdirect routing (DSR)</code>
<code>  lb_kind DR</code>
<code>  protocol TCP</code>
<code>  # リアルサーバのIPアドレスおよびヘルスチェックのポート番号</code>
<code>  # Webは80番や443番、MySQLは3306番など</code>
<code>  real_server 10.5.0.36 80 {</code>
<code>    weight 1</code>
<code>    # ヘルスチェック失敗時はweightをさげる</code>
<code>    inhibit_on_failure</code>
<code>    # ヘルスチェック方式</code>
<code>    # WebはHTTP_GETやSSL_GET、MySQLはTCP_CHECKなど</code>
<code>    HTTP_GET {</code>
<code>    # Webはurl、MySQLではconnect_port 3306など</code>
<code>    url {</code>
<code>    # ヘルスチェック用のページ</code>
<code>      path /healthchk.html</code>
<code>      status_code 200</code>
<code>    }</code>
<code>    connect_timeout 3</code>
<code>    # ヘルスチェック失敗時の間隔</code>
<code>    delay_before_retry 7</code>
<code>  }</code>
<code>}</code>
<code># リアルサーバー2台目以降も同じ設定にする</code>
<code>  real_server 10.5.0.229 80 {</code>
<code>    weight 1</code>
<code>    inhibit_on_failure</code>
<code>    HTTP_GET {</code>
<code>      url {</code>
<code>        path /healthchk.html</code>
<code>        status_code 200</code>
<code>      }</code>
<code>      connect_timeout 3</code>
<code>      delay_before_retry 7</code>
<code>    }</code>
<code>  }</code>
<code>}</code>

Step3. リアルサーバーの準備

手順1の場合はWebサーバー、手順2の場合はDBサーバーを例として準備します。ApacheやMySQLをインストールして、サービスをスタートすれば動作確認はとれます。Webサーバーに関しては、ヘルスチェック用のページも忘れず用意しておいてくださいね! iptablesの記入重要です。リアルサーバーがLVSのVIP宛のパケットを受け取ったとき、自分宛のパケットとして処理できるようにさせてあげる必要があります。

<code># -d 10.5.0.100 の部分でご自身のLVSのVIPを指定する</code>
<code>[root@Real1 ~]# service iptables save</code>

Step4. keepalivedの起動

LVS冗長構成の設定とVIPの準備ができたので、keepalivedを起動して、様子を見てみましょう! keepalivedの起動

VIPの確認マスター(LB)のほうでeth0に割り当てられているIPアドレスを見てみましょう。

<code>2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000</code>
<code>link/ether 02:00:56:df:00:0f brd ff:ff:ff:ff:ff:ff</code>
<code>inet 10.5.0.133/21 brd 10.5.7.255 scope global eth0</code>
<code>inet 10.5.0.100/32 scope global eth0</code>
<code>inet6 fe80::56ff:fedf:f/64 scope link</code>
<code>valid_lft forever preferred_lft forever</code>

マスターのほうにVIPがついています。VIPは、実際にLVSとして動いているサーバーに付きます。なのでこの時点で同じコマンドをバックアップのほうで入力しても、VIPは表示されません。マスターが正常にLVSとして稼働しているからです。

動作確認動作確認の前に、LVS上でipvsadmコマンドを使ってバランシングの状態をマスター、バックアップ両方で確認してみましょう。

<code>IP Virtual Server version 1.2.1 (size=4096)</code>
<code>Prot LocalAddress:Port Scheduler Flags</code>
<code>-&gt; RemoteAddress:Port           Forward Weight ActiveConn InActConn</code>
<code>TCP  10.5.0.100:80 rr</code>
<code>-&gt; 10.5.0.36:80                 Route   1      0          0</code>
<code>-&gt; 10.5.0.229:80                Route   1      0          0</code>

LVSのIPアドレスが見事VIPの10.5.0.100(手順2の場合10.5.4.100)になっています。ここでマスターを落としてみて、バックアップへフェイルオーバーするか確認してみます。

<code>keepalived を停止中:                                       [  OK  ]</code>
<code>[root@LB ~]# ip addr show eth0</code>
<code>2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000</code>
<code>link/ether 02:00:56:df:00:0f brd ff:ff:ff:ff:ff:ff</code>
<code>inet 10.5.0.133/21 brd 10.5.7.255 scope global eth0</code>
<code>inet6 fe80::56ff:fedf:f/64 scope link</code>
<code>valid_lft forever preferred_lft forever</code>

マスターでもう一度eth0に割り当てられているIPアドレスを見てみると、VIPが消えています。では、バックアップのほうを見てみましょう。

<code>2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000</code>
<code>link/ether 02:00:0a:30:00:10 brd ff:ff:ff:ff:ff:ff</code>
<code>inet 10.5.0.195/21 brd 10.5.7.255 scope global eth0</code>
<code>inet 10.5.0.100/32 scope global eth0</code>
<code>inet6 fe80::aff:fe30:10/64 scope link</code>
<code>valid_lft forever preferred_lft forever</code>

VIPが自動的にバックアップのNICに切り替わりました。冗長化は保たれていますね。

<code>IP Virtual Server version 1.2.1 (size=4096)</code>
<code>Prot LocalAddress:Port Scheduler Flags</code>
<code>-&gt; RemoteAddress:Port           Forward Weight ActiveConn InActConn</code>
<code>TCP  10.5.0.100:80 rr</code>
<code>-&gt; 10.5.0.36:80                 Route   1      0          0</code>
<code>-&gt; 10.5.0.229:80                Route   1      0          0</code>

バランシング状態も大丈夫のようです。これでLVSが冗長化されていることがわかりました。ばっちりですね★

 

終わりに

みなさん、LVSの冗長化はいかがでしたか?コンフィグの部分はさておき、VIPの取得が少し手間かもしれませんが、高価なロードバランサー2台分のお値段を考えると、全然お得ですよね!

もっとも魅力的なのはやはりクラウド環境で、VRRPを用いたLVSの冗長化が可能な仕様だと思っています。例の通り、IDCFクラウドはAPIさえクリアしてしまえば簡単にそれを実現できてしまいます。インフラのポイント、安定性と柔軟性においては文句なしです!

もちろん、もし内部トラフィックのバランシングのためでしたら、特にAPIを使う必要もないです。IPアドレスを指定してkeepalived.confに記述するだけで大丈夫です。なので、ぜひ構築したい環境の必要に応じて、楽できるインフラ構築を目指しましょう!ありがとうございましたー^ ^

<関連記事>


Viewing all articles
Browse latest Browse all 169

Trending Articles