今回はDRBD(Distributed Replicated Block Device)とLINSTORを利用し、データをリアルタイムに同期する冗長化ストレージサーバーを構築する方法についてご紹介します。
まず、主なストレージの分類について紹介します。
- ローカルストレージ
サーバー本体に直接内蔵されているストレージ(ディスク)です。
OSの起動データや他のサーバーと共有する必要のないデータを保存します。
- ファイルストレージ
ファイル単位でデータを管理するストレージです。マルチアクセス制御が得意。
NASで利用されることが多い。(例)Amazon EFS、NFS
- ブロックストレージ
データを固定サイズのブロックに分割して保存するストレージです。I/O性能が高い。
DBや仮想マシンのディスクとして利用される。(例)Amazon EBS、DRBD
- オブジェクトストレージ
ファイル単位、ブロック単位ではなく、オブジェクトと呼ばれる非構造化形式でデータを管理する。
通常は直接マウントは出来ない。対話には専用クライアント、プログラムが必要。(例)Amazon S3
今回ご紹介するDRBDは、ブロックストレージに分類されます。DRBDとLINSTORで構成したディスクプールを使ってNFS(Network File System)を構成する手順を紹介していきます。
NFSは、ネットワークを介してファイルストレージを提供する仕組みです。サーバーの分野では古くから活用されておりますが、現在でも広く使われている技術の一つです。
DRBDの概要
まずは、DRBDがどのようなソフトウェアであり、どのような構成で利用するのかについて簡単にご説明いたします。
DRBDとは?
DRBD(Distributed Replicated Block Device)は、オーストリアのLINBIT社が開発したソフトウェアで、複数台のストレージサーバー間でデータをリアルタイムに同期する機能を提供します。オープンソースソフトウェア(OSS)として提供されており、最大32台のサーバーをサポートしています。
基本的な機能は無料で利用可能ですが、遠隔地同期に最適化されたDRBD Proxyや商用サポートは有償での提供となります。
プライマリサーバーがダウンした場合、セカンダリサーバーは自動的にプライマリサーバーに昇格し、システムの可用性を確保します。
ただし、DRBDが提供するのはストレージの冗長性とデータ同期であり、管理機能が欠けています。これらを補うのがLINSTORになります。
LINSTORとは?
LINBIT社が提供する、DRBDの管理ツールです。JAVAで動作します。
複数のDRBDで構成されたディスクをプール化し、仮想ストレージとして制御、提供します。ストレージボリュームをコントロールし、ボリュームの作成、移動、削除を行います。
主な使用ソフトウェアとその役割
今回、DRBDを利用してファイルストレージを提供するために、いくつかのソフトウェアを組み合わせて使用します。ここでは、DRBDと併せて利用する主要なソフトウェアについて、その役割を簡単にご紹介します。
- NFS
ネットワークを介してファイルストレージ機能を提供します。
- corosync
Heartbeatの後継となるソフトウェアでクラスタ内の通信を監視し、状態を管理します。
- pacemaker
corosyncを利用して構成されたHAクラスタにおいて、実際のリソース制御やフェイルオーバー、オーケストレーション制御を行います。高可用性を実現します。
DRBD、LINSTORを含む5つのソフトウェアで構成されるこのシステムは、初めて導入する際には少々複雑に感じるかもしれません。
今回の設定内容のサーバー構成
今回のブログでは以下のイメージ図の構成での設定をご紹介させて頂きます。

設定内容
基本構成及び前提は以下の通りになります。
OS:Almalinux8.10
プライマリ(稼働機):drbdtest1.space-i.com(192.168.2.61)
セカンダリ(予備機):drbdtest2.space-i.com(192.168.2.62)
仮想サービスIP(VIP):192.168.2.63
OSのインストールなどは完了していることを前提としています。
この手順ではローカルストレージのデバイス領域の一部をDRBDに割り当てていますので、OSインストール時のディスク設定にて空き領域を確保します。
それでは設定内容のご紹介をさせて頂きます。
作業は、稼働機のみ、予備機のみと記載していなければ、稼働機・予備機の両方で設定をしています。
相手側とホスト名で通信する
以下の設定はDNSで名前解決できるホスト名であれば設定は不要となります。
vi /etc/hosts
192.168.2.61 drbdtest1 drbdtest1.space-i.com
192.168.2.62 drbdtest2 drbdtest2.space-i.com
ボリュームグループ作成
初めにOSインストール時に空き領域を確保したデバイスに論理ボリューム(LVM)としてパーティションを作成します。
fdisk /dev/vda
n パーディション作成
t パーティションのタイプを設定(31でLVM)
w 書き込み
reboot 再起動し反映
次にPV(物理ボリューム)を作成します。
pvcreate /dev/vda3
pvdisplayで確認します。
次にVG(ボリューム・グループ)を作成します。
vgcreate drbdpool /dev/vda3
vgdisplayで確認をします。
firewall設定
各アプリケーション用の待ち受けポートを設定しています。
# nfs
firewall-cmd --add-port=2049/tcp --zone=public --permanent
firewall-cmd --add-port=2049/udp --zone=public --permanent
firewall-cmd --add-port=111/tcp --zone=public --permanent
firewall-cmd --add-port=111/udp --zone=public --permanent
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p tcp -m multiport --dports 32771,32773,32774,32776 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p tcp -m multiport --sports 32771,32773,32774,32776 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p udp -m multiport --dports 32772,32773,32775,32776 -j ACCEPT
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -p udp -m multiport --sports 32772,32773,32775,32776 -j ACCEPT
# linstor
firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address="192.168.2.0/24" port port=3366 protocol=tcp accept' --permanent
firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address="192.168.2.0/24" port port=3370 protocol=tcp accept' --permanent
# pcsd
firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address="192.168.2.0/24" port port=2224 protocol=tcp accept' --permanent
firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address="192.168.2.0/24" port port=3121 protocol=tcp accept' --permanent
# heartbeat/corosync
firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address="192.168.2.0/24" port port=5404 protocol=udp accept' --permanent
firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address="192.168.2.0/24" port port=5405 protocol=udp accept' --permanent
# drbd9 (resource単位で自動割り当て、7000から順次)
firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address="192.168.2.0/24" port port=7000-7100 protocol=tcp accept' --permanent
# 反映
firewall-cmd --reload
drbd、linstorのインストール
drbd9本体とlinstor(管理ツール)インストールします。
dnf install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
dnf install drbd90-utils kmod-drbd90 lvm2
# Almalinux8 のビルドマシン用パッケージ導入します。
dnf -y groupinstall "Development Tools"
dnf -y install kernel-devel libxslt docbook-style-xsl git
# LINSTOR のビルドに必要なパッケージもインストールします。
dnf -y install java-1.8.0-openjdk-devel protobuf-compiler python2-setuptools python2
# ビルド出力先dir作成
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
# ビルド用パッケージ
cd /usr/local/src
wget https://services.gradle.org/distributions/gradle-6.0.1-bin.zip
unzip gradle-6.0.1-bin.zip
# 一時的にパス通します
export PATH=$PWD/gradle-6.0.1/bin:$PATH
# Linstor-server ビルド&install
cd /usr/local/src
wget https://pkg.linbit.com//downloads/linstor/linstor-server-1.12.6.tar.gz
rpmbuild -tb linstor-server-1.12.6.tar.gz
rpm -ivh /root/rpmbuild/RPMS/noarch/linstor-common-1.12.6-1.el8.noarch.rpm
rpm -ivh /root/rpmbuild/RPMS/noarch/linstor-satellite-1.12.6-1.el8.noarch.rpm
rpm -ivh /root/rpmbuild/RPMS/noarch/linstor-controller-1.12.6-1.el8.noarch.rpm
# python-linstor build&install
cd /usr/local/src
wget https://pkg.linbit.com//downloads/linstor/python-linstor-1.8.0.tar.gz
tar -zxvf ./python-linstor-1.8.0.tar.gz
cd ./python-linstor-1.8.0
make rpm
rpm -ivh ./dist/python-linstor-1.8.0-1.noarch.rpm
# linstor-client build&install
cd /usr/local/src
wget https://pkg.linbit.com//downloads/linstor/linstor-client-1.8.0.tar.gz
tar -zxvf ./linstor-client-1.8.0.tar.gz
cd linstor-client-1.8.0
make rpm
rpm -ivh ./dist/linstor-client-1.8.0-1.noarch.rpm
linstorセットアップ
controllerは管理端末でのみ実行します。
(本来はDRBDノード以外で管理用端末を用意した方が良いのですが、今回は稼働機にて実行します。)
複数端末から実行すると不整合が起こり設定が壊れます。
稼働機でのみ実行
systemctl enable linstor-controller
systemctl start linstor-controller
稼働機・予備機で実行
systemctl enable linstor-satellite
systemctl start linstor-satellite
# node接続(稼働機で実行)
linstor-controllerとlinstor-satelliteを実行してから10秒で疎通完了するので時間をおいてから実行すること
linstor node create drbdtest1.space-i.com 192.168.2.61 --node-type Combined
linstor node create drbdtest2.space-i.com 192.168.2.62
※linstor-controllerも合わせて実行するマシンには「--node-type Combined」を付けます。
※ZFS絡みのエラーが出るがZFS対応を実装していないためなので無視します。
# node接続確認(稼働機で確認)
各NodeのStateがOnlineであればOK
SATELLITEがOFFLINEのときはSATELLITEでlinstorが起動していない
linstor node list
?────────────────────────────────────?
? Node ? NodeType ? Addresses ? State ?
?????????????????????????????????????????????????????????????????????????
? drbdtest1.space-i.com ? COMBINED ? 192.168.2.61:3366 (PLAIN) ? Online ?
? drbdtest2.space-i.com ? SATELLITE ? 192.168.2.62:3366 (PLAIN) ? Online ?
?────────────────────────────────────?
storage-pool設定(稼働機で実行)
linstor storage-pool create lvm drbdtest1.space-i.com pool01 drbdpool
linstor storage-pool create lvm drbdtest2.space-i.com pool01 drbdpool
# storage-pool確認
追加したpoolのStateがOkであることを確認します。
linstor storage-pool list
?──────────────────────────────────────────────────────────────────?
? StoragePool ? Node ? Driver ? PoolName ? FreeCapacity ? TotalCapacity ? CanSnapshots ? State ? SharedName ?
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? DfltDisklessStorPool ? drbdtest1.space-i.com ? DISKLESS ? ? ? ? False ? Ok ? ?
? DfltDisklessStorPool ? drbdtest2.space-i.com ? DISKLESS ? ? ? ? False ? Ok ? ?
? pool01 ? drbdtest1.space-i.com ? LVM ? drbdpool ? 6.05 TiB ? 6.05 TiB ? False ? Ok ? ?
? pool01 ? drbdtest2.space-i.com ? LVM ? drbdpool ? 6.05 TiB ? 6.05 TiB ? False ? Ok ? ?
?──────────────────────────────────────────────────────────────────?
resource設定(稼働機で実行)
linstor resource-definition create res0
# resouirce確認
指定したresourceの名前で設定されていることを確認
linstor rd list(稼働機で実行)
?───────────────────────?
? ResourceName ? Port ? ResourceGroup ? State ?
???????????????????????????????????????????????
? res0 ? ? DfltRscGrp ? ok ?
?───────────────────────?
volume設定(稼働機で実行)
linstor volume-definition create res0 6T
6Tは容量
# volume確認
設定したvolumeサイズに誤りが無い事を確認
容量を間違えたときは以下のコマンドで削除
linstor volume-definition delete res0 0
linstor vd list
?────────────────────────────────?
? ResourceName ? VolumeNr ? VolumeMinor ? Size ? Gross ? State ?
?????????????????????????????????????????????????????????????????
? res0 ? 0 ? 1000 ? 6 TiB ? ? ok ?
?────────────────────────────────?
resourceとstorage-poolの紐づけ(稼働機で実行)
linstor resource create drbdtest1.space-i.com res0 --storage-pool pool01
linstor resource create drbdtest2.space-i.com res0 --storage-pool pool01
# 紐づけ確認
初回は同期の為、secoundary側のStateがSyncTargetとなる。
何度か実行しstateの%が進んでいることを確認します。
同期完了後は量NodeのStateがUptoDateとなることを確認します。
linstor r list
──────────────────────────────?
? ResourceName ? Node ? Port ? Usage ? Conns ? State ? CreatedOn ?
??????????????????????????????????????????????????????????????????????????????????????????????????????????
? res0 ? drbdtest1.space-i.com ? 7000 ? Unused ? Ok ? UpToDate ? 2025-4-3 14:51:12 ?
? res0 ? drbdtest2.space-i.com ? 7000 ? Unused ? Ok ? SyncTarget(0.59%) ? 2025-4-3 14:51:21 ?
?─────────────────────────────────────────────────────
drbdチューニング設定(稼働機で実行)
linstor resource-definition drbd-options --protocol C --quorum off --read-balancing least-pending --c-plan-ahead 0 --c-max-rate 300M --c-min-rate 100M --al-extents 3389 --max-buffers 20000 --max-epoch-size 20000 --sndbuf-size 0 --on-io-error detach --after-sb-0pri disconnect --after-sb-1pri disconnect --after-sb-2pri disconnect --rr-conflict disconnect res0
DRBD領域を作成・マウントしフォーマット(稼働機で実行)
cd
mkfs.xfs /dev/drbd1000
mkdir /home/nfs
chmod 777 /home/nfs
mount /dev/drbd1000 /home/nfs
予備機でマウント領域の作成
cd
mkdir /home/nfs
chmod 777 /home/nfs
nfs状態ファイルをdrbd領域へ移動(稼働機で実行)
mkdir -p /home/nfs/var/lib/
cp -a /var/lib/nfs /home/nfs/var/lib/
mv /var/lib/nfs /var/lib/nfs_
ln -s /home/nfs/var/lib/nfs /var/lib/nfs
予備機で実行
mv /var/lib/nfs /var/lib/nfs_
ln -s /home/nfs/var/lib/nfs /var/lib/nfs
mountはpacemakerで制御するので一旦unmountします。
umount /home/nfs
nfs関連設定
vi /etc/exports
/home/nfs/user-data/ 192.168.2.0/255.255.255.0(rw,sync,no_root_squash,no_all_squash)
vi /etc/nfs.conf
NFS v3として構成するために必要な設定
--------------------------------------------------
STATD_PORT=32771
STATD_OUTGOING_PORT=32772
MOUNTD_PORT=32773
LOCKD_TCPPORT=32774
LOCKD_UDPPORT=32775
RQUOTAD_PORT=32776
RPCNFSDCOUNT=128
pacemaker、corosyncインストール
dnf --enablerepo=ha -y install pacemaker pcs
pcsの管理ユーザーのパスワード設定
passwd hacluster
パスワードはユーザー名と同じhaclusterとしておきます。
サービス起動設定
systemctl enable pcsd
systemctl start pcsd
systemctl enable corosync
systemctl enable pacemaker
※corosyncとpacemakerはコマンドから実行するのでここでは起動しません。
cluster設定作成(稼働機で実行)
pcs cluster setup nfs_cluster drbdtest1.space-i.com drbdtest2.space-i.com
corosync、pacemaker起動(稼働機で実行)
pcs cluster start --all
--all オプションで稼働機・予備機のpcs clusterが起動します。
resource設定用configファイル作成(稼働機で実行)
現在位置にcluster_cfg.cibとして作成します。
pcs -f cluster_cfg.cib resource create res_drbd ocf:linbit:drbd drbd_resource=res0 drbdconf=/etc/drbd.conf op monitor interval=10s
pcs -f cluster_cfg.cib resource promotable res_drbd master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true
pcs -f cluster_cfg.cib resource create mount_nfs ocf:heartbeat:Filesystem device=/dev/drbd1000 directory=/home/nfs fstype=xfs
pcs -f cluster_cfg.cib resource create res_nfs systemd:nfs-server op monitor interval=10s
pcs -f cluster_cfg.cib resource create VIP ocf:heartbeat:IPaddr2 ip=192.168.2.63 nic=ens3 cidr_netmask=24 op monitor interval=8s
pcs -f cluster_cfg.cib constraint order res_drbd-clone then mount_nfs
pcs -f cluster_cfg.cib resource group add group-nfs mount_nfs res_nfs VIP
pcs -f cluster_cfg.cib constraint colocation add master res_drbd-clone with group-nfs INFINITY
作成したconfigファイルを取り込む
pcs cluster cib-push cluster_cfg.cib
ハングしたノードを強制停止する機能を無効化します。
pcs property set stonith-enabled=false
ディスクを使った死活チェック無効化
pcs property set no-quorum-policy="ignore"
ここまでの設定でDRBD9が使える状態になっています。
確認コマンドを利用してステータスの正常性を確認してみましょう。
プロパティ設定確認
pcs property
エラー確認
crm_verify -L -V
pacemakerクラスター状態確認
pcs cluster status
pcs status
pacemaker制御リソース確認
pcs resource show
pcs resource show --full
WEBサーバーからDRBD領域のマウント
次の例ではWEBサーバーの/var/www/html
にDRBDサーバーの仮想IPアドレスである192.168.2.63の /home/nfs/user-data
をマウントしています。
vi /etc/fstab
以下を追記します。
192.168.2.63:/home/nfs/user-data /var/www/html nfs rw,hard,noatime,vers=3,rsize=32768,wsize=32768,fsc 0 0
mount -a でマウント設定を反映します。
マウント確認
WEBサーバーで df コマンドを実行して以下のように表示されることを確認します。
192.168.2.63:/home/nfs/user-data 1548005696 573582144 895782752 40% /var/www/html
ここまでの設定により、WEBサーバーの /var/www/html
でデータの更新や削除が行われると、実際にはDRBDサーバーの /home/nfs/user-data
以下のデータが更新・削除されます。この設定により、DRBDを利用したファイルストレージが正常に機能する状態となります。
よくある障害対応
システム運用において、稼働中の機器がダウンした際、予備機が自動的にセカンダリからプライマリへと昇格する仕組みがあります。この動作は「フェイルオーバー」と呼ばれサービスの高可用性を確保します。
一方で、稼働機が復旧した際には、元の稼働機をプライマリに戻す必要があります。このプロセスを「フェイルバック」と言います。
フェイルバックを実施するためには、以下の手順を実行します。
# 稼働機で実行
pcs cluster start drbdtest1.space-i.com
# 予備機でdrbdtest2をスタンバイにするとdrbdtest2がオフライン状態になり仮想IPアドレス、マウント先がフェイルバックします。
pcs node standby drbdtest2.space-i.com
# drbdtest2のスタンバイを解除します
pcs node unstandby drbdtest2.space-i.com
以上でフェイルバック完了です。
pcs statusコマンドなどでステータスを確認してください。
スプリットブレインからの復旧
高可用性システムにおいて、各ノード自体は正常なままノード間の通信が途絶えると、ノードそれぞれがプライマリノードとして動作しようとしてしまう場合があります。この現象は「スプリットブレイン」と呼ばれ、システムの整合性や安定性に深刻な影響を与える可能性があります。
スプリットブレインからの復旧には、以下の以下の手順を実行します。
# データ廃棄側で実施
drbdadm disconnect res0
# primaryになってたらsecondaryへ変更
drbdadm secondary res0
# データ破棄
drbdadm connect --discard-my-data res0
# データ生存側で実施
drbdadm disconnect res0
drbdadm connect res0
以上で復旧完了です。
pcs statusコマンドなどでステータスを確認してください。
最後に
当社は、Amazon EFSやAmazon S3をはじめとするAWSクラウド環境でのストレージ構築、EC2を活用したDRBDの構築など例外環境のノウハウがあります。また自社データセンターにおけるオンプレミス環境でのストレージ運用など長年の運用実績と豊富な対応経験を有しています。
ストレージの選定やインフラ環境における最適な構成がわからないなどでお困りの際は、是非お気軽にご相談ください。
経験豊富なエンジニアが直接お相談に対応させて頂きます。