アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

LVMのスナップショット機能を使ってXenイメージのバックアップ

今回は、社内サーバに関するバックアップの一環で、LVMのスナップショットを使用してXenイメージのバックアップをとってみました。

LVM(Logical Volume Manager)とは?


名前の通り、論理ディスクを管理する機能です。
通常のパーティションだと、サイズを動的に変更したり、複数のディスクにまたがって一つのパーティションにするなど出来ませんが、そこにLVMを噛ませることにより、柔軟に管理出来るようになります。

LVM概要


LVMは既存のパーティション上に乗って仮想化する機構なので、下記の3種類のレイヤがあります。
・PV(Physical Volume)
 物理的に書き込む領域です。(HDDのパーティションなど)
 領域をLVMのPVとして初期化した際に、PE(Physical Extents)という単位で分割され、この単位で論理領域の確保が出来るようになります。

・VG(Volume Group)
 PVをまとめたもので、LVMとして使用出来る領域になります。
 物理領域(PV)をまとめて一つの デバイス にしたものと思ってください。

・LV(Logical Volume)
 実際に使用する領域。
 VGにパーティションを切ってしたものとでも思ってください。

細かい説明はググってください。

スナップショットとは?


ある時点に記録されている状態を取っておいたもの。
スナップショットを作成した瞬間の情報を保持することが出来ます。

Xenのイメージなど、常時使用中で何か書き込みがあるファイルの場合、cpなどで普通にコピーするとコピー中もデータが書き換わり不整合が起てしまうので、スナップショットを作成してコピーすることにより、破損を最小限(突然電源を落とした程度)にとどめてバックアップ出来ます。
ただし、Copy on write で実装されている関係で、スナップショットを作成した瞬間から書き込みコストが増大しますので、恒久的なバックアップには使えません。(使えないこともないですが遅くなります)
そのため、今回はスナップショットからデータを吸い出したあとに消去する手法にしました。

スナップショットの作成


スナップショットの作成は下記のようにします。


lvcreate -s -L 2G -n "snap_20120719" "/dev/xenimages/xen-image-disk0"

簡単ですね。

-s スナップショットとして作成
-L スナップショット領域のサイズ(元ボリューム側で変更されたサイズがこのサイズを超えるまで使用可能。
  超えるとスナップショットのデータが壊れる可能性あり)
-n スナップショットの名前
元ボリュームのパス

となります。

実際の作業


基本的な流れは、下記のようになります。
・スナップショット作成
・マウント
rsyncで内容をコピー
・アンマウント
・スナップショット削除

毎回手動で実行するのは馬鹿馬鹿しいので、cronで実行出来るようにスクリプト化しました。
ついでに古いものの自動削除も。



#!/bin/bash

export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

function backup {
    orgvol="$1";

    # スナップショットパス定義
    snapvol="$orgvol-snap_`date '+%Y%m%d%H%M%S'`"

    if [ -b "$snapvol" ];then
        echo "$snapvol が存在します"
        return 9;
    fi

    if [ ! -b "$orgvol" ];then
        echo "$orgvol が存在しません"
        return 9;
    fi
    
    ret=0

## LVM自体バックアップ版
## 無駄が多いのでボツ
#    # スナップショットのエリアをddする
#    echo "バックアップ中..."
#    if ! dd if="$snapvol" | gzip > "$backupdir/`basename $snapvol`.gz";then
#        echo "ddの実行に失敗"
#        ret=2
#    fi

    # バックアップ先ディレクトリ作成
    snapbackupdir="$backupdir/snap_`basename $snapvol`"
    test ! -d "$snapbackupdir"  & & mkdir "$snapbackupdir";
    if [ ! -d "$snapbackupdir" ];then
        echo "バックアップディレクトリの作成に失敗"
        return 3
    fi
    # マウント先作成
    echo "tmpmount作成"
    test ! -d "tmpmount"  & & mkdir "tmpmount"
    if [ ! -d "tmpmount" ];then
        echo "マウント先ディレクトリの作成に失敗"
        return 4
    fi

    # LVMスナップショットを取る
    echo "スナップショット作成 `basename $snapvol`" "$orgvol"
    if ! lvcreate -s -L 2G -n "`basename $snapvol`" "$orgvol";then
        echo "スナップショットの作成に失敗"
        return 1;
    fi

    # スナップショットをマウントしてrsync
    echo "mount"
    if ! mount -o ro,nouuid "$snapvol" "tmpmount";then
        echo "マウントに失敗"
        ret="5"
    fi

    if [ $ret -eq 0 ];then
        echo "rsync中..."
        if ! rsync -auv --progress "tmpmount/" "$snapbackupdir/";then
            echo "rsync実行に失敗"
            ret=6
        fi
    fi

    # umount
    echo "umount"
    if ! umount "tmpmount";then
        echo "umountに失敗"
        ret=7
    fi

    # rmdir
    echo "rmdir"
    if ! rmdir "tmpmount";then
        echo "tmpmount削除に失敗"
        ret=8
    fi

    # スナップショットを削除
    echo "スナップショット削除"
    if ! lvremove -f "$snapvol";then
        echo "スナップショット削除に失敗"
        ret=4
    fi
    
    return $ret;
}

function rotate {
    # 1日分以降を削除
    backupdir="$1"
    for dir in $backupdir/snap_*; do 
        # unixtimeに変換
        utime="`echo $dir | perl -MTime::Local -pe 's/.*(201\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/($6,$5,$4,$3,$2-1,$1)/; $_=(timelocal eval $_)."\n"'; `"
        time7="$((`date +%s` - 86400))"
        if [ "$utime" -gt 1240432473 ];then # 念の為
            if [ "$utime" -lt "$time7" ];then
                rm -rfv "$dir"
            fi
        fi
    done
}

# バックアップするデバイス スペース区切りで複数指定可
lvmnames="/dev/xenimages/xen-image-disk0"

# バックアップ先
backupdir="/mnt/backup"

rotate $backupdir;

# 全てのボリュームに対して実行
for orgvol in $lvmnames;do
    backup "$orgvol"
    res="$?"
    if [ "$res" -ne 0 ];then
        echo "code: $res" | /usr/bin/mail -s "[`hostname`] LVM snapshot faild" mailaddress@example.com
    fi
done


単純ですがこんな感じで書いて見ました。
これを毎日1回実行すればスナップショット使用してバックアップ出来ます。
なお、ディレクトのパスとか名前は環境によって違うのであくまでも 参考まで にしてください。
もし実際のサーバで試す場合には、壊れてもいいサーバでテストを入念にしてください。

バックアップしようとして、全部消えるとか洒落にならないですよね。
ちょっとしたバグで、多量のデータが消えると言う悪夢がたまにあるので・・・。

使用感


弊社の場合、対象が400GB程度ある+バックアップ先にGlusterFSを使用しているためバックアップ自体は遅いですが、数時間あれば終わります。
バックアップ中はパフォーマンスは落ちますが、深夜なのでそれほど苦情は出ていないようです。
※詳細なパフォーマンスについては測定もできますが、本番運用中+GlusterFSを使用しているため速度的に不安定で大したデータは取れないので、そのうちに環境できたらやるかもしれません。

また、この方法だとディスクのフルバックアップになるため無駄が多くなります。どうにかして差分バックアップ出来ないか模索中なので、出来たらブログの記事にします。

以上、LVMスナップショットを使ったバックアップの紹介でした。

SoftwareRAID + LVM + RAID1 移行(+ パーティション縮小)してみました

サーバーと言えば、冗長化は必須です。
自宅のXenサーバーもそろそろRAID化したくなってきました。
なにしろ、数年前に買ったMaxtor製250GBで、いくら高耐久モデルといっても1台では心配なので、余った別ディスクのパーティションを使用してRAID1構成にするこに。
もちろん、パーティション切って、RAID化して、データをコピーして、コピー元を消してRAIDの片割れとして追加すればRAID化出来ますが、せっかくLVMを使用しているので止めずにRAID1化してみました。

LVMについて
LVMとは大まかに言えばドライブの仮想化です。
複数のパーティションを一まとめの仮想ドライブにし、その中をそれぞれのパーティションに分配するイメージで、物理的は配置は気にしなくて良いのでリサイズなどが自由にできます。
細かいことはググってください。

★注意★
以下の内容を試す場合にはあくまでも自己責任でお願いします。
なお、クリティカルなサーバーなどで実験される際には、必ず同じ構成の壊れてもいい環境で十分にテストされることを推奨いたします。

今回の構成

/dev/hda8: 既存のパーティション
/dev/sdb2: 新規追加
以上2台で構成します。
なお、hda8には、PVが一つあり、その上にVG(lvm0)が一つだけ乗っています。

手順については、
1・sdb2をフォーマットし、PVを作成
2・lvm0にmd7を追加
3・hda8のエクステントををsdb2へ移動
4・hda8を切り離し
5・hda8をmd7に追加
と言う感じになります。

では、早速移行作業をしていきます。

1・sdb2をフォーマットし、PVを作成
fdiskにてsdb2を作成し、typeを"fd"(Linux RAID Autodetect)に設定したのち、以下コマンドを実行。


$ sudo mdadm --create /dev/md7 --level=1 --raid-devices=2 /dev/sdb2 missing

これで、sdb2の上にmd7が作成します。

2・lvm0にmd7を追加


$ sudo pvcreate /dev/md7     #PV作成
$ sudo vgextend lvm0 /dev/md7    #lvm0にmd7を追加


3・hda8のエクステントををsdb2へ移動
今回の肝"pvmove"を実行します。
これは、指定したPV(hda8)の物理エクステントを同じVG内の別のPV(md7)に移動します。
(完了までには多少時間が掛かります)


$ sudo pvmove /dev/hda8


4・hda8を切り離し
vgreduceにて、既存のVG(lvm0)からPV(hda8)を取り除きます。


$ sudo vgreduce lvm0 /dev/hda8


5・hda8をmd7に追加
1番と同じ手順で行けば良かったのですが、sdb2のサイズ指定を間違えてしまいました。


$ sudo fdisk -l /dev/sdb
(中略)
/dev/sdb2           60802       91201   244188000   fd  Linux raid autodetect
$ sudo fdisk -l /dev/hda
(中略)
/dev/hda8            3795       30515   214636401   8e  Linux LVM

pvmoveで移動し直して縮小すれば問題ないですが、せっかくなのでこのままリサイズにチャレンジします。

まずは、PVのサイズを小さくします。


$ sudo pvresize --setphysicalvolumesize 204G /dev/md7
$ sudo pvscan
  PV /dev/md7    VG lvm0            lvm2 [204.00 GB / 16.00 GB free]
  PV /dev/hda8                      lvm2 [204.69 GB]
  Total: 2 [408.69 GB] / in use: 1 [204.00 GB] / in no VG: 1 [204.69 GB]


次にmd7のサイズを変更します


$ sudo mdadm /dev/md7 --grow --size=214628400

$ cat /proc/mdstat
Personalities : [raid1]
md7 : active raid1 sdb2[0]
      214628400 blocks [2/1] [U_]

縮小出来たっぽい?
Raidのサイズは縮小されているようです。


次はsdb2のサイズ変更


$ sudo fdisk  /dev/sdb

The number of cylinders for this disk is set to 91201.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): p

Disk /dev/sdb: 750.1 GB, 750156374016 bytes
255 heads, 63 sectors/track, 91201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1       60801   488384001   fd  Linux raid autodetect
/dev/sdb2           60802       91201   244188000   fd  Linux raid autodetect

Command (m for help): d
Partition number (1-4): 2

Command (m for help): p

Disk /dev/sdb: 750.1 GB, 750156374016 bytes
255 heads, 63 sectors/track, 91201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1       60801   488384001   fd  Linux raid autodetect

Command (m for help): d
Partition number (1-4): 2

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (60802-91201, default 60802):
Using default value 60802
Last cylinder or +size or +sizeM or +sizeK (60802-91201, default 91201): 87521

Command (m for help): p

Disk /dev/sdb: 750.1 GB, 750156374016 bytes
255 heads, 63 sectors/track, 91201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1       60801   488384001   fd  Linux raid autodetect
/dev/sdb2           60802       87521   214628400   83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table.
The new table will be used at the next reboot.
Syncing disks.




後は、hda8をRAIDに追加するだけ?


$ sudo mdadm --manage /dev/md7 --add /dev/hda8
mdadm: added /dev/hda8

$ cat /proc/mdstat
Personalities : [raid1]
md7 : active raid1 hda8[2] sdb2[0]
      214628400 blocks [2/1] [U_]
      [>....................]  recovery =  3.4% (7494976/214628400) finish=118.2min speed=29184K/sec


できた!!
思ったよりハマりましたが何とか完了。
(ちなみに、サイズギリギリでやった場合にhda8が小さいといわれうまく行かなかったので、PVのサイズを小さくして再チャレンジしました)

これで再構成が完了すればRAID1運用出来ます。

LVMと言うより、パーティションのリサイズの方が多くなってしまいました・・・。

おまけ
fdisk後に再起動したくない場合は、


$ sudo partprobe

でOK

DRBD+heartbeat+LVM(on Fedora Core10)によるクラスタリング

こんにちは、亀本です。

今回は、PHPとかから少し離れて、サーバのクラスタリングのお話です。
ちょっと仕事で冗長化システムを組む必要があったので、せっかくなので記事にまとめました。


さて、ここで目指すのは、DRBDを使ったデータレプリケーションサーバ( Master / Slave 構成 )の自動フェイルオーバークラスタ( 非フェイルバック構成 )です。

ネットワーク構成としては、ルータから結ばれるLAN(eth0に接続)とは別に、eth1で1対1のLAN接続を行います。
また、heartbeatでのクラスタ構成後は、eth0に仮想IPとして192.168.1.100を割り振るようにします。

eth1の設定は、



# vi /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
HWADDR=00:00:00:00:00:00
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.50.1
NETMASK=255.255.255.0


のような感じになります。

また、他にもheartbeat用にttyS0 (RS-232Cのシリアル) をクロスで結んでいます。
こちらは特に設定の必要はありませんし、付けなくてもシステムは組めます。


1. サーバ構築時のパーティション設定

ハードディスク構成は、Hardware RAID 1+0 ベースの1 Logical Drive でやってます。
作成するパーティション構成としては、最終的に



○物理レイヤ
/dev/cciss/c0d0
     c0d0p0 LVM Volume
     c0d0p1 /boot     # ブートローダ

○LVM
/dev/LVMVol1/lv_root /
/dev/LVMVol1/lv_var  /var  # なんとなく分けた。このあたりはご自由に。。
/dev/LVMVol1/lv_data /data # drbdによるレプリケーション対象ドライブ。あとから/dev/drbd0でラッピングされます。
/dev/LVMVol1/lv_meta (none) # drbdのmetaデータ格納用ドライブ


という構成を目指します。LVMVol1がLVMのボリュームグループ名、lv_rootなどはLV名です。

この構成を作成するにあたり、OSのインストール時に注意すべき事として、lv_metaに相当するmetaデータ用パーティションの取り扱いがあります。
この領域は、DRBDがメタデータを作成する際に独自ファイルシステムを作成しようとするので、OS側でフォーマットされてしまっているとエラーが発生する事があります。
なので、OSインストール時には作成せず、領域だけ残すようにして、root,var,data領域を作成しましょう。
また、後々サーバ名も必要になるので、localhost.localdomainなどではなく、ちゃんとしたサーバ名をつけておくようにしてください。

なお、もし構築済みのサーバでLVM領域をめいっぱい使いきってしまっている場合には、LVM領域の変更をする必要があります。
その方法についても、あとで少しふれておきます。


2. DRBDのインストール

ここでは、最小構成(Base + Vimぐらい) でインストールした前提で話を進めます。
なお、yumの設定やyum updateはやってある前提です。

2.1 コンパイルに必要なツールの準備

Fedora CoreではDRBDのrpmパッケージは用意されておらず、自前でコンパイルする必要があります。
そのため、まずDRBDのrpm作成に必要なツール類をインストールします。



# yum install make gcc glibc flex rpm-build


自分の環境ではmake,glibcは入っていたので、gccflexrpm-buildとその関連パッケージがインストールされました。

また、DRBDのコンパイルにはカーネルのソース等も必要になるので、それらも入手しておきます。



# yum install kernel-devel
# yumdownloader --source kernel
# rpm -ivh kernel-2.6.27.29-170.2.78.fc10.src.rpm


rpmのインストールではユーザ/グループのwornが出ますが気にしなくて大丈夫です。

2.2 DRBDのコンパイルとインストール

次に、DRBDのソースを取得してきて、DRBDをコンパイルします。
DRBDのソースは、http://oss.linbit.com/drbd/ からダウンロードできます。



# wget http://oss.linbit.com/drbd/8.3/drbd-8.3.2.tar.gz


あとは、以下のようにソースを展開してmakeすれば、rpmの作成まで一括でやってくれます。



# tar xvzf drbd-8.3.2.tar.gz
# cd drbd-8.3.2
# make rpm


make終了後に以下のように作成したrpmの一覧が出れば成功です。



You have now:
-rw-r--r-- 1 root root  220334 2009-08-14 02:09 dist/RPMS/x86_64/drbd-8.3.2-3.x86_64.rpm
-rw-r--r-- 1 root root 1079065 2009-08-14 02:09 dist/RPMS/x86_64/drbd-km-2.6.27.29_170.2.78.fc10.x86_64-8.3.2-3.x86_64.rpm


あとは、このrpmを展開すれば、インストールは完了です。



# cd dist/RPMS/x86_64/
# rpm -ivh *.rpm


2.3 DRBDインストール後の注意点

DRBDは、カーネルモジュール作成時にカーネルのソースを利用しているため、カーネルのバージョンが変わってしまうと動かなくなってしまう場合があります。
そのため、カーネルのバージョンアップがかかるようなアップデートをかける場合には、DRBDの再構築も忘れずに行うようにしてください。
cronでyum のアップデートを行うように設定している場合は、アップデート対象からkernelを除外しておくなどの対応をしておき、kernelのメンテナンスだけは手動で行うようにするとよいでしょう。



# vi /etc/yum.conf
exclude=kernel*


3. DRBDのセットアップ

続けて、DRBDを動作させるためのセットアップを行っていきます。

3.1 DRBDのmetaデータについて

DRBDは、実際に共有されるデータ以外にも、変更データ管理用のmetaデータを作成しますが、そのmetaデータの管理方法には「データ領域に含める(internal)」「外部領域を利用する(external)」の2種類の方法が用意されています。

どちらが良いのか、というのは一概には言えないようなのですが、internalでやり方を書いてあるものは多くてもexternalでやっているドキュメントがあまり見当たらなかったので、今回は外部領域を利用する方法を紹介します。


3.2 metaデータ用LVの作成

まずはmetaデータを格納する領域を確保します。
どのくらい領域が余っているかは、以下のようにして確認できます。



# vgdisplay |grep Free
  Free  PE / Size       209 / 6.53 GB


自分の環境では、端数を残しておいたらこのくらいになりましたが、metaデータにはさすがにちょっと6Gは多い気もしますね。まぁ今回はこれで行きます。
次のようにして、LVを作成します。



# lvcreate -l 209 -n lv_meta LVMVol1
  Logical volume "lv_meta" created


容量をバイトサイズで指定したい場合には、-l 209の代わりに -L 6G などと指定してあげればOKです。

3.3 領域を使いきっていた場合

OSインストール時に領域を残してあれば上記の操作だけで大丈夫ですが、LVMの領域を使いきっていた場合には、何かしらのLVをリサイズして縮小し、使用領域を確保する必要があります。
/dev/LVMVol1/lv_data (ext3)を縮小する場合には



# lvdisplay -C |grep lv_data
  lv_data LVMVol1 -wi-ao 292.97G

# umount /data
# resize2fs /dev/LVMVol1/lv_data 290G
# lvreduce -L 290G /dev/LVMVol1/lv_data
# mount /data


とします。なお、リサイズに伴ってデータが欠損する危険はついて回りますので、そこは自己責任でお願いします。
(よほど使いこんでいなければ、大丈夫そうですが。。。)

これで、2Gちょっとぐらいの領域が新たに確保できるようになるので、あとは3.2で紹介した方法でmetaデータ用のLVを作ってください。

3.4 drbd.confの設定

ここまででmetaデータ用の領域が確保できたので、続けてDRBDの設定drbd.confを以下のように作成しましょう。



# vi /etc/drbd.conf

resource r0 {
  protocol B;

  handlers {
    pri-on-incon-degr "halt -f";
  }

  startup {
    wfc-timeout 120;
    degr-wfc-timeout 120;
  }

  syncer {
    rate 100M;
  }

  disk {
    on-io-error detach;
  }

  net {
    cram-hmac-alg "sha1";
    shared-secret "HogeHoge";
    after-sb-0pri disconnect;
    after-sb-1pri disconnect;
    after-sb-2pri disconnect;
    rr-conflict    disconnect;
  }

  on db1.example.com {
    device     /dev/drbd0;
    disk       /dev/LVMVol1/lv_data;
    address    192.168.50.1:7788;
    flexible-meta-disk /dev/LVMVol1/lv_meta;
  }

  on db2.example.com {
    device     /dev/drbd0;
    disk       /dev/LVMVol1/lv_data;
    address    192.168.50.2:7788;
    flexible-meta-disk /dev/LVMVol1/lv_meta;
  }
}


各項目の細かい説明は、man drbd.confや 邦訳( http://www.drbd.jp/documentation/drbd.conf.html )を参照してください。

ここでは、環境に合わせて必ず変更が必要な on句の説明をしておきます。

まず、on db1.example.com となっているonの後の名前は、uname -nで出てくる各サーバのホスト名である必要があります。それぞれの対象サーバで設定を行いましょう。
また、addressではそれぞれのサーバのIP、およびDRBDの通信に使うポート番号を指定します。

次にdiskとdeviceですが、diskが実際にDRBDが書き込みを行うデバイス本体で、deviceがDRBDのデバイス名です。
この設定では、/dev/drbd0というデバイスに対しての書き込みが、DRBDを経由してそれぞれのサーバの/dev/LVMVol1/lv_dataに書き込まれることになります。

こう設定すると、lv_dataデバイスはDRBDの支配下に置かれることになります。
そのため、今までlv_dataをマウントしていた/dataディレクトリは今後/dev/drbd0をマウントするようにシステムの設定を変更する必要があります。

最後に、flexible-meta-diskですが、これが先ほど作ったメタデータ格納用のデータ領域の指定です。

3.5 DRBDボリュームの作成

以上でdrbd.confの設定が終わったので、実際にDRBDのリソースを作成します。



# drbdadm create-md r0
md_offset 0
al_offset 4096
bm_offset 36864

Found some data
 ==> This might destroy existing data! <==

Do you want to proceed?
[need to type 'yes' to confirm]


ここで、yesとタイプして進めれば、metaデータの作成が完了し、DRBDを起動する準備が整います。
なお、create-mdの後に指定しているのはresourceの後ろに書いたリソース名で、この名前は自由に変えられます。

3.6 internalでやる場合の注意

metaデータ領域をinternalにする場合には、flexible-meta-diskの指定を[ internal ]変更する事で可能です。
共有対象となる領域内(今回で言えば/dev/LVMVol1/lv_data)にmetaデータを保存する領域を作成するので、この領域が何かしらのFileSystemでフォーマットされていると、こちらのFAQで参照できるようなエラーに当たる事があります。

その場合はFAQにしたがい、ボリュームを作り直すなりしてトライしてみてください。

4 DRBDの起動と同期

これまでの作業を、2台のサーバで設定し終えたら、DRBDの起動準備が整います。
あとは、DRBDを起動して同期作業を行いましょう。

4.1 モジュールのロード

まずは、DRBDのカーネルモジュールをロードします。



# modprobe drbd


以下のようになればOKです。



# lsmod|grep drbd
drbd                  225992  0


4.2 DRBDの起動

いよいよDRBDの起動です。以下のようにして、起動させてください。



# /etc/init.d/drbd start


2台のサーバのうち、最初に起動したサーバの方では以下のような警告が出ますので、yesとタイプして先に進み、もう1台も起動してください。



Starting DRBD resources: [ d(r0) s(r0) n(r0) ]..........
***************************************************************
 DRBD's startup script waits for the peer node(s) to appear.
 - In case this node was already a degraded cluster before the
   reboot the timeout is 120 seconds. [degr-wfc-timeout]
 - If the peer was available before the reboot the timeout will
   expire after 120 seconds. [wfc-timeout]
   (These values are for resource 'r0'; 0 sec -> wait forever)
 To abort waiting enter 'yes' [  52]:yes


各サーバのDRBDを起動したら、以下のようにして状態を確認してみましょう。



# cat /proc/drbd
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by root@db1.example.com, 2009-08-14 02:09:08
 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent B r----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:307200000


となり、cs:Connected ro:Secondary/Secondary と、両方ともセカンダリで接続されているのが分かります。
この状態ではまだ、/dev/drbd0はマウントする事ができません。


4.3 プライマリの設定とデータ同期

では、1台をプライマリに昇格し、/dev/drbd0をマウントしてデータ同期できるようにしましょう。
プライマリにしたいサーバで、以下のコマンドを実行します。



# drbdadm -- --overwrite-data-of-peer primary r0


これで、実行した側のサーバがプライマリに切り替わり、同時にデータの同期が開始されます。
セカンダリ側では何もする必要はありません。

初回同期の際には、差分の同期ではなく全データの完全同期が行われます。
その様子も、/proc/drbd をみる事で把握する事が出来ます。



# cat /proc/drbd
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by root@db1.example.com, 2009-08-14 02:09:08
 0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent B r----
    ns:8887460 nr:0 dw:0 dr:8888236 al:0 bm:542 lo:1710 pe:31 ua:1886 ap:0 ep:1 wo:b oos:298312664
        [>....................] sync'ed:  2.9% (291320/300000)M
        finish: 0:38:00 speed: 130,412 (80,064) K/sec


この同期が100%になれば、晴れてDRBDのレプリケーションが完成です。

4.4 DRBDボリュームのマウントと 設定変更

この時点で、プライマリ側では/dev/drbd0を利用する事が出来るようになり、書き込んだ内容はすべて同期されるようになります。



# mount -t ext3 /dev/drbd0 /data/


さて、これでDRBDは使えるようになりましたが、最後にrebootなどした際に謝ってlv_dataが/dataにマウントされてしまわないよう、fstabを変更して、以下のようにlv_dataの項目をコメントアウトしておきます。



# vi /etc/fstab

/dev/LVMVol1/lv_root    /                       ext3    defaults        1 1
#/dev/LVMVol1/lv_data    /data                   ext3    defaults        1 2
/dev/LVMVol1/lv_var     /var                    ext3    defaults        1 2
.
.
.


これで、誤ってlv_dataがマウントされてしまう事もなくなります。
なお、今回は最終的にheartbeatがDRBDの面倒を見ることになるので、ここではfstabに新しい設定などは加えていませんが、自分でマウントする場合などは



/dev/drbd0    /data                   ext3    defaults        1 0


のような設定を追加しておくと便利でしょう。

5. heartbeatのインストールとDRBD連携

DRBDの設置が完了したので、続けてheartbeatをインストールし、DRBDと連携させてみます。

5.1 インストール

Fedora Core 10では、heartbeatはyumでインストール可能です。



# yum install heartbeat


以上でインストール完了です。

5.2 設定とDRBD連動

では、これを2台のサーバで連動するように、設定します。

heartbeatの動作には、/etc/ha.d/ディレクトリの中に、
・authkeys
・ha.cf
・haresources
の3つを作成する必要があります。
多くの設定項目がありますが、付属のサンプルがあるのでこれをコピーして使うとよいでしょう。



# cp /usr/share/doc/heartbeat-2.1.3/authkeys /etc/ha.d/
# cp /usr/share/doc/heartbeat-2.1.3/ha.cf /etc/ha.d/
# cp /usr/share/doc/heartbeat-2.1.3/haresources /etc/ha.d/


これらを順に設定して行きます。
まず、authkeysは、以下の2行をコメントアウト解除します。



# vi /etc/ha.d/authkeys
auth 1
1 crc


また、パーミッションも次のように変更しておく必要があります。



# chmod 600 /etc/ha.d/authkeys


次にha.dは、以下のように項目を設定して行きます。
ほとんどがコメントアウトを解除するだけですが、一部値が違うものは変更してください。



# vi /etc/ha.d/ha.cf
keepalive 2
deadtime 30
warntime 10
initdead 120

udpport 694
baud    19200
serial  /dev/ttyS0 
ucast eth1 192.168.50.2

auto_failback off

node    db1.example.com
node    db2.example.com


ここで、ucastはeth1から192.168.50.2に向けてユニキャストでheartbeatの確認をする、という意味の設定で、192.168.50.2に該当するサーバでは
ucast eth1 192.168.50.1
のような設定になります。
また、node はheartbeatの対象となるサーバの、uname で取得できるサーバ名を設定します。

なお、baudとserialはシリアルケーブル用の設定なので、シリアルケーブルをつながない場合には必要ありません。

最後にharesourcesには、以下の1行を追加してください。



# vi /etc/ha.d/haresources

db1.example.com 192.168.1.100/24 drbddisk::r0 Filesystem::/dev/drbd0::/data::ext3


これらを設定したのに、heartbeatを再起動しましょう。(install時に自動的に起動しているので、再起動になります)

以上で、設定はすべて完了です。
heartbeatが正常にフェイルオーバーするかを確認するには、ifconfigやdfなどで設定情報を確認した後、現在プライマリとして動作しているサーバのheartbeatwをstopするなどして、セカンダリサーバがきちんと仮想IPを持ったり、/dataディレクトリに/dev/drbd0がマウントされていたりするかチェックすればよいでしょう。

また、stopしたheartbeatを再度startしても、自動フェイルバックせずにそのまま稼働し続けます。


だいぶ長くなってしまいましたが、これでベースシステムとしてのheartbeat + DRBD (+ LVM)の自動フェイルオーバークラスタの出来上がりです。

DRBD + heartbeatはちゃんと設定すると色々と細かい制御ができていい感じなので、ぜひぜひ活用していきたいですね。