OpenMediaVault7 (OMV7) で作る PC2台連携 108TB RAID6 システム【Part 4】では、PC2台を連携して 18TB x 6台 (=108TB) + 2台(エラー訂正ディスク) の RAID6 システムのメンテナンス、ツール追加、その他 等を順不同で追加していきます。なお、 OpenMediaVault7 (OMV7) で作る PC1台 54TB RAID5 システム【Part 1】【Part 2】を読まれている事を前提にしています。有用なツール、電源 ON/OFF 時の挙動、等は基本的に同じです。既にそちらで説明しているものは、項目だけ 列挙する事があります。
全体構成・動作説明
全体構成を上図に示します。master 側から見ると Disk 8台の RAID6 システムとして動きます。Disk 8台中、4台は iSCSI ディスクとして slave 側に配置します。それぞれ全体の IP も決まっていますので、記入してあります。全体構成を考えながら、作成していくと何をやっているか理解し易いと思います。
なお、上記の図にはありませんが、リモートコントロールiLO のポートとして各PC1ポート消費しています。それぞれの IP 番号を書いておきます。
master PC iLO : 192.168.11.40 ← master PC モニター・コントロール 低速可 master PC eno1 : 192.168.11.41 ← メインのデータI/Oポート 最高速度(1Gbps)必要 slave PC iLO : 192.168.11.140 ← slave PC モニター・コントロール 低速可 slave PC eno1 : 192.168.11.141 ← slave PC の Webコントロール 低速可 高速が必要な1ポートを含む4ポートがLANとつながります。 PC間のみ通信(高速が必要) master PC eno2 : 192.168.12.41 ← 高速が必要(0.7Gbps以上)なので 1Gbpsポート使用 slave PC eno2 : 192.168.12.141 ← 高速が必要(0.7Gbps以上)なので 1Gbpsポート使用
メンテナンス
out of date ERROR を修正する。 【2025年3月26日 記録】
手順通り、電源を切らなかった。突然停電して、システムが落ちてしまった。間違って、slave側を先に落としてしまった。その他 とにかくRAIDシステムにダメージを与える操作をしてしまった。
で、RAIDが立ち上がらなくなってしまった。実際、突然のERRORに遭遇するとパニック状態になります。なんせ、もし直せなかった場合は 数十テラのデータが消えるかもしれないのですから… 完璧なシュミレーションは無理ですが、ある程度の推定はできます。いざ遭遇時に少しでも落ち着いて対処できる様 どうしてもやっておきたかった ERROR シュミレーションをします。
slave側 ( iSCSI側) の電源を先に落として、色々よけいな操作をして、立ち上がらない状態にしました。いざ、やってみるとなかなかERROR状態になりません。10回電源の ON/OFF をやってやっとERROR状態を作りました。まあ、立ち上がらないと言ってもハード的に壊れる訳でなく、あくまでRAID6の設定の一部が壊れて、ソフト的に立ち上がらなくなっている状態です。なお、運用中のシステムで実験するのは怖いので、ただいま、作成中のシステムです。なので、ディスクシリアルが異なったり、openmedia-51 だったりします。気にしないように。
まず、cat /var/log/installer/StartUptime_log を /dev/md0 再構築の辺りから表示します。log が長くなるので、Timeout Mismatch 部分は実行しないようにコメントアウトしてあります。
アセンブルが (=再構築) うまくできていないので、まず、DiskInfoM.sh で 認識しているディスクをしらべます。認識しているディスクで -v (=詳細情報付き) で 再構築してみます。 で、結局 sdf 〜 sdi が out of date (古い情報と訳されている) で、ERROR となっている。実際こうなると 通常の アセンブル命令では動作しない。所で、古い情報とはどういう事であろう。容易に想像がつくのは スーパーブロックの中でなにか 時間(もしくはイベント的な物) を管理する情報があって、その時間が合わないと ERROR になるのでは..。以下は /dev/sda の スーパーブロック情報です。
このうち、時間管理、イベント管理に使えそうなのは赤線 “Update Time” か Events ではないだろうか。そこで、この両者がそれぞれ、どうなっているか調べてみた。
grep で調べてみた所、正に sdf 〜 sdi の情報が “時間的に古い” イベント”カウント的に古い”事が分かる。時間はmdadm 外からいじる事ができるので、 Eventsで管理しているのかもしれない。後はどうやって修正するかなのだが..。ここで
# mdadm --assemble --help
で assemble (=再構築) に関するオプションを調べる。すると最後の方に Options の説明で
– -force オプションに out-of-date の説明が見える。どうやら – -force を使うと out-of-date を解消できそうです。やってみましょう。
90 UP to 94 がゆっくり 1 ずつ増加します。時々、止まったりして、かなりリアルです。見事、ERRORは修正されました。
ネットで検索してみると、mdadm では out of date ERROR が良く起きるみたいで、out of date の解消法の質問に遭遇します。この – -force を知っていれば、スターウォーズでも戦えるかも。
あと、- -run を併用すれば、完璧に治らなくても、縮退モードで動作させる事もできます。
それから、間違って F フラグをディスクに設定した場合等もこの – -force で修正する事ができます。
但し 100% 修正できるか分かりません。あくまで緊急対応です。基本は正しく電源ON/OFF です。
メンテナンス用 ツールの整理 ( master側 ) 【2025年3月26日 記録】
本システムは /sbin/ 下に xxxx.sh で幾つか自作のツールを配置しています。それぞれ作ったタイミングで説明はしているのですが、何処になにの説明が有るか位は整理してきおきたいと思います。
UsbCopy.sh
PC1台 54TB RAID5 システム【Part 1】鈴木のOMV7 ベースセットをコピーする に説明。USBメモリーコピープログラム
RemoteSync.sh
PC1台 54TB RAID5 システム【Part 2】rsync補助 プロトコルに説明。漢字を含むフォルダーコピーに便利なプログラム
StartUptime.sh
PC1台 54TB RAID5 システム【Part 1】StartUptime.service 導入で、動作タイミングを
PC2台連携 108TB RAID6 システム【Part 2】再起動時のRAID環境の再構築で 動作内容を説明している。
ShutDowntime.sh
PC1台 54TB RAID5 システム【Part 1】ShutDowntime.service 導入で、動作タイミングを
PC2台連携 108TB RAID6 システム【Part 1】電源OFF時 ツールで、動作内容を説明している。
DiskInfoM.sh
PC2台連携 108TB RAID6 システム【Part 1】DiskInfo ツール で内容を説明
_Beep.sh
他のプログラムの補助的プログラム _Beep.sh n で n回 Beepを鳴らす。(現在 n = 1 〜 4) パラメータ外の時はなにもしない。
_DiskIdM.sh
ディスクシリアルを一元管理する為の補助的プログラム、master側 ディスク交換時には生シリアルを書き直すのは この関数のみ 他はこの関数を呼び出す事でシリアル番号を得る。_DiskIdM.sh n ( n = 0 ~ 7 )で /dev/disk/by-id/ 下にあるシリアル番号を返す。操作すればわかるが、n = 0 〜 3 では、master側 ディスクのシリアル番号、n = 4 〜 7 では scsi-36…10001 〜 scsi-36… 40001 を返す、これはiSCSIディスクのシリアル番号での扱い。
RAIDスクラビング & デフラグ
PC1台 54TB RAID5 システム【Part 2】運用時のメンテナンスで説明しています。
メンテナンス用 ツールの整理 ( slave側 ) 【2025年3月26日 記録】
slave 側 PCも /sbin/ 下に xxxx.sh で幾つか自作のツールを配置しています。
UsbCopy.sh
PC1台 54TB RAID5 システム【Part 1】鈴木のOMV7 ベースセットをコピーする に説明。USBメモリーコピープログラム、master側 PC と同じ物
StartUptime.sh
PC1台 54TB RAID5 システム【Part 1】StartUptime.service 導入で、動作タイミングを説明。
PC2台連携 108TB RAID6 システム【Part 2】StartUptime.sh に Timeout Mismatch 対策 を追加
で内容を説明している。
ShutDowntime.sh
PC1台 54TB RAID5 システム【Part 1】ShutDowntime.service 導入で、動作タイミングを説明しているのみ。動作タイミング確認に Beep をならしているが、初期導入のままでも良い。
DiskInfoS.sh
PC2台連携 108TB RAID6 システム【Part 1】DiskInfo ツール で内容を説明
_Beep.sh
他のプログラムの補助的プログラム _Beep.sh n で n回 Beepを鳴らす。(現在 n = 1 〜 4) パラメータ外の時はなにもしない。
_DiskIdS.sh
ディスクシリアルを一元管理する為の補助的プログラム、slave側 ディスク交換時には生シリアルを書き直すのは この関数と、tgtサービスの設定になる。他の関数はこの関数を呼び出す事でシリアル番号を得る。_DiskIdS.sh n ( n = 4 ~ 7 )で /dev/disk/by-id/ 下にあるシリアル番号を返す。
故障時のディスク交換【追加 2025年4月13日】
“PC2台連携”システムは master、slave を iSCSIで繋いでいますので、その作業が追加されます。それも含めて、ディスク故障時のシュミレーションを行います。
故障ディスクの特定から電源OFF まで
RAID ディスク故障時の挙動については今一経験が少ないのですが、読み書きが極端に遅くなるとかで分かるようです。RAIDの状態を詳細に知るコマンド
# mdadm --detail /dev/md0
で出力に degraded (=劣化) の文字があれば、ハードディスクに障害が発生しています。
# cat /proc/mdstat
でも知る事ができます。この2つのコマンドでRAID の状態を知り、不良ディスクを特定します。
今 DISK6 ( = sdh ) が故障したと仮定します。DISK6 ( = sdh ) と仮定したのは、DISK4~DISK7は iSCSIで繋がっており、その分作業が追加になるからです。対して、故障ディスクがDISK0~DISK4 の場合の作業は【 】内に太字で 記入しておきます。
今、RAID は動作している状態です。RAID が動作中は(F) マークを付けないと remove できませんので、最初に fail コマンドを実行してから、sdh をremove します。
# mdadm --fail /dev/md0 /dev/sdh ← 故障マークを付けてRAIDに故障をしらせる # mdadm --remove /dev/md0 /dev/sdh ← 故障した sdh をRAID から(論理的に)はずす。
次に、(1) (2) (3) の順に実行して 電源 OFF します。
(1) 故障ディスクのスーパーブロックを消します。
# mdadm --zero-superblock /dev/sdh ← sdh のスーパーブロックを消している。
これは故障ディスクが悪さをしない為の予防措置です。ディスクを間違えないように(超重要)。
(2) つぎに StartUptime.sh を編集して、再起動時は、iSCSI ディスクの認識までを行い、RAID 再構築コマンド以降を実行しないようにします。以下 編集後の StartUptime.sh の一部です。
(3) ShutDowntime.sh を実行して RAID6 をストップ状態にします。下図は remove, から (1) (3) を順に実行した様子です。ストップ状態になったら、master, slave の順に電源を OFF します。
故障ディスク入れ替え後、iSCSI ディスクとして設定する。
今回は DISK6 ( = sdh) が故障しましたので、ディスクを入れ替えた後はDISK6を iSCSIディスクとして認識しないといけません。まず、slave 側だけを立ち上げた後に、(1) SSH端末で、_DiskIdS.sh に DISK6 の生シリアルを記入しなおします。(2) OMV7 のコントロール画面で サービス → Tgt → Targets → Backingstores のdisk6 の生シリアルを記入しなおします。(1)(2)を実行後、再度リブートします。【 故障ディスクが DISK0~DISK3 の場合は iSCSI設定作業は必要ありません。単に slave をリブートするだけです。master 電源OFF 時に故障ディスクを入れ替えて下さい 】
master リブート後、全ての DISKを確認する。
slave リブート後、master をリブートします。立ち上がったら、DiskInfoM.sh ですべてのディスクが認識されているか確認してください。【 故障ディスクが DISK0~DISK3 の場合はここで、_DiskIdM.sh の生シリアルを直します。DISK0~DISK3 の交換時に生シリアルを直すのはここだけです。】 すべて問題なくディスクが認識されたら、必要ならば ( = 通常 mdadm はスーパーヘッダーを検出できないと データの有無にかかわらず、データクリアされたディスクと同じに扱う) 入れ替えたディスクをスワイプします。まちがえないよう(超重要) 。
RAID再構築の前にここまでを完全にします。
RAID6 再構築・結果確認、StartUptime.sh 再編集
DiskInfoM.sh で、すべてのトライブを確認済みです。ここからは、StartUptime.sh の 後半の内容をマニュアルで実行します。この時、結果も確認します。以下 -v オプションも付けて、実際の様子を示します。
動作を確認できたので、StartUptime.sh を再編して元にもどし、通常の手順で電源OFF ( = ShutDowntime.sh → master, slave の順に電源をOFF ) します。
通常の手順で起動。StartUptime.sh のログ等で、動作を確認して下さい。
【2025年4月13日 作成ここまで】
mdadm ver1.2 の Super Block を編集する。【2025年4月14日 】
Super Blockを編集するのは超危険な行為ですので、必要がない方はここを飛ばして下さい。決してお勧めしません。編集は自己責任でお願い致します。繰り替えしますが、Super Blockをいじるのは決してお勧めしません。超危険です。
Super Block は何処にあるのでしょう。
mdadm のスーパーブロックは、mdadm の内部管理用なので、編集は禁止されています。私は何処にあるかも知りませんでした。そこで、今はやりのAI ( =copilot ) に聞いてみます。
mdadm バージョン毎のスーハ―ブロックの場所とバイト数を教えて。
- バージョン 0.9: 場所: ディスクの末尾。 サイズ: 約64KiB。
- バージョン 1.0:場所: ディスクの末尾から8KiB~12KiBの位置。サイズ: 約4KiB。
- バージョン 1.1:場所: ディスクの先頭。サイズ: 約4KiB。
- バージョン 1.2:場所: ディスクの先頭から4KiBの位置。サイズ: 約4KiB。
ついでに、ハードデイスクを直接編集できるか聞いてみた、一度領域をFile に読み出してから編集して元に戻す方法を提案された。読み出し / 書き込みは dd 命令で、編集は hexedit を使うらしい。これらの情報を元に まず、最初に領域を特定した。mdadm v1.2 なので、ディスク先頭から 4KiB (4096bytes) の位置から 512bytes を Super Block として扱う事にした。512Bytes 以降は 00H に設定されているので、現在は使っていないのかもしれない。4096 バイト目から 512+16 bytes の hexdump の例 を表示する。実際の解析は赤で囲んだあたりになると思います。これと examine 命令で表示した SuperBlock と比べると全部は無理にしても、かなりの部分、解析できそうです。
Super Block Read, Write, Edit
Super Block のRead / Write は dd コマンドを使います。基本は Read も Write も同じです。
# dd if=INPUT of=OUTPUT bs=1 skip=4096 or seek=4096 count=512 2>/dev/null
となります。 Read の場合は INPUT が ディスク /dev/sda 〜 /dev/sdi , OUPUT が ファイル名 skip=4096 , 2>/dev/null は余計な表示が消えるだけです。動作には影響ありません。Write の場合は INPUTがファイル名 , OUTPUTがディスク /dev/sda ~ /dev/sdi なので seek=4096 になります。ただし、この命令だけでは簡単すぎて、ケアレスミスを必ずしますので、しつこく入出力チェックをしています。SbReader.sh SbWriter.sh とも 先頭から4096 offset した 512bytesを扱います。プログラム内容をみれば容易に理解できると思います。(この程度が理解できない場合は必ずミスをしますので、Super Block の編集は諦めましょう。)
ソースを載せておきます。両ツールは /root 下で使います。SbReader.sh です。
#!/bin/bash # SbReader.sh ( SbReader.sh Super Block Read program for mdadm ver 1.2 ) # Cution! Super Block for mdadm v1.2 → Start 4096byte value = 512 byte) PATH=/usr/sbin:/usr/bin:/sbin:/bin if [ $( pwd ) != "/root" ]; then echo "ERROR Directory is not root" exit 0 fi if [ $# != 2 ]; then echo "" echo " (例) SbReader.sh <From device> <To file> " echo " (1) SbReader.sh sda SBAdisk" echo " (2) SbReader.sh sda /root/SBAdisk" echo "" exit 0 fi OK=0 if [ $1 = sda ]; then OK=1; fi if [ $1 = sdb ]; then OK=1; fi if [ $1 = sdc ]; then OK=1; fi if [ $1 = sdd ]; then OK=1; fi if [ $1 = sde ]; then OK=1; fi if [ $1 = sdf ]; then OK=1; fi if [ $1 = sdg ]; then OK=1; fi if [ $1 = sdh ]; then OK=1; fi if [ $1 = sdi ]; then OK=1; fi if [ $OK = 0 ]; then echo "ERROR $1 is not Drive [ sda - sdi ]" exit 0 fi OK=1 if [ $2 = sda ]; then OK=0; fi if [ $2 = sdb ]; then OK=0; fi if [ $2 = sdc ]; then OK=0; fi if [ $2 = sdd ]; then OK=0; fi if [ $2 = sde ]; then OK=0; fi if [ $2 = sdf ]; then OK=0; fi if [ $2 = sdg ]; then OK=0; fi if [ $2 = sdh ]; then OK=0; fi if [ $2 = sdi ]; then OK=0; fi if [ $OK = 0 ]; then echo "ERROR $2 is Drive [ sda - sdi ]" exit 0 fi OK=1 if [ $2 = "/dev/sda" ]; then OK=0; fi if [ $2 = "/dev/sdb" ]; then OK=0; fi if [ $2 = "/dev/sdc" ]; then OK=0; fi if [ $2 = "/dev/sdd" ]; then OK=0; fi if [ $2 = "/dev/sde" ]; then OK=0; fi if [ $2 = "/dev/sdf" ]; then OK=0; fi if [ $2 = "/dev/sdg" ]; then OK=0; fi if [ $2 = "/dev/sdh" ]; then OK=0; fi if [ $2 = "/dev/sdi" ]; then OK=0; fi if [ $OK = 0 ]; then echo "ERROR $2 is Drive [ /dev/sda - /dev/sdi ]" exit 0 fi if [ $# = 2 ]; then dd if=/dev/$1 of=$2 bs=1 skip=4096 count=512 2>/dev/null fi
SbWriter.sh です。
#!/bin/bash # SbWriter.sh ( SbWriter.sh Super Block Writer program for mdadm ver 1.2 ) # Cution! Super Block for mdadm v1.2 → Start 4096byte value = 512 byte) PATH=/usr/sbin:/usr/bin:/sbin:/bin if [ $( pwd ) != "/root" ]; then echo "ERROR Directory is not root" exit 0 fi if [ $# != 2 ]; then echo "" echo " (例) SbWriter.sh <From file> <To device> " echo " (1) SbWriter.sh SBAdisk sda" echo " (2) SbWriter.sh /root/SBAdisk sda" echo "" exit 0 fi OK=1 if [ $1 = "/dev/sda" ]; then OK=0; fi if [ $1 = "/dev/sdb" ]; then OK=0; fi if [ $1 = "/dev/sdc" ]; then OK=0; fi if [ $1 = "/dev/sdd" ]; then OK=0; fi if [ $1 = "/dev/sde" ]; then OK=0; fi if [ $1 = "/dev/sdf" ]; then OK=0; fi if [ $1 = "/dev/sdg" ]; then OK=0; fi if [ $1 = "/dev/sdh" ]; then OK=0; fi if [ $1 = "/dev/sdi" ]; then OK=0; fi if [ $OK = 0 ]; then echo "ERROR $1 is Drive [ /dev/sda - /dev/sdi ]" exit 0 fi OK=1 if [ $1 = sda ]; then OK=0; fi if [ $1 = sdb ]; then OK=0; fi if [ $1 = sdc ]; then OK=0; fi if [ $1 = sdd ]; then OK=0; fi if [ $1 = sde ]; then OK=0; fi if [ $1 = sdf ]; then OK=0; fi if [ $1 = sdg ]; then OK=0; fi if [ $1 = sdh ]; then OK=0; fi if [ $1 = sdi ]; then OK=0; fi if [ $OK = 0 ]; then echo "ERROR $1 is Drive [ sda - sdi ]" exit 0 fi OK=0 if [ $2 = sda ]; then OK=1; fi if [ $2 = sdb ]; then OK=1; fi if [ $2 = sdc ]; then OK=1; fi if [ $2 = sdd ]; then OK=1; fi if [ $2 = sde ]; then OK=1; fi if [ $2 = sdf ]; then OK=1; fi if [ $2 = sdg ]; then OK=1; fi if [ $2 = sdh ]; then OK=1; fi if [ $2 = sdi ]; then OK=1; fi if [ $OK = 0 ]; then echo "ERROR $2 is not Drive [ sda - sdi ]" exit 0 fi if [ $( wc -c < $1 ) != 512 ]; then echo "ERROR for File bytes count(=512)" exit 0 fi echo "" echo -n "Out to /dev/$2 , Ara you OK? [Y/n]: " read ANS case $ANS in Y ) ;; y ) ;; * ) echo "" echo "# SbWriter Not Started !!!" echo -n "# "; date; echo "" exit 0 ;; esac echo "# dd if=$1 of=/dev/$2 bs=1 seek=4096 count=512" echo "" dd if=$1 of=/dev/$2 bs=1 seek=4096 count=512
読みだした File の編集は hexedit を使います。 hexedit の使い方は各自、お調べ下さい。
# hexedit -l16 <File名> ← 横 16bytes 表示で使います。
Super Block 編集の目的は…
危険な Super Block 編集をしようというのには理由があります。mdadm の状態を表すとき cat /proc/mdstat と打つと 答えに sda[0] sdb[1] sdc[2] sdd[3] sde[4] 〜 sdi[7] が表示されます。この[ ] 内の数字はデバイスインデックスと呼ばれるらしいのですが ( =copilot調べ ) 最初 md0 をクリエイトした時に DISK0~DISK7 の 順番通り sd[abc 〜 i] と入力すると それぞれ対応のディスク番号がちょうどインデックスとして入ります。つまり sdn と DISKm がすぐわかります。所が故障ディスクを入れ替えた場合、このインデックスが進むのです。例えば sdh[6] を入れ替えた場合 0 〜 7 の次の数字 8 になります。つまり sdh[8] になるのです、例えば次に sdb[1] を入れ替えると sdb[9] になります。まあ、RAID動作に支障はないので、そういうものだとの考えもありますが、私は sdh[8] → sdh[6] にしたいのです。現在の私の知識では、mdadm のコマンドで変更する事ができませんでした。SuperBlockの 1 Byte を変更すると (正確にはそのあと Checksum も変更する) 可能な事が分かっています。この後 実際に sdh[8] → sdh[6] に変更する様子を示します。
ディスク番号とデバイスインデックスを同じにする
丁度、ディスク交換のシュミレーションとして DISK6 sdh ディスクを交換中です。以下にRAID のmdstat を示します。 sdh [8] になっているのが分かると思います。
これを、 sdh [8] → sdh[6] とする事でデバイスインデックスをディスク番号と同じに致します。
まず、ShutDowntime.sh を実行して RAID をストップ状態にします。現在の sdh のスーパーブロックのようすを見ておきます。
さて、事前の調査で、デバイスインデックスを示すバイトは 4096 + a0H であると分かっています。以下の赤線のバイトを 08 → 06 に変更して、/dev/sdh に書き込みます。
書き込んだ後に /dev/sdh のスーパーブロックを見ると、Device Role が spare になっています。但し check sum が違っていますので、check sum を修正して、もう一度書き込みます。check sum が違っていると組み込み拒否されます。
Device Role : spare , Checksum : correct で、次に進みます。
ディスクが揃っているのを確認したら、RAIDを構築します。構築に、sdh が足りなくて立ち上がらない事が想定されるので – – run オプションを付けている。立ち上がると spare はすぐに投入されるみたいです、その時インデックスが 6 なので、自動的に sdh[6] になるのでは…? 。この後に mount する必要があるが、上図では省いてある。図外で問題なくマウントした。
【2025年4月14日 作成ここまで】