2012年5月8日火曜日

KVMでHAクラスタの機能検証環境を構築 - めもめも


KVMでHAクラスタの機能検証環境を構築


  • 2011/08/04 17:50 クラスタの基本構成まで書いた。
  • 2011/08/05 18:50 サービスリソースの構成も書いた。

「RHCS設計・運用入門」という資料を作るにあたって「そういえば、あの設定ってどういう動きになるんだっけ???」みたいなことをサクッと確認できる環境をKVMで用意しました。せっかくなので構築手順を残しておきます。

ハードウェア依存の機能や微妙なパラメータチューニングの確認は、きちんと物理サーバでやるべきですが、こういう手軽な環境を手元のPCに用意しておくともろもろの作業効率が格段に上がります。(インフラ技術はいぢり倒して学ぶのが王道ですしね。)

参考資料)High Availability Add-On 非公式技術情報


前提ソフトウェア

RHEL6.1のHigh Availability Add-Onを使用します。以前はRed Hat Cluster Suite(RHCS)として有名だったやつですが、なにげに名称が変更されています。

レポジトリからまとめて導入する時はこれでOKです。

  # yum groupinstall "High Availability"  

High Availabilityグループで入るのは下記のパッケージ(とその前提パッケージ)なので、Fedoraでがんばる方はこれらと同等パッケージをご使用ください。

  # rpm -q cman ccs omping rgmanager  cman-3.0.12-41.el6_1.1.x86_64  ccs-0.16.2-35.el6.x86_64  omping-0.0.1-4.el6.x86_64  rgmanager-3.0.12-11.el6_1.1.x86_64  

VM環境の準備

こんな感じの仮想ネットワークとVM2個を用意します。KVMの仮想ネットワークの構成方法はプロのためのLinuxシステム・ネットワーク管理技術の第5章に詳しく書いてあります。


メモメモ

ハートビートが切断してあるノードの状態が不明になった場合、相手のノードは、管理ネットワークを通じてこのノードを強制再起動します。物理サーバ環境であれば、各ノードのリモート管理NIC(IPMIの接続ポート)を管理ネットワークに接続しておいて、ここから強制再起動を実施します。

これは、ハートビートが通じない、すなわちハートビート・ネットワークが切れているかも知れない状態で実施する必要がありますので、ハートビート・ネットワークと管理ネットワークを兼用することはできません。必ずハートビート・ネットワークとは独立した経路で強制再起動できる方法を用意してください。

どうしてもネットワークが3経路用意できない場合は、サービスネットワークとハートビート・ネットワークを兼用するか、サービスネットワークと管理ネットーワークを兼用することになります。前者の場合は、サービスネットワークの通信負荷が上がってもハートビートが切れないかどうか入念な事前確認が必要です。(サービスネットワークと管理ネットワークを兼用できるかどうかは、クラスタとは直接関係なく、ネットワークの管理ポリシーに依存することですね。)

node01とnode02それぞれにRHEL6.1を入れて、前述のHigh Availabilityグループを導入します。その他には、このぐらいの準備をします。

・iptablesはoffっておく。

・ntpdで時刻同期しておく。

・/etc/hostsは下記のとおり。

  127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4  ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6  192.168.7.121	node01  192.168.7.122	node02  192.168.7.123	node03    192.168.8.121	node01m  192.168.8.122	node02m  192.168.8.123	node03m    192.168.9.121	node01h  192.168.9.122	node02h  192.168.9.123	node03h  

・両ノードのrootユーザ同士でSSHの公開鍵認証を設定して、パスワード無しのSSHが打てるようにしておく。


共有ストレージの準備

ホストLinuxのiSCSIターゲットを使用します。外付ストレージ装置を用意しないでここまでできるってLinuxはすばらしぃですね。

まず、ホストLinuxで下記を実行します。

  # yum install scsi-target-utils  # mkdir -p /var/lib/tgtd/cluster01  # cd /var/lib/tgtd/cluster01  # dd if=/dev/zero of=volume01.img bs=1M count=100  # dd if=/dev/zero of=volume02.img bs=1M count=1000  

targetedモードでSELinuxを動かしている場合は、Volumeファイルは/var/lib/tgtd/以下に置く必要があるので注意してください。続いて、/etc/tgt/targets.confの末尾に下記を追加します。

        backing-store /var/lib/tgtd/cluster01/volume01.img      backing-store /var/lib/tgtd/cluster01/volume02.img    

最後にtgtdサービスを起動します。

  # chkconfig tgtd on  # service tgtd start  # tgt-admin -s  Target 1: iqn.2011-08.com.example.yourhost:tgt01      System information:          Driver: iscsi          State: ready      I_T nexus information:      LUN information:          LUN: 0              Type: controller              SCSI ID: IET     00010000              SCSI SN: beaf10              Size: 0 MB, Block size: 1              Online: Yes              Removable media: No              Readonly: No              Backing store type: null              Backing store path: None              Backing store flags:           LUN: 1              Type: disk              SCSI ID: IET     00010001              SCSI SN: beaf11              Size: 105 MB, Block size: 512              Online: Yes              Removable media: No              Readonly: No              Backing store type: rdwr              Backing store path: /var/lib/tgtd/cluster01/volume01.img              Backing store flags:           LUN: 2              Type: disk              SCSI ID: IET     00010002              SCSI SN: beaf12              Size: 1049 MB, Block size: 512              Online: Yes              Removable media: No              Readonly: No              Backing store type: rdwr              Backing store path: /var/lib/tgtd/cluster01/volume02.img              Backing store flags:       Account information:      ACL information:          ALL  

上記のようにvolume01.imgとvolume02.imgがLUNとして構成されていればOKです。それぞれこの後で、Quorum Diskと共有データ領域として使用します。

node01とnode02では、それぞれ次の手順でiSCSI LUNを認識させます。

  # chkconfig iscsi  # service iscsi start  # iscsiadm -m discovery --type sendtargets --portal 192.168.8.1  # service iscsi restart  

fdiskで見て、100MBの/dev/sdaと1GBの/dev/sdbが認識されていればOKです。(仮想マシンに接続した仮想ディスクは、virtioドライバを使っているので/dev/vdXXの前提です。)なお、iSCSIについては、プロのためのLinuxシステム構築・運用技術の第3章に詳しく書いてあります。


クラスタ構成の準備

いよいよクラスタの構成ですが、初めに下準備をしておきます。これは、node01、node02で共通に実施します。

ricciサービスを起動します。これはリモート管理用のデーモンで、cluster.confを動的に変更する際に必要になります。

  # chkconfig ricci on  # service ricci start  

また、リモート管理の際にricciユーザのパスワードで認証するため、事前にパスワードの設定が必要です。

  # passwd ricci  

クラスタのトポロジーを管理するcmanとリソースの監視を行うrgmanagerは自動起動しないようにします。障害などでノードが再起動した際に、障害が残ったノードが勝手にクラスタに参加するのを防ぐためです。


Windows XPでは、コマンドが動作しない見つける
  # chkconfig cman off  # chkconfig rgmanager off  

クラスタを起動・停止するためのスクリプトを4つ用意します。それぞれ、ローカルノードのクラスタの開始・停止と、全ノードのクラスタの開始・停止です。

/usr/local/bin/clstart

  #!/bin/sh  service cman start  service rgmanager start  

/usr/local/bin/clstop

  #!/bin/sh  service rgmanager stop  service cman stop  

/usr/local/bin/clstart_all

  #!/bin/sh  ssh node01 /usr/local/bin/clstart &  ssh node02 /usr/local/bin/clstart &  wait  

/usr/local/bin/clstop_all

  #!/bin/sh  ssh node01 /usr/local/bin/clstop &  ssh node02 /usr/local/bin/clstop &  wait  

実行権も忘れずに設定します。

  # chmod u+x /usr/local/bin/clst*  

続いて、Quorum Diskをフォーマットします。これは、node01からのみ実施します。

  # mkqdisk -c /dev/sda -l qdisk01  mkqdisk v3.0.12    Writing new quorum disk label 'qdisk01' to /dev/sda.  WARNING: About to destroy all data on /dev/sda; proceed [N/y] ? y  Warning: Initializing previously initialized partition  Initializing status block for node 1...  (中略)  Initializing status block for node 15...  Initializing status block for node 16...  

メモメモ

Quorum Diskは、各ノードが定期的に生存情報を書き込むことで、お互いの状態を確認しあいます。このコマンドの出力を見ると16ノード分の「状態書き込みエリア」が確保されていることが分かります。現在の仕様では、Quorum Diskを使用する場合は最大16ノード構成になるため、ここでは最大ノード数分のエリアを確保しています。

両方のノードで次のコマンドを実行して、Quorum Diskとして認識されることを確認します。

  # mkqdisk -L  mkqdisk v3.0.12    /dev/block/8:0:  /dev/disk/by-id/scsi-1IET_00010001:  /dev/disk/by-path/ip-192.168.8.1:3260-iscsi-iqn.2011-08.com.example.yourhost:tgt01-lun-1:  /dev/sda:  	Magic:                eb7a62c2  	Label:                qdisk01  	Created:              Thu Aug  4 16:37:37 2011  	Host:                 node01  	Kernel Sector Size:   512  	Recorded Sector Size: 512  

データ領域の共有ディスクをフォーマットします。これもnode01のみで実施します。

  # mkfs.ext4 /dev/sdb  

両方のノードで/data01にマウントできることを確認します。両ノードで同時にマウントしないように注意してください。

  # mkdir /data01  # mount /dev/sdb /data01  # umount /data01  

クラスタ構成ファイルの作成

お待ちかねのクラスタの構成です。High Availability Add-Onでは、クラスタの構成は1つの設定ファイル/etc/cluster/cluster.confにすべてまとめてXMLで記載します。分かりやすいです。問い合わせ対応の際もまずはこのファイル1つ送ってもらえば、ほとんどの確認ができます。

まずは、クラスタの基本構成だけを記載したのがこちらです。

  xml version="1.0"  config_version="1" name="cluster01">      expected_votes="3"/>                  name="node01h" nodeid="1" votes="1">                                     name="virsh_reboot">                      name="kvmhost01" port="RHCSvm01"/>                                                                 name="node02h" nodeid="2" votes="1">                                     name="virsh_reboot">                      name="kvmhost01" port="RHCSvm02"/>                                                                   token="20000"/>      interval="1" label="qdisk01" master_wins="1" tko="10" votes="1"/>                  name="kvmhost01" agent="fence_virsh" ipaddr="192.168.8.1" login="root" passwd="XXXXX" option="reboot"/>            

ポイントだけ簡単に説明します。


Quorumの設定

Quorumはハートビートネットワークが分断して、クラスタが複数の島に分かれたときに生き残る島を決定する仕組みです。これには、島が持っている"votes"の値を計算する必要があります。(2ノード構成の場合は、1対1に分かれるしかないのであまり深い意味はありませんが・・・。)

まず、各ノードは1vote持っており、Quorum Diskも1vote持っているので、すべてが正常に稼働している時はクラスタ全体で3votesになります。これをここで指定します。


Win XPの上でSHA1SUMを実行する方法
      expected_votes="3"/>  

クラスタに参加するノードの設定

"clusternode"タグに1ノードずつ記載します。

          name="node01h" nodeid="1" votes="1">                                     name="virsh_reboot">                      name="kvmhost01" port="RHCSvm01"/>                                                       

nameオプションは、ハートビートネットワークのアダプタ名を指定します。nodeidは重複しない値を指定すること。

fenceタグは、ハートビートが切断するなどして、クラスタマネージャがこのサーバを強制再起動すると判断した時に用いる再起動方法です。node01が障害と判断すると、node02がここに指定された方法でnode01を再起動します。したがって、この方法はnode02から実行できる必要があります。ここで指定するmethodとdeviceの実体は、この後のfencedeviceで定義されます。

                name="kvmhost01" agent="fence_virsh" ipaddr="192.168.8.1" login="root" passwd="XXXXX" option="reboot"/>        

ここでは、KVMのホストLinuxにlibvirtで接続して、VMを強制再起動するという仕組みを用いています。先に説明したように、ハートビート・ネットワークが切れているかもしれない状況で実施するものですので、ハートビートネットワークとは独立した管理ネットワーク経由で接続するようにIPを指定しています。ホストLinuxのrootパスワードが入っているのが気になる人は、SSH公開鍵認証も利用できます。passwdオプションの代わりにidentity_fileオプションで秘密鍵を指定します。先のclusternode側の設定にあるportオプションはlibvirtから見えるVM名を指定します。


Quorum Diskの設定

Quorum Diskに関する設定はここです。

      token="20000"/>      interval="1" label="qdisk01" master_wins="1" tko="10" votes="1"/>  

各ノードは、interval(1秒)ごとにQuorum Diskに生存情報を書き込みます。tko(10回)連続して生存情報が確認されないノードは死亡したと判断されて、先のFencedeviceで強制再起動されます。あるいは、Quorum Diskにtko回連続で書き込めないことに自分で気づいた場合は、自発的に再起動します。つまり、Quorum Diskによる障害検知は10秒以内に行われます。Quorum Diskは、ハートビートよりも"確実"な障害検知を提供する仕組みなので、ハートビート切断による障害検知は、これより遅くする必要があります。がハートビートによる障害検知の時間指定です。この例では20000msec(20秒)になります。

Quroum Disk的にはノードは生きているのに、ハートビート切断が起きた場合にどうなるか。。。。ですが、ここでは、master_winsオプションを指定しているので、内部的に決定されるマスターノードが生き残って、相手のノードは強制再起動されます。

ちなみに・・・・

あまり推奨される構成ではありませんが、サービスネットワークとハートビートネットワークを兼用する構成の場合、この方法では困ることがあります。例えば、サービス用のNICの障害でハートビートが切れた場合、どちらになるかよく分からない非マスターノードではなくて、NIC障害がおきたノードの方に死亡してもらう必要があります。このような場合は、master_winsオプションを外して、代わりに、heuristicを指定します。

      interval="1" tko="10" votes="1" label="qdisk01">          program="/root/bin/pingcheck.sh" score="1" interval="2" tko="3"/>        

programで指定されたシェルをinterval(2秒)ごとに実行して、tko(3回)連続して0以外のリターンコードを返すとそのノードは自発的に死亡します。例えば、ゲートウェイにpingが通るか確認するシェルを利用すれば、NIC障害のノードが自爆して、もう一方のノードが生き残ります。

なお、cluster.confに文法的な間違いがないかどうかは、次のコマンドで確認ができます。

  # ccs_config_validate   Configuration validates  

クラスタの起動

node01で作成した/etc/cluster/cluster.confをnode02にもコピーしたら、さっそくクラスタを起動します。

node01で先に用意したスクリプトを実行します。


バッチファイルを作成する方法
  # clstart_all   Starting cluster:      Checking if cluster has been disabled at boot... [  OK  ]     Checking Network Manager... Starting cluster:      Checking if cluster has been disabled at boot... [  OK  ]     Checking Network Manager... [  OK  ]     Global setup... [  OK  ]     Loading kernel modules... [  OK  ]     Global setup... [  OK  ]     Loading kernel modules... [  OK  ]     Mounting configfs... [  OK  ]     Starting cman... [  OK  ]     Mounting configfs... [  OK  ]     Starting cman... [  OK  ]     Starting qdiskd... [  OK  ]     Starting qdiskd... [  OK  ]     Waiting for quorum... [  OK  ]     Starting fenced... [  OK  ]     Starting dlm_controld... [  OK  ]     Waiting for quorum... [  OK  ]     Starting fenced... [  OK  ]     Starting dlm_controld... [  OK  ]     Starting gfs_controld... [  OK  ]     Unfencing self... [  OK  ]     Joining fence domain... [  OK  ]     Starting gfs_controld... [  OK  ]     Unfencing self... [  OK  ]     Joining fence domain... [  OK  ]  Starting Cluster Service Manager: [  OK  ]  [  OK  ]  Starting Cluster Service Manager: [  OK  ]  

両ノードの/var/log/messagesをじっくり眺めてクラスタの起動の様子を堪能してください。起動が完了したら次のコマンドで状態を確認します。

  # clustat   Cluster Status for cluster01 @ Thu Aug  4 17:40:28 2011  Member Status: Quorate     Member Name                                   ID   Status   ------ ----                                   ---- ------   node01h                                           1 Online, Local   node02h                                           2 Online   /dev/block/8:0                                    0 Online, Quorum Disk    # cman_tool status  Version: 6.2.0  Config Version: 1  Cluster Name: cluster01  Cluster Id: 8208  Cluster Member: Yes  Cluster Generation: 12  Membership state: Cluster-Member  Nodes: 2  Expected votes: 3  Quorum device votes: 1  Total votes: 3  Node votes: 1  Quorum: 2    Active subsystems: 10  Flags:   Ports Bound: 0 177    Node name: node01h  Node ID: 1  Multicast addresses: 239.192.32.48   Node addresses: 192.168.9.121   

メモメモ

上記のコマンド出力の最後にMulticast addressが表示されているのは、ハートビートにマルチキャストを利用しているためです。実環境では、ハートビート・ネットワークのスイッチは、マルチキャストを通すように設定が必要です。

また、ここではシェルスクリプトとSSHを利用して、両方のノードのクラスタサービスを同時に起動している点に注意してください。1ノードずつ順番にクラスタサービスを起動してはいけません。1ノードだけクラスタサービスを起動すると、相手ノードの状態が分からないので、ノード障害と誤検知して、相手ノードの強制再起動を実行してしまいます。

・・・・いま、「あー。誤検知するのか。だめだなぁ」と思ったあなたは反省してください。仮に、相手ノードが障害で一時的にフリーズ状態だったらどうなるでしょう? 強制再起動せずにほっておいて、そのうちフリーズから回復して、突然、両ノードから共有ファイルにアクセスしたらどうなるでしょう??? HAクラスタは障害が発生している状況の下でその役割を果たすソフトウェアですので、常に安全サイドを考えて動作します。HAクラスタを運用する際は、クラスタの仕組みを理解した上で、常にそれぞれのノードの状態を考えながら操作してください。

この後は、それぞれのノードでハートビートネットワークのアダプタをifdownするなどして、擬似ハートビート障害を起こして何がおきるか確認してください。Quorum Diskへのアクセス障害を起こしたい時は、iptablesでiSCSIパケットをブロックするなどしてください。

  # iptables -A INPUT -m tcp -p tcp --sport 3260 -j REJECT  

擬似障害で強制再起動されたノードは、再起動後に次のコマンドで自ノードのクラスタサービスを起動すると再びクラスタに参加します。

  # clstart  Starting cluster:      Checking if cluster has been disabled at boot...        [  OK  ]     Checking Network Manager...                             [  OK  ]     Global setup...                                         [  OK  ]     Loading kernel modules...                               [  OK  ]     Mounting configfs...                                    [  OK  ]     Starting cman...                                        [  OK  ]     Starting qdiskd...                                      [  OK  ]     Waiting for quorum...                                   [  OK  ]     Starting fenced...                                      [  OK  ]     Starting dlm_controld...                                [  OK  ]     Starting gfs_controld...                                [  OK  ]     Unfencing self...                                       [  OK  ]     Joining fence domain...                                 [  OK  ]  Starting Cluster Service Manager:                          [  OK  ]  

サービスリソースの定義

それでは、このクラスタの上で実行するサービスを定義します。ここでは、IPアドレス(192.168.7.99)、ファイルシステム(/dev/sdbを/data01にマウント)、自作アプリケーションをHA化します。自作アプリケーションは事前に/etc/init.d/以下に配置するserviceスクリプトからstart/stop/statusが実行できるようにしておきます。ここでは、/etc/init.d/myapplを作っています。

ではおもむろに定義を書き下します。先のcluster.confの最上位のclusterタグの内側(子供)に入るように配置してくださいね。


                              name="dom01" ordered="1" restricted="1">                  name="node01h" priority="1"/>                  name="node02h" priority="2"/>                                    autostart="0" domain="dom01" name="service01">              address="192.168.7.99" monitor_link="on"/>              device="/dev/sdb" fstype="ext4" mountpoint="/data01" name="data_fs">                  

0 コメント:

コメントを投稿