DRBD Reactorを使ったNFSサーバ

はじめに

前回のBlogではDRBDとPacemakerを使ったNFSクラスタの構築を説明しました。

LINBITではPacemakerに変わるクラスタ管理のソフトウェアDRBD Reactorを開発していて、彼らのHow-to Guidesでは、DRBDとDRBD Reactorを使ったNFSの構築方法(NFS High Availability Clustering Using DRBD and DRBD Reactor on RHEL 9)も公開しています。

今回はこれを元に、検証環境にNFSクラスタを構築し、Pacemakerを使った場合との設定の違いを紹介します。

検証の環境

DRBD Reactorではフェンシングの代わりにQuoramでスプリットブレインを防止します。そのためKVMを使った仮想環境上に3つのサーバを用意しました。OSは元の記事に合わせてAlmaLinux 9.4をインストールして、ホスト名、DRBDでレプリケーションするデバイス、ネットワークアドレスは以下のようになります。

ホスト名デバイス名ネットワーク1ネットワーク2
node1/dev/vdb192.168.3.9610.0.0.96
node2/dev/vdb192.168.3.9710.0.0.97
node3/dev/vdb192.168.3.9810.0.0.98

※システムの全体設定としては、ファイヤーウォールとSELinuxは停止しています。
 本番環境での構築ではファイヤーウォールは設定されることをお勧めします。

DRBDのインストール

前回の記事でも説明したように今回の検証で使ったAlmalinux 9.4では無償で利用できるDRBDのパッケージがないため、過去の記事で紹介したソースコードからDRBDをインストールする方法使ってDRBDのパッケージを作成するか、DRBDのデモライセンスを申請して、DRBDのバイナリーを入手してください。デモライセンスの申請はこちらのページから行えます。

DRBD Reactorは内部でPacemakerのリソースエージェントを利用するため、PacemakerはLINBITのデモライセンスを使うか、RHEL9のHA Packagesからダウンロードします。

最初にDRBDをdnfコマンドでインストールしてください。

[root@node1 ~]# dnf -y install drbd kmod-drbd lvm2

DRBDはDRBD Reactorから起動するため、OSの起動時に自動起動しないようにします。次のコマンドを実行して、自動起動を無効にします。

[root@node1 ~]# systemctl disable --now drbd

そのほかのソフトウェアのインストール

DRBD ReactorはPacemakerのリソースエージェントを使ってリソースの制御ができます。今回の設定でもファイルシステムのマウントやNFSの制御に利用するため、resouce-agentsをインストールします。

[root@node1 ~]# dnf -y install resource-agents

またNFSのためのパッケージをインストールし、rpcbindサービスが自動起動するよう設定します。

[root@node1 ~]# dnf -y install nfs-utils rpcbind
[root@node1 ~]# systemctl enable --now rpcbind

ディスクの設定

本設定ではportblock OCF リソースエージェントを使用します。
この実行には「スクラッチ」ディスク領域が必要になります。そのためには、DRBD リソースのボリューム 0 を使用します。このデバイスは小さくてもかまいません。今回はfdiskを使ってデータ用のデバイスを20MBと残りをNFSデータ領域(8GB)に分割しました。

[root@node1 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sr0 11:0 1 1024M 0 rom
vda 252:0 0 20G 0 disk
├─vda1 252:1 0 1G 0 part /boot
└─vda2 252:2 0 19G 0 part
├─almalinux-root 253:0 0 17G 0 lvm /
└─almalinux-swap 253:1 0 2G 0 lvm [SWAP]
vdb 252:16 0 8G 0 disk
├─vdb1 252:17 0 20M 0 part
└─vdb2 252:18 0 8G 0 part

DRBDの設定

まずDRBDの設定をします。各ノードの/etc/drbd.d/ディレクトリにnfs.resという名前で設定ファイルを以下の内容で作成します。

resource nfs {
    protocol C;
    volume 0 {
	device "/dev/drbd0";
	disk "/dev/vdb1";
	meta-disk internal;
    }
    volume 1 {
	device "/dev/drbd1";
	disk "/dev/vdb2";
	meta-disk internal;
    }
    on "node1" {
	node-id 0;
	address 10.0.0.96:7788;
    }
    on "node2" {
	node-id 1;
	address 10.0.0.97:7788;
    }
    on "node3" {
	node-id 2;
	address 10.0.0.98:7788;
    }
    options {
	auto-promote no;
	quorum majority;
	on-no-quorum io-error;
	on-suspended-primary-outdated force-secondary;
	on-no-data-accessible io-error;
    }
    connection-mesh {
	hosts node1 node2 node3;
    }
}

DRBDのメタデータを作成します。

[root@node1 ~]# drbdadm create-md nfs
initializing activity log
initializing bitmap (4 KB) to all zero
Writing meta data…
New drbd meta data block successfully created.
initializing activity log
initializing bitmap (512 KB) to all zero
Writing meta data…
New drbd meta data block successfully created.

メタデータを作成したらDRBDを起動します。(drbdadm up)
drbdadm statusを実行して、ノード間の通信が正常に行われ、ディスクの状態がInconsistent になっていることを確認します。

[root@node1 ~]# drbdadm up nfs
[root@node1 ~]# drbdadm status nfs
nfs role:Secondary
  volume:0 disk:Inconsistent open:no
  volume:1 disk:Inconsistent open:no
  node2 role:Secondary
    volume:0 peer-disk:Inconsistent
    volume:1 peer-disk:Inconsistent
  node3 role:Secondary
    volume:0 peer-disk:Inconsistent
    volume:1 peer-disk:Inconsistent

DRBDの初期同期を行いますが、ここでは new-current-uuidを使って初期同期はスキップします。

[root@node1 ~]# drbdadm new-current-uuid --clear-bitmap nfs/0
[root@node1 ~]# drbdadm new-current-uuid --clear-bitmap nfs/1

drbdadm statusを実行して、各ノードdiskとpeer-diskがUpToDataになっていることを確認してください。この状態になるとDRBDはデータの同期が開始されます。

[root@node1 ~]# drbdadm status nfs
nfs role:Secondary
  volume:0 disk:UpToDate open:no
  volume:1 disk:UpToDate open:no
  node2 role:Secondary
    volume:0 peer-disk:UpToDate
    volume:1 peer-disk:UpToDate
  node3 role:Secondary
    volume:0 peer-disk:UpToDate
    volume:1 peer-disk:UpToDate

次にデバイスにアクセスするために、node1で次のコマンドを実行して、DRBDのリソースnfsをPrimaryに昇格します。

[root@node1 ~]# drbdadm primary nfs

DRBDで管理されたデバイス(/dev/drbd0、/dev/drbd1)にファイルシステムを作成します。ここでは、/dev/drbd0はEXT4で、/dev/drbd1はXFSのファイルシステムを作成しています。

[root@node1 ~]# mkfs.ext4 /dev/drbd0
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 20440 1k blocks and 5112 inodes
Filesystem UUID: 93d2d221-81d6-4e67-b288-92ae004df15c
Superblock backups stored on blocks: 
	8193
Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
[root@node1 ~]# mkfs.xfs /dev/drbd1
meta-data=/dev/drbd1             isize=512    agcount=4, agsize=522910 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1 nrext64=0
data     =                       bsize=4096   blocks=2091639, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=16384, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
Discarding blocks...Done.

ファイルシステムの作成が終わったら、マウントポイントを作成して、マウントしてみます。

[root@node1 ~]# mkdir -p /nfsdata/internal/nfs
[root@node1 ~]# mount /dev/drbd0  /nfsdata/internal/nfs
[root@node1 ~]# mkdir -p /nfsdata/exports/nfs/data
[root@node1 ~]# mount /dev/drbd1 /nfsdata/exports/nfs/data

次に/nfsdata/internal/nfsディレクトリ内にはnfsinfoとtickleという名前のディレクトリを作成します。

[root@node1 ~]# mkdir -p /nfsdata/internal/nfs/nfsinfo  
[root@node1 ~]# mkdir -p /nfsdata/internal/nfs/tickle

マウントの確認とディレクトリの作成が終わったら、デバイスをアンマウントします。

[root@node1 ~]# umount /dev/drbd0
[root@node1 ~]# umount /dev/drbd1

最後にdrbdadm secondaryを実行して、nfsリソースをSecondaryに降格します。

[root@node1 ~]# drbdadm secondary nfs

以上で、DRBDのセットアップは終了です。

DRBD Reactorのインストールと設定

すべてのノードにdnfコマンドでDRBD Reactorをインストールします。
DRBD Reactorは自動起動するようすべてのノードで systemctlコマンドを使って、enableに設定します。

[root@node1 ~]# dnf -y install drbd-reactor
[root@node1 ~]# systemctl enable --now drbd-reactor.service  

DRBD Reactorにはdrbd-reactorctlという管理ツールがあります。
このツールを使って、nfsリソース関連したサービスを登録します。

[root@node1 ~]# drbd-reactorctl edit nfs

テキストエディタが起動されるので、以下の設定を入力します。
設定はTOML形式で記述します。

#| Please edit the snippet below. Lines beginning with a '#|' will be ignored,
#| and an empty file will abort the edit. If an error occurs while saving this file will be
#| reopened with the relevant failures.
#|
#| Happy editing:
[[promoter]]
id = "nfs"
[promoter.resources.nfs]
start = [
  "ocf:heartbeat:portblock portblock action=block ip=192.168.3.95 portno=2049 protocol=tcp",
  """ocf:heartbeat:Filesystem fs_cluster_private device=/dev/drbd0 \
  directory=/nfsdata/internal/nfs fstype=ext4 run_fsck=no""",
  """ocf:heartbeat:Filesystem fs_1 device=/dev/drbd1 \
  directory=/nfsdata/exports/nfs/data fstype=xfs run_fsck=no""",
  """ocf:heartbeat:nfsserver nfsserver nfs_ip=192.168.3.95 \
  nfs_server_scope=192.168.3.95 nfs_shared_infodir=/nfsdata/internal/nfs/nfsinfo""",
  """ocf:heartbeat:exportfs export_drbd_nfs_vol clientspec=192.168.3.0/255.255.255.0 \
  directory=/nfsdata/exports/nfs/data fsid=1d0b09e0-1f65-5ae4-98c4-8661f84a5325 \
  options='rw,all_squash,anonuid=0,anongid=0'""",
  "ocf:heartbeat:IPaddr2 virtual_ip cidr_netmask=24 ip=192.168.3.95",
  """ocf:heartbeat:portblock portunblock action=unblock ip=192.168.3.95 \
  portno=2049 protocol=tcp tickle_dir=/nfsdata/internal/nfs/tickle""",
]

設定の流れ

  1. NFSポートをブロック
    • アドレス: 192.168.3.95
    • ポート番号: 2049
  2. ファイルシステムをマウント
    • /dev/drbd0/nfsdata/internal/nfsにマウント
    • /dev/drbd1/nfsdata/exports/nfs/dataにマウント
  3. NFSサーバーを公開
    • nfsserverリソースエージェントを使用
  4. 仮想IPアドレスの設定
    • 仮想IP: 192.168.3.95
  5. NFSポートのブロック解除

すべての設定は昇格時に順次実行されます。
3ノード構成で仮想IPアドレスは共通で設定されています。

DRBD Reactorをnode1で設定しました。Pacemakerは1ノードで設定すると残りのノードに同じ設定がコピーされますが、DRBD Reactorは設定をコピーする必要があります。設定は/etc/drbd-reactor.d/nfs.tomlに保存されるので、これをnode2、node3にscpコマンドを使ってコピーします。

[root@node1 ~]# scp /etc/drbd-reactor.d/nfs.toml node2:/etc/drbd-reactor.d/
[root@node1 ~]# scp /etc/drbd-reactor.d/nfs.toml node3:/etc/drbd-reactor.d/

各ノードで次のコマンドを実行し、設定を有効にします。

[root@node1 ~]# systemctl reload drbd-reactor.service

以上で設定は終わりです。

動作確認

drbd-reactorctl status nfsを実行すると、DRBD Reactorの動作を確認できます。

[root@node1 ~]# drbd-reactorctl status nfs
/etc/drbd-reactor.d/nfs.toml:
Promoter: Currently active on this node
● drbd-services@nfs.target
● ├─ drbd-promote@nfs.service
● ├─ ocf.rs@portblock_nfs.service 
● ├─ ocf.rs@fs_cluster_private_nfs.service 
● ├─ ocf.rs@fs_1_nfs.service 
● ├─ ocf.rs@nfsserver_nfs.service 
● ├─ ocf.rs@export_drbd_nfs_vol_nfs.service 
● ├─ ocf.rs@virtual_ip_nfs.service 
● └─ ocf.rs@portunblock_nfs.service 

他のノードでは次のように表示されます。

[root@node2 ~]# drbd-reactorctl status nfs
/etc/drbd-reactor.d/nfs.toml:
Promoter: Currently active on node 'node1'
○ drbd-services@nfs.target
○ ├─ drbd-promote@nfs.service
○ ├─ ocf.rs@portblock_nfs.service 
○ ├─ ocf.rs@fs_cluster_private_nfs.service 
○ ├─ ocf.rs@fs_1_nfs.service 
○ ├─ ocf.rs@nfsserver_nfs.service 
○ ├─ ocf.rs@export_drbd_nfs_vol_nfs.service 
○ ├─ ocf.rs@virtual_ip_nfs.service 
○ └─ ocf.rs@portunblock_nfs.service 

サービスが動いているノードではが、スタンバイのノードではが表示されます。

NFSサービスの起動をnode1で確認してください。

[root@node1 ~]# showmount -e 192.168.3.95
Export list for 192.168.3.95:
/nfsdata/exports/nfs/data 192.168.3.0/255.255.255.0

障害試験は別のテストクライアントからNFSマウントして、サービスが起動中のnode1をシャットダウンし、node2もしくはnode3にフェールオーバーすることを確認してください。

まとめ

DRBD Reactorを使うと、Pacemakerより少ない設定でHAクラスタを構築できます。Quorumを使ってデータを保護するために3ノード構成にする必要がありますが、スプリットブレインの発生を確実に防止できます。興味のある方はDRBD9のユーザーズガイドDRBD Reactorの開発サイトもご覧いただき、DRBD Reactorの可能性を確かめて下さい。