DRBD + Keepalived + NFS on CentOS Stream 8

自宅のシステムはiSCSIのディスクが単一障害点になっています。
共有ディスクに関しては冗長化するのは難しいと思っていましたが、DRBD+Keepalived +NFSを用いてESXiで使える冗長化共有ディスクを試してみようと思います。

ちなみにはじめはiSCSIでやって、切替時にPDLになるのをどうしても回避できなかったので、NFSを使ってます。

環境としてはESXi6.7で仮想マシンを作りCentOS Stream8をMinimalインストールします。
スペックはCPU2コア、メモリ4GB、ディスク50GB+共有ディスクで行きます。

しばらくはdrbd01で作業して、後で仮想マシンをクローンしてdrbd02を作成します。

+----------------------+     +----------------------+ 
| CentOS Stream 8      |     | CentOS Stream 8      | 
| drbd01               |     | drbd02               | 
| sda(50GB)            |     | sda(50GB)            | 
| sdb                  |     | sdb                  | 
| 192.168.1.231(BootIP)|     | 192.168.1.232(BootIP)| 
| 192.168.1.230(VIP)   |     | 192.168.1.230(VIP)   | 
+-ens192---------------+     +-ens192---------------+ 
   |                            |
   +----------------------------+ 1GbE

まずはkeepalivedを入れます。これでVIPを移動させます。

# dnf install -y keepalived

設定をバックアップして編集します。

# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.org
# vi /etc/keepalived/keepalived.conf

# vi /etc/keepalived/keepalived.conf
↓ 中身を消して以下で上書きます
! Configuration File for keepalived
global_defs {
  vrrp_garp_master_refresh 60
  garp_master_delay        5
  advert_int               1
}
vrrp_instance VI_1 {
  state             BACKUP
  interface         ens192
  virtual_router_id 230
  priority          100
  advert_int        3
  authentication {
    auth_type PASS
    auth_pass password
  }
  virtual_ipaddress {
    192.168.1.230/24
  }
}

vrrp_garp_master_refreshはマスター更新時にGARPを投げる設定をしてARPテーブル更新をさせます。
state BACKUPは、フェイルバックをさせないようにしてます。(VIPを自動で戻す必要もないならBACKUP同士で良いみたい)

Firewallでvrrpを開けて、keepalivedを起動と自動起動にしておきます。

# firewall-cmd --permanent --add-protocol=vrrp
# firewall-cmd --reload
# systemctl start keepalived.service
# systemctl enable keepalived.service

後はSELinuxを無効にしておきます。

# vi /etc/selinux/config
SELINUX=enforcing
↓
SELINUX=disabled

この段階でip aで確認するとvirtual_ipaddressで指定したIPアドレスをens192に割りついていることが確認できます。

次にDRBDのコンパイルに必要なツールを入れます。(kmodはstreamになかったみたい)

# dnf -y install gcc gcc-c++ kernel-devel kernel-rpm-macros make perl-interpreter rpm-build kernel-abi-whitelists wget elfutils-libelf-devel flex automake

カーネルモジュールをダウンロードしてコンパイルします。

# wget https://pkg.linbit.com//downloads/drbd/9/drbd-9.1.6.tar.gz
# gzip -cd drbd-9.1.6.tar.gz | tar xvf -
# mkdir rpmbuild
# mkdir rpmbuild/BUILD rpmbuild/RPMS rpmbuild/SOURCES rpmbuild/SPECS rpmbuild/SRPMS
# cd drbd-9.1.6
# make kmp-rpm

次にユーティリティをダウンロードしてコンパイルします。

# wget https://pkg.linbit.com//downloads/drbd/utils/drbd-utils-9.20.2.tar.gz
# cp drbd-utils-9.20.2.tar.gz ~/rpmbuild/SOURCES/
# cd ~/rpmbuild/SOURCES/
# gzip -cd drbd-utils-9.20.2.tar.gz | tar xvf -
# cd drbd-utils-9.20.2
# ./autogen.sh
# ./configure --enable-spec
# rpmbuild -bb drbd.spec --without sbinsymlinks --without heartbeat --with prebuiltman

コンパイルしたrpmをインストールします。

# ~/rpmbuild/RPMS/x86_64 
# dnf -y localinstall kmod-drbd-9.1.6_4.18.0_365-1.x86_64.rpm drbd-utils-9.20.2-1.el8.x86_64.rpm drbd-bash-completion-9.20.2-1.el8.x86_64.rpm drbd-xen-9.20.2-1.el8.x86_64.rpm drbd-udev-9.20.2-1.el8.x86_64.rpm drbd-pacemaker-9.20.2-1.el8.x86_64.rpm drbd-man-ja-9.20.2-1.el8.x86_64.rpm drbd-9.20.2-1.el8.x86_64.rpm

DRDB用のポートも開放します。

# firewall-cmd --add-port=6996-7800/tcp --permanent
# firewall-cmd --reload

設定ファイルを作ります。

# cd /etc/drbd.d/
# vi r0.res
↓ ファイルを作って追記します
resource r0 {
    net{
        protocol    C;
        max-buffers 128K;
    }
    on node1 {
        device    /dev/drbd0;
        disk      /dev/sdb1;
        address   192.168.1.231:7788;
        meta-disk internal;
    }
 
    on node2 {
        device    /dev/drbd0;
        disk      /dev/sdb;
        address   192.168.1.232:7788;
        meta-disk internal;
    }
}

設定ファイルができたので、メタデータを作成します。

# drbdadm create-md r0

ここまでできたら仮想マシンをクローンします。
クローン後はホスト名、IPアドレスを忘れずに変更します。
また、ESXiの設定で該当マシンのセキュアブートを無効にしておきます。

両ノードでDRBDを起動します。

[root@drbd01 ~]# drbdadm up r0
[root@drbd02 ~]# drbdadm up r0

ステータスを確認するとInconsistentになっているので同期が必要です。

[root@drbd01 ~]# drbdadm status r0
r0 role:Secondary
  disk:Inconsistent
  drbd02 role:Secondary
    peer-disk:Inconsistent

片ノードをプライマリに変更し、セカンダリに戻します。するとUpToDateに変わります。これで同期完了です。

[root@drbd01 ~]# drbdadm --force primary r0
[root@drbd01 ~]# drbdadm secondary r0
[root@drbd01 ~]# drbdadm status r0
r0 role:Secondary
  disk:UpToDate
  drbd02 role:Secondary
    replication:SyncSource peer-disk:Inconsistent done:21.07

[root@drbd01 ~]# drbdadm status r0
r0 role:Secondary
  disk:UpToDate
  drbd02 role:Secondary
    peer-disk:UpToDate

ディスクが用意できたので、ファイルシステムを作ります。1ノード側でxfsでサクッと作ります。

[root@drbd01 ~]# mkfs.xfs /dev/drbd0

ファイルシステムができたので、マウントポイントを作ります。

[root@drbd01 ~]# mkdir /drbd0
[root@drbd01 ~]# chmod 777 /drbd0
[root@drbd02 ~]# mkdir /drbd0
[root@drbd02 ~]# chmod 777 /drbd0

両ノードでマウントをチェックします。

[root@drbd01 ~]#  mount /dev/drbd0 /drbd0
[root@drbd01 ~]# drbdadm status r0
r0 role:Primary
  disk:UpToDate
  drbd02 role:Secondary
    peer-disk:UpToDate

[root@drbd01 ~]# umount /drbd0
[root@drbd01 ~]# drbdadm status r0
r0 role:Secondary
  disk:UpToDate
  drbd02 role:Secondary
    peer-disk:UpToDate

[root@drbd02 ~]# mount /dev/drbd0 /drbd0
[root@drbd02 ~]# drbdadm status r0
r0 role:Primary
  disk:UpToDate
  drbd01 role:Secondary
    peer-disk:UpToDate

[root@drbd02 ~]# umount /drbd0
[root@drbd02 ~]# drbdadm status r0
r0 role:Secondary
  disk:UpToDate
  drbd01 role:Secondary
    peer-disk:UpToDate

次に両ノードでNFSをインストールして設定します。

# dnf -y install nfs-utils
# vi /etc/exports
↓ファイルを作って追記します
/drbd0 192.168.0.0/16(rw)
# firewall-cmd --add-service={nfs3,mountd,rpc-bind} --permanent
# firewall-cmd --reload

最後にkeepalivedで切替時にNFSを起動/停止をさせるようにします。

# vi /usr/local/sbin/keepalived_master
↓ファイルを作って追記します
#!/bin/sh
mount /dev/drbd0 /drbd0
systemctl start rpcbind nfs-server

# vi /usr/local/sbin/keepalived_backup
↓ファイルを作って追記します
#!/bin/sh
umount /drbd0
systemctl stop rpcbind nfs-server

# chmod +x /usr/local/sbin/keepalived_master
# chmod +x /usr/local/sbin/keepalived_backup
# vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
  vrrp_garp_master_refresh 60
  garp_master_delay        5
  advert_int               1
}
vrrp_instance VI_1 {
  state             BACKUP
  interface         ens192
  virtual_router_id 230
  priority          100
  advert_int        3
  authentication {
    auth_type PASS
    auth_pass password
  }
  virtual_ipaddress {
    192.168.1.230/24
  }
  ↓以下を追記
  notify_master "/usr/local/sbin/keepalived_master"
  notify_backup "/usr/local/sbin/keepalived_backup"
  notify_fault  "/usr/local/sbin/keepalived_backup"
  notify_stop   "/usr/local/sbin/keepalived_backup"
}

keepalivedを再起動して確認します。今回はdrbd02がVIPを取得したので、rdbd02でNFSを起動してますね。

[root@drbd02 ~]# systemctl restart keepalived.service
[root@drbd01 ~]# systemctl restart keepalived.service
[root@drbd01 ~]# systemctl status rpcbind nfs-server
● rpcbind.service - RPC Bind
   Loaded: loaded (/usr/lib/systemd/system/rpcbind.service; disabled; vendor pr>
   Active: inactive (dead) since Sun 2022-02-20 10:53:57 JST; 1min 23s ago

● nfs-server.service - NFS server and services
   Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; disabled; vendor>
  Drop-In: /run/systemd/generator/nfs-server.service.d
           mqorder-with-mounts.conf
   Active: inactive (dead) since Sun 2022-02-20 10:49:47 JST; 5min ago

[root@drbd02 ~]# systemctl status rpcbind nfs-server
● rpcbind.service - RPC Bind
   Loaded: loaded (/usr/lib/systemd/system/rpcbind.service; disabled; vendor pr>
   Active: active (running) since Sun 2022-02-20 10:53:58 JST; 1min 5s ago

● nfs-server.service - NFS server and services
   Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; disabled; vendor>
  Drop-In: /run/systemd/generator/nfs-server.service.d
           mqorder-with-mounts.conf
   Active: active (exited) since Sun 2022-02-20 10:53:58 JST; 1min 5s ago

この状態で切替を行うとrdbd01でNFSを起動すること確認します。

[root@drbd02 ~]# systemctl restart keepalived.service
[root@drbd02 ~]# systemctl status rpcbind nfs-server
● rpcbind.service - RPC Bind
   Loaded: loaded (/usr/lib/systemd/system/rpcbind.service; disabled; vendor pr>
   Active: inactive (dead) since Sun 2022-02-20 10:57:28 JST; 24s ago

● nfs-server.service - NFS server and services
   Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; disabled; vendor>
  Drop-In: /run/systemd/generator/nfs-server.service.d
           mqorder-with-mounts.conf
   Active: inactive (dead) since Sun 2022-02-20 10:57:27 JST; 25s ago

[root@drbd01 ~]# systemctl status rpcbind nfs-server
● rpcbind.service - RPC Bind
   Loaded: loaded (/usr/lib/systemd/system/rpcbind.service; disabled; vendor pr>
   Active: active (running) since Sun 2022-02-20 10:57:28 JST; 49s ago

● nfs-server.service - NFS server and services
   Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; disabled; vendor>
  Drop-In: /run/systemd/generator/nfs-server.service.d
           mqorder-with-mounts.conf
   Active: active (exited) since Sun 2022-02-20 10:57:28 JST; 49s ago

サービスが切り替えできているのが確認できますね。DRBDの自動プロモーションでサービスに合わせてPrimaryは自動的に切り替わります。

VIPに指定した192.168.1.230を指定するとESXiからマウントできます。

ESXiでマウントしたドライブをWin10のVMからベンチしてみました。同一ノードのESXiでマウントしているのでReadはそれなりに速度が出ています。ただ、Writeはノード間の通信がボトルネックになるようですね。ノード間は1GbEなので理論値で125MB/s程度だと考えると効率の良い数値が出ているかと思います。

ちなみに共有ディスクに使用しているディスク領域に対するベンチは以下です。

ベンチ中に切り替えをしてみました。青で囲ったところでしばらくアクティブは100%で転送自体は止まりますが、その後は何事もなかったようにベンチが進みました。

これで冗長化共有ディスクがかんたんに組めますね。
ESXiでNFSは遅いと昔聞きましたが、それなりにパフォーマンスが出る+DRBDで筐体冗長化もできるとなるとなかなか使い勝手が良さそうです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)