CentOS6.5でDRBD8.4を使ってみる - vol.3 DRBD初期設定編

# しおり

[CentOS6.5でDRBD8.4を使ってみる - vol.0 準備編](http://qiita.com/takehironet/items/4d26198798fb4b7454f8)
[CentOS6.5でDRBD8.4を使ってみる - vol.1 インストール編](http://qiita.com/takehironet/items/c90cd89fb621e570571f)
[CentOS6.5でDRBD8.4を使ってみる - vol.2 Corosync設定編](http://qiita.com/takehironet/items/61a3da51af3b32957872)
[CentOS6.5でDRBD8.4を使ってみる - vol.3 DRBD初期設定編](http://qiita.com/takehironet/items/13518725ee7c694efe90)
[CentOS6.5でDRBD8.4を使ってみる - vol.4 CRM設定編](http://qiita.com/takehironet/items/486bcdfe5609c67d5148)

# DRBDの初期設定

## global_common.confの設定

`/etc/drbd.d/global_common.conf` を編集します(以下はコメント行を省略しています)。

```plain:global_common.conf
global {
        usage-count no;
}

common {
        handlers {

        }

        startup {
        }

        options {
        }

        disk {
                resync-rate 50M;
        }

        net {
                protocol C;
                csums-alg sha1;
                verify-alg sha1;
        }
}
```

`usage-count no;` はLINBIT社に利用情報を送信しないようにする設定です。
LINBIT社の[利用統計サイト](http://usage.drbd.org/)に情報を提供する場合には `usage-count yes;` で構いません。

`resync-rate 50M;` は再同期の場合の帯域制御です。単位はbytes/secondです。

`protocol C;` は同期プロトコルのモードで、基本的にモードCを使います。それぞれのモードと意味は次のとおりです。

* protocol A: 非同期モード。対向ノードに送信して書き込み完了とする
* protocol B: メモリ同期モード。対向ノードが受信して、メモリに格納された時点で書き込み完了とする
* protocol C: 同期モード。対向ノードが受信して、ディスクに書き込みをした時点で書き込み完了とする

`csums-alg sha1;` は更新されたブロックの検出に使用するアルゴリズムをSHA1に設定しています。
`crc32c` や `md5` も選べるので、負荷と確実性を天秤にかけて選択します。

`verify-alg sha1;` はブロックデバイス全体をスキャンして再確認(verify)する際に使用するアルゴリズムをSHA1に設定しています。
verifyはCRONで定期的に実行するのが理想であり、その際の負荷や速度、確実性を考慮し、アルゴリズムを選択します。

## リソースの定義

`/etc/drbd.d/r0.res` を作成してリソース(デバイス)を定義します。

```plain:r0.res
resource r0 {
        meta-disk internal;
        device /dev/drbd0;
        disk /dev/vdb1;

        on drbd1 {
                address 192.168.130.18:7788;
        }
        on drbd2 {
                address 192.168.130.19:7788;
        }
}
```

`r0` という名前のDRBDリソースを定義します。

`meta-disk internal;` は `/dev/vdb1` の中にメタ情報を持つことを指定しています。

`on drbd1` や `on drbd2` はノード別の設定をしています。
`on ～` は `hostname` で表示されるものを設定します。

## Firewallの設定

リソースで使用するポートでのTCP通信を許可します。双方向に接続がされるので、注意します。

今回は次の行を `/etc/sysconfig/iptables` に追加して `service iptables restart` しておきます。

```plain
-A INPUT -m tcp -p tcp --dport 7788 -j ACCEPT
-A INPUT -m tcp -p tcp --sport 7788 -j ACCEPT
-A OUTPUT -m tcp -p tcp --dport 7788 -j ACCEPT
-A OUTPUT -m tcp -p tcp --sport 7788 -j ACCEPT
```

## DRBDデバイスの設定

### パーティションの用意

fdiskなどのパーティショニングツールで、DRBDに使用するボリュームを用意します。今回は`/dev/vdb`にパーティションを1つ作成し`/dev/vdb1`としています。

リソースの定義と必ず一致させます。

`/dev/vdb`となっているのは検証環境がKVMで動く仮想マシンであり、ゲストでvirtioドライバを使用しているからです。

### メタデータの作成

両方のノードで、先ほど作成したパーティションにメタデータを書き込みます。

```plain
drbdadm create-md r0
```

DRBDリソースとして使おうとするボリュームにファイルシステムが見つかると、こんなエラーが表示されます。

```plain
md_offset 2146430976
al_offset 2146398208
bm_offset 2146332672

Found ext3 filesystem
     2096128 kB data area apparently used
     2096028 kB left usable by current configuration

Device size would be truncated, which
would corrupt data and result in
'access beyond end of device' errors.
You need to either
   * use external meta data (recommended)
   * shrink that filesystem first
   * zero out the device (destroy the filesystem)
Operation refused.

Command 'drbdmeta 0 v08 /dev/vdb1 internal create-md' terminated with exit code 40
```

そんなときは、適当にゼロを書いてファイルシステムを破壊してしまえば、メタデータの作成は成功します。

```plain
dd if=/dev/zero of=/dev/vdb1 bs=512 count=1024
```

### リソースの有効化

リソース `r0` を有効化します。両ノードで以下を実行します。

```plain
drbdadm up r0
```

`cat /proc/drbd` でリソースの状態を確認します。

```plain
version: 8.4.5 (api:1/proto:86-101)
GIT-hash: 1d360bde0e095d495786eaeb2a1ac76888e4db96 build by mockbuild@Build64R6, 2014-08-17 19:26:04
 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r-----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:2096028
```

`cs:Connected` となっており、 `ro:Secondary/Secondary` 続けて `ds:Inconsistent/Inconsistent` であれば成功です。

### 初期同期

最初に両方のデバイスを同期します。
`drbd2` を同期 *先* として`drbd1` からコピーします

同期 *先* の `drbd2` の内容を破棄するコマンドを実行します。これは同期 *先* の `drbd2` で実行します。

```plain
drbdadm invalidate r0
```

すると `cat /proc/drbd` の結果が次のようになります。

```plain
version: 8.4.5 (api:1/proto:86-101)
GIT-hash: 1d360bde0e095d495786eaeb2a1ac76888e4db96 build by mockbuild@Build64R6, 2014-08-17 19:26:04
 0: cs:SyncSource ro:Secondary/Secondary ds:UpToDate/Inconsistent C r-----
    ns:2048 nr:0 dw:0 dr:66560 al:0 bm:0 lo:3 pe:0 ua:3 ap:0 ep:1 wo:f oos:2029468
        [>....................] sync'ed:  3.4% (2029468/2096028)K
        finish: 0:00:30 speed: 66,560 (66,560) K/se
```

`drbd1` が同期 *元* なので、 `cs:SyncSource` `ds:UpToDate/Inconsistent` となっています。

同期 *先* の `drbd2` では `cs:SyncTarget` `ds:Inconsistent/UpToDate` となります。

同期完了すると、以下のように `cs:Connected` `ds:UpToDate/UpToDate` に変化します。

```plain
version: 8.4.5 (api:1/proto:86-101)
GIT-hash: 1d360bde0e095d495786eaeb2a1ac76888e4db96 build by mockbuild@Build64R6, 2014-08-17 19:26:04
 0: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
    ns:0 nr:8192 dw:8192 dr:4192056 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
```

### 昇格

リソースを昇格して `Primary` にしなければ、 `/dev/drbd0` は読み書きできません。
マウントして利用するにも、ファイルシステムを作る必要がありますので、リソースを `Primary` にします。

ここでは `drbd1` で作業します。

```plain
drbdadm primary r0
```

`ro:Primary/Secondary` に変化することを確認します。

```plain
version: 8.4.5 (api:1/proto:86-101)
GIT-hash: 1d360bde0e095d495786eaeb2a1ac76888e4db96 build by mockbuild@Build64R6, 2014-08-17 19:26:04
 0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
    ns:8192 nr:0 dw:0 dr:4192720 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
```

これで `mkfs.ext4 /dev/drbd0` が成功します。ちなみに、 `Secondary` のノードで実行すると失敗します。

```plain
[root@drbd2 ~]# mkfs.ext4 /dev/drbd0
mke2fs 1.41.12 (17-May-2010)
mkfs.ext4: Wrong medium type while trying to determine filesystem size
```