これまで、OpenMediaVault 5 (以後 OMV5) 、OpenMediaVault 6 (以後 OMV6) を使って RAID Z 、RAID Z2 を実現し、使ってまいりましたが、ディスクの使用容量が増えるにしたがって、動作に問題が生じて来ました。読み出し時に一瞬止まるのです。主に動画で再生時に詰まった様な動作になるのです。一時間の再生動画で 1-2 回以上は一瞬止まります。RAID Z, RAID Z2 はメモリー食いなのでメモリー不足なのかも知れません。それに、大容量のディスク装置も結局は殆ど NAS として使っているだけなので、今一 RAID Z, RAID Z2 の機能が生かしきれていません。・・で、ディスクの容量増大に伴って、軽いシステムである RAID5, RAID6 を OpenMedia 7 (以後 OMV7) で実現、全面的に移行します。
この記事では、PC2台を連携して 18TB x 6台 (=108TB) + 2台(エラー訂正ディスク) の RAID6 システムを実現します。なお、先に OpenMediaVault7 (OMV7) で作る PC1台 54TB RAID5 システム【Part 1】 【Part 2】を読まれている事を前提にしていますので、既にそちらで説明しているものは、項目だけ 列挙する事があります。
【追加説明 2024年7月2日】この記事は一度記事にしたものを全面的に修正、再編成してあります。システム作成中の方針変更が何度か有り、記事作成後に全体を読み直した所、説明が前後している所があり、内容がわかりずらくなっていました。作成システムは満足いく動作を得られましたので、【Part 1】で RAID用ソフト mdadmの動作説明、iSCSI 用ソフト tgtd の動作説明、その他ツールの説明等 、予め理解しておくべき事柄を【Part 2】で作成方法を説明【Part 3】で追加項目+メンテナンス 構成に変更致しました。私自身の備忘録を兼ねておりますので、作成自体に直接関係しない事も記録してあります。【追加説明 ここまで】
全体構成・動作説明
全体構成を上図に示します。master 側から見ると Disk 8台の RAID6 システムとして動きます。Disk 8台中、4台は iSCSI ディスクとして slave 側に配置します。それぞれ全体の IP も決まっていますので、記入してあります。平常運転時の master 側の eno1 の帯域を 1Gbps とした時に 他の LANポートの帯域がどれくらい必要か色線で示してあります。eno2 ←→ eno2 の帯域が (1.0 x 8 / 6) x 0.5 = 0.66 ≒ 0.7Gbps となります。slave 側の eno1 はWeb管理画面を読み書きするだけなので、0.1Gbps で良いでしょう。従って平常運転時には帯域的に足らない所はありません。 ( eno1, eno2 は 1Gbpsポート )。ただ、再同期時やシステムチェック時など高速で全体スキャンを行う時には eno2 ←→ eno2 の帯域がボトルネックになります。まあ、PC 2台に分けたコストだとのんびり運用する事にしましょう。
mdadm
mdadm使用方針
mdadmの動作説明を一部引用します。
Linux のソフトウェアRAIDは md (Multiple Devices) デバイスドライバとして実装されている。 現状 Linux ではリニアmd デバイス,RAID 0 (ストライピング),RAID 1 (ミラーリング),RAID 4,RAID 5,RAID 6 そしてマルチパス(MULTIPATH) がサポートされている。mdadm は MD デバイスの作成,管理,そしてモニタを行うためのプログラムである。
mdadm で出来る事はマニュアルを見れば解るのですが、良くわからないのはその”実行形態”です。最初はこの実行形態がよく理解できず、使いこなせませんでした。私の理解ではその実行形態は 2つあると考えます。その一つは上の説明にも書かれている デバイスドライバ的 形態、もう一つは通常のプログラム的 形態です。例えば RAID6 を実行する場合は 最初幾つかのディスクを組にして mdadmで RAID6を create します。この時は mdadm は通常のプログラムとして動作します。create したディスクには SuperBlock が書き込まれ RAID6のディスクとなります。一方、システム起動時には mdadm がデバイスドライバ的に働き、つまり sda, sdb, sdc, …. などが作成されるのとほぼ同じタイミングで SuperBlockのあるディスクをスキャンしてRAID6用のブロックデバイス mdxx が作成されます。システム立ち上がって通常のプログラムを実行できる頃にはもうすでに mdadm デバイスドライバ が mdxx を作成し終わっているのです。
実はこのタイミングが重要なのです、上記の全体構成でも説明しましたが、DISK群Bは iSCSIで masterと繋がっています。このiSCSIソフトは通常のプログラムですので、システム立ち上がり時の早い段階 (=まだ通常プログラムは実行できない) は DISK群B は使えない事になります。ですから、DISK群BもRAID6のディスクとして使う為には mdadm も通常ソフトとして使える必要があります。
mdadm はシステム立ち上がり時にはかならず、デバイスドライバ的に動作します。その後は通常プログラムとして動作致しますので、iSCSIディスク群も RAIDディスクとして使うために
(1) システム立ち上がり時に mdadm動作を失敗させる (=STOP状態で動作させる) (2) iSCSI用ソフトを動作させディスク群BもRAID6用ディスクとして準備する (3) mdadm でディスク群A,ディスク群Bを合わせて RAID6を再構成する
と致します。(1)はデバイスドライバレベル (2) 以降は通常のプログラムとして動作します。
mdadm.conf ファイル
さてここで、胆になる /etc/mdadm/mdadm.conf ファイルについて説明致します。実はmdadmがデバイスドライバ的に動作する場合でも 通常プログラムとして動作する場合でもこのmdadm.conf ファイルの設定に従って動作致します。以下にひな形を示します。mkconf で出す事もできます。
それぞれの項目は、例えば”mdadm.conf 徹底解説”でグーグル検索すればわかります。ここでは、本システムで使用するのに重要な 2つの項目について説明します。
#DEVICE partitions containers
ここには、スキャンするべき DEVICEについて書きます。フォーマットは
DEVICE 物理ボリュームのデバイスファイル
となります。例えば、sda, sdb のみスキャンさせたいと思えば、 DEVICE /dev/sda /dev/sdb または DEVICE /dev/sd[ab] と書きます。もしなにも書いていない場合は DEVICE partitions containers (=すべてのパーティションをスキャン) と同じになります。
# definitions of existing MD arrays
この行には、mdadm が操作・検索対象とするアレイの一覧を記述します。作成したARRAY は
# mdadm --detail --scan
で出力できますので、これを /etc/mdadm/mdadm.conf の # definitions of existing MD arraysの次の行に貼り付ければOKです。そうすると次回も同じ mdxx を作成する事ができます。
さて、mdadm.conf は作成して終わりではありません。デバイスドライバ組み込み作業
# update-initramfs -u
をすれば、システムに組み込む事ができます。組み込み時に設定した mdadm.conf が使われます。組み込み後は通常プログラム用にmdadm.conf を書き直しても 組み込み済みmdadm動作には影響ありません。
組み込み後も立ち上がり時に使っています。通常プログラム用には別のファイルを準備する必要があります。
またプログラム的に使う時には明示的にコマンド内に –scan を入れます。例えば
# mdadm -As A → アセンブル=再構築命令 s → scan=mdadm.confの内容に従う
mdadm.confの内容に従いスキャンして、SuperBlockの記述状態に再構築する。という具合です。アセンブル命令では使わないで要素を全て記入する方法もあります。
組み込みmdadm動作の止め方 ( =mdadmドライバ不活性化 )
例えば 8台のディスクから構成されているRAID6 の場合 sda, sdb のみスキャンさせると 不完全にRAID6が構成され、動作しません。つまり STOP状態になります。ただし、おそらくは sda, sdb は RAID6 のメンバーでしょうから sda, sdb 等メンバーの一部ににアクセスした状態で STOP します。
DEVICE /dev/sd[wxyz] または DEVICE /dev/sdw /dev/sdx /dev/sdy /dev/sdz
と記入。絶対にメンバーではない ( なぜならアルファベットの若い順にディスクが割り振られるので、最期の方は殆ど割り振られる事がない ) sdw, sdx, sdy, sdz 等、存在しないディスクをスキャンさせたらディスクに全くアクセスしないで完全なSTOP状態になります。本システムではこれを利用してデバイスドライバ的には mdadmを止めています。( スキャンするディスクは1台分だけでも問題ない気がしますが、確認がめんどうだったので、RAID6の最低構成分4台にしています) 今後このストップ状態を mdadmドライバ不活性化と呼ぶことにします。以下に状態を示します。
iSCSI ディスク (slave側)
iSCSCディスクは 鈴木のOMV7 ベースセットに iSCSI target プラグイン = openmediavault-tgt 7.0 を導入しているだけです。
mdadmドライバ不活性化
OMV7 は最初から mdadm が導入済みです。つまり、mdadmデバイスドライバが入っているのです。なにも処理をしないと、ディスクがRAID6用メンバーにフォーマットされた段階で、mdadmデバイスドライバが動作しだして、システム立ち上がり時にRAIDが不完全に動作してしまいます。mdadm の項で説明したmdadmドライバ不活性化をする必要があります。具体的には Master側で不活性化時に設定した mdadm.conf をコピーして update-initramfs -u すれば良いです。
iSCSI ソフトの動作確認
iSCSI プラグインを導入して、設定をした段階で、tgtdソフト が導入、設定がされています。具体的設定の方法や実際の確認については 【Part 2】に譲るとして、 tgtd の動作確認に簡単に触れておきます。mdadmドライバ不活性化処理をしないと、mdadm側がディスクを独占してしまい、tgtd ソフト側がディスクにアクセスできません。その場合はtgtd 動作確認をしてもディスクアクセスが表示されません。結果、master側から iSCSIディスクにアクセスできない事になります。以下はmdadmドライバ不活性化処理をし、正常動作の確認をしています。
不活性化処理に失敗し、正常に動作していない場合はこのdisk4 から disk7 が表示されません。iSCSCディスク(=Slave) は tgtd が正常動作確認ができれば、特に他の設定は必要ありません。(実際にはType Mismatch 対策のみ StartUptime.sh で行います)
DiskInfo ツール
Master側のディスクを正面左から DISK0, DISK1, DISK2, DISK3 とし、Slave側のディスクを正面左から DISK4, DISK5, DISK6, DISK7 とします。このDISK番号と /dev/disk/by-id/ata-xxxx のシリアルIDとsdx などのブロックデバイスの関係がすぐわかるよう、 OpenMediaVault7 (OMV7) で作る PC1台 54TB RAID5 システム【Part 1】【Part 2】 では、DiskInfo.sh、_DiskId.sh を導入しました。本システムではこれをもとに まず、slave 用の DiskInfoS.sh を作成します。_DiskIdS.sh は 生シリアル番号を書き換えます。DiskInfo.sh も DiskInfoS.sh に作り直して、動作を確認しておきます。
DiskInfoS.sh ( Disk-Information program for Slave )
Slave 側の DISK は DISK4, DISK5, DISK6, DISK7 とします。それに伴ってSlave側の _DiskIdS.sh と DiskInfoS.sh を作成します。まずは、 _DiskId.sh を直します。実行フラグを忘れずに。
#!/bin/bash # _DiskIdS.sh ( Disk by-Id return program for Slave ) DISK4=/dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE_14xxxx_disk4 DISK5=/dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE_14xxxx_disk5 DISK6=/dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE_14xxxx_disk6 DISK7=/dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE_14xxxx_disk7 # シリアル番号は実際から適当に変更してあります。 PATH=/usr/sbin:/usr/bin:/sbin:/bin if [ $1 = 4 ]; then echo $DISK4 exit 0 fi if [ $1 = 5 ]; then echo $DISK5 exit 0 fi if [ $1 = 6 ]; then echo $DISK6 exit 0 fi if [ $1 = 7 ]; then echo $DISK7 exit 0 fi echo "/dev/disk/by-id/"
次に DiskInfo.sh → DiskInfoS.sh (Disk-Infomation program for Slave) も直します。
#!/bin/bash # DiskInfoS.sh ( DiskInfoS.sh Disk-Information program for Slave ) PATH=/usr/sbin:/usr/bin:/sbin:/bin DISK4=$(_DiskIdS.sh 4) DISK5=$(_DiskIdS.sh 5) DISK6=$(_DiskIdS.sh 6) DISK7=$(_DiskIdS.sh 7) echo -n "DISK4 : "; echo -n $DISK4; echo -n " → "; readlink $DISK4 if [ $? != 0 ]; then echo "" fi echo -n "DISK5 : "; echo -n $DISK5; echo -n " → "; readlink $DISK5 if [ $? != 0 ]; then echo "" fi echo -n "DISK6 : "; echo -n $DISK6; echo -n " → "; readlink $DISK6 if [ $? != 0 ]; then echo "" fi echo -n "DISK7 : "; echo -n $DISK7; echo -n " → "; readlink $DISK7 if [ $? != 0 ]; then echo "" fi
以下実行例です。
DiskInfoM.sh ( Disk-Information program for Master )
同様に Master側の _DiskIdM.sh と DiskInfoM.sh を作成します。 _DiskId.sh を以下に拡張しました。
#!/bin/bash # _DiskIdM.sh ( Disk by-Id return program for Master ) DISK0=/dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE_14xxxx_disk0 DISK1=/dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE_14xxxx_disk1 DISK2=/dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE_14xxxx_disk2 DISK3=/dev/disk/by-id/ata-TOSHIBA_MG09ACA18TE_14xxxx_disk3 DISK4=/dev/disk/by-id/scsi-360000000000000000e00000000010001 DISK5=/dev/disk/by-id/scsi-360000000000000000e00000000020001 DISK6=/dev/disk/by-id/scsi-360000000000000000e00000000030001 DISK7=/dev/disk/by-id/scsi-360000000000000000e00000000040001 # disk0~disk3のシリアル番号は実際から適当に変更してあります。 PATH=/usr/sbin:/usr/bin:/sbin:/bin if [ $1 = 0 ]; then echo $DISK0 exit 0 fi if [ $1 = 1 ]; then echo $DISK1 exit 0 fi if [ $1 = 2 ]; then echo $DISK2 exit 0 fi if [ $1 = 3 ]; then echo $DISK3 exit 0 fi if [ $1 = 4 ]; then echo $DISK4 exit 0 fi if [ $1 = 5 ]; then echo $DISK5 exit 0 fi if [ $1 = 6 ]; then echo $DISK6 exit 0 fi if [ $1 = 7 ]; then echo $DISK7 exit 0 fi echo "/dev/disk/by-id/"
DiskInfo.sh → DiskInfoM.sh として DISK4 〜 DISK7 の分を追加しました。
#!/bin/bash # DiskInfoM.sh ( DiskInfoM.sh Disk-Information program for Master ) PATH=/usr/sbin:/usr/bin:/sbin:/bin DISK0=$(_DiskIdM.sh 0) DISK1=$(_DiskIdM.sh 1) DISK2=$(_DiskIdM.sh 2) DISK3=$(_DiskIdM.sh 3) DISK4=iscsi-iqn.2024-06.local.openmedia-141:disk4 DISK5=iscsi-iqn.2024-06.local.openmedia-141:disk5 DISK6=iscsi-iqn.2024-06.local.openmedia-141:disk6 DISK7=iscsi-iqn.2024-06.local.openmedia-141:disk7 echo "" echo -n "DISK0 : "; echo -n $DISK0; echo -n " → "; readlink $DISK0 if [ $? != 0 ]; then echo "" fi echo -n "DISK1 : "; echo -n $DISK1; echo -n " → "; readlink $DISK1 if [ $? != 0 ]; then echo "" fi echo -n "DISK2 : "; echo -n $DISK2; echo -n " → "; readlink $DISK2 if [ $? != 0 ]; then echo "" fi echo -n "DISK3 : "; echo -n $DISK3; echo -n " → "; readlink $DISK3 if [ $? != 0 ]; then echo "" fi echo "" echo -n "DISK4 : "; echo -n $DISK4; echo -n " → " readlink /dev/disk/by-path/*$DISK4* if [ $? != 0 ]; then echo "" fi echo -n "DISK5 : "; echo -n $DISK5; echo -n " → " readlink /dev/disk/by-path/*$DISK5* if [ $? != 0 ]; then echo "" fi echo -n "DISK6 : "; echo -n $DISK6; echo -n " → " readlink /dev/disk/by-path/*$DISK6* if [ $? != 0 ]; then echo "" fi echo -n "DISK7 : "; echo -n $DISK7; echo -n " → " readlink /dev/disk/by-path/*$DISK7* if [ $? != 0 ]; then echo "" fi
実行すると DISK0 〜 DISK3 と シリアルNo と sdx との関係、DISK4 〜 DISK7 と iqn…と sdx との関係が一目瞭然ですね。
これで、ディスクを入れ替える場合等にも、該当のディスクを間違える事なく交換できると思います。例えば sdf を交換するには、DISK4 を交換すれば良いという事です。また、sdf 〜 sdi が表示されてなければ iSCSIディスクは認識されていない事になります。