Software RAID on Vine Linux 6.5

以下では当方で運用しているソフトウェアRAIDについて紹介します。
2018-09-20  

1. はじめに
2. 実行環境
3. 再起動
4. mdadmの設定(RAID5)
5. 管理運用
6. メールの設定
7. まとめ


1. はじめに

ここでは、LinuxによるソフトウェアRAIDの実行例を示します。遠隔地で稼働しているサーバにRAIDを導入した際の設定・管理運用法等が主題となります。具体的にはHDDケースに収納した2TBx4のHDDをRAID5で4TBのHDDとし、データ保管庫として運用しています。

最初に実行環境を提示し、次に再起動に関する問題について言及します。その後、mdadmによるRAID5の設定を行い、さらに、管理運用、障害時の対応などについてmdmonitorを中心に検証していきます。最後にメールの送信について考えますが、これはRAIDに特有な問題ではありません。

なお、以下に記載されている価格は税込です。


2. 実行環境

OSは、Vine Linux 6.5、ソフトウェアRAIDのユーティリティであるmdadmは、2.6.9です。Vineの更新が滞っているため少し古目なのが、幾分、気になるところではありますが、特に問題なく動作しています。

ハードウェアは
malva.karing.jp
CPU Pentium4 651 3.4GHz
RAM DDR2 1536MB
マザーボード AOPEN i915Ga-E
on board sound Intel HD Audio
on board NIC Marvell 88E8053
SATA HDD Hitachi HDT72502 250GB
SATA HDD WDC WD10EACS 1TB
DVD-RAM MATSHITA DVD-RAM SW-9587S
PCI USB CARD IO data 1394US2-PCI
HDD case MARSHAL MAL-3035SBKU3
SATA HDD HGST 2TBx4
OS Vine Linux 6.5

image of MAL-3035SBKU3.jpg 今時、Pentium4の機体もないだろ、と思わないでもないですが、遠隔地にある機体なのでなかなか思うように更新できません。

上記の太字部分がRAID関連で、2TBx3のHDDを搭載したHDDケース(MARSHAL MAL-3035SBKU3)がUSB拡張カード経由で接続されています。HDDケースであるMAL-3035SBKU3はHDDを4台搭載でき、インターフェイスはUSB3.0およびeSATAに対応しています。USBは内蔵のハブ経由で、eSATAはPMPにより、それぞれ一本のケーブルでPC本体と接続し、インターフェイスは接続しているケーブルにより自動選択されます。ハードウェアRAIDの機能はありませんが、秋葉原で実売12,000円ほどでコストパフォーマンスは高いと思います。

本体との接続は出来ればパフォーマンスの観点からeSATAで行いたいのですが、i915Ga-EのICH6はPMPに対応していないためMAL-3035SBKU3にeSATAで接続した場合、HDDは一つしか認識できません。というわけでUSBで接続するわけですが、このHDDケースを接続したまま再起動するとBIOSが途中でストールし、接続を外すとBIOSは再び動き出すという事態に遭遇しました。MAL-3035SBKU3の仕様ではOS起動後に接続することとなっているのでこれは不具合ではないものの、遠隔地に設置してあるサーバが正常に再起動できないのでは何かと困るので、この問題はMAL-3035SBKU3をBIOSの制御下にないUSB拡張カードのポートに接続することでとりあえず回避しています。詳細は次項で言及します。

実装しているHDDは2TBx4で、3台をRAID5とし1台をスペアとする4TBのHDDとして運用しています。HDDは中古で一個4,320円でした。HGST製の同じ物で揃えています。


3. 再起動

MAL-3035SBKU3(HDDケース)の仕様では、OSの起動後に接続して使用するようにと説明書にあるのですが、遠隔地で運用する場合、再起動時にケーブルの脱着もしくは電源の入切を物理的に行うことができず、仕様に沿う運用は困難です。実際にこのHDDケースをi915Ga-EのUSBポートに接続したまま再起動した場合、BIOS起動時にストールしてしまいます。ならば、いっそeSATAで運用できればとPMP対応のeSATA拡張カードも試してみたのですが、これはOS(Vine Linux 6.5、kernel-4.4.110-2vl6.i686)起動中に途中でストールしてしまいました。なんとかならないかと手持ちのマザーボード3種とeSATA拡張カード、USB拡張カードでHDDケースを接続したままの再起動を試行してみた結果が以下です。

マザーボード SATA PMP eSATA SATA3E2-PCIe USB 1394US2-PCI
AOpen i915Ga-E × ×
FOXCONN 45CM-S × ×
ASRock H67M-GE/THW ×

まず、手持ちのマザーボードにはPMP対応の物はありませんでした。そして、PMP対応eSATA増設カードで再起動時にも問題が起きなかった(ストールしなかった)マザーボードはH67M-GE/THWのみでした。しかし、このH67M-GE/THW、USB3.0を使うと固まるという問題があるため信頼性に難があり、USB3.0を無効にした状態で経過観察中となっています。そのため、PC本体の方は従来のまま(i915Ga-E)でUSB拡張カードを増設し、その増設ポート経由でHDDケースを接続するということになりました。

外付けのRAIDとしては、HDDはSATAですのでeSATAでの接続が第一の選択肢となるのですが、HDDケースと本体とを一本のケーブルでつなぐPMPはPC本体側の対応の有無が非常にわかりづらく、性能に優れるわけでなく、避けられるなら避けた方が無難だと思います。CenturyのCRCH35E4ISなどはPMPではなく、HDD1台毎にケーブルが独立しており、インターフェイスも単純で再起動の問題も出難いと思われます。難点はSATAポートを多数必要とすることとケーブル数が増えるため配線周りが物理的に混雑することです。


4. mdadmの設定(RAID5)

RAID環境の構築にあたり、ここではソフトウェアRAIDでRAID5を選択しています。なぜソフトウェアRAIDなのかと言えば柔軟性と操作性になります。ソフトウェアRAIDはOSと一体化しているので細かな設定も容易ですが、ハードウェアRAIDの場合、ディスクIO以外の操作はそのハードウェアRAID固有のレイヤーを介さなければ、通常、OSからはできません。Windowsならばそれらの専用ツールなりが用意されていることもあるのでしょうが、Linuxでは望み薄です。Linuxで遠隔地からRAIDを操作しようと思えばハードウェアRAIDの選択肢はなくなります。また、なぜRAID5なのかと言えば、単純に容量の効率性を重視したためです。

LinuxのソフトウェアRAIDでは、「mdadm」を使います。RAIDを構成するHDDはパーティションを単位とします。厳密にはパーティションでなくても可能ですが、特段のメリットはありません。
# mdadm --create /dev/md0 -n 3 -l 5 /dev/sdc1 /dev/sdd1 /dev/sde1

RAID5の設定は上記のコマンドだけで終了です。/dev/md0がRAID5によって作成される仮想デバイスです。オプションの「-n 3」はHDDを3台使用することを指定しており、「-l 5」がRAID5であることを指定しています。そして、オプションに続き、このRAID5で使用するデバイスが列記されています。RAID5の仮想デバイスが作成されるとmdadmは最初に2台のデバイスの差分を残りの1台に保存していきます。この処理(リビルド)は自動的に開始され、仮想デバイス(/dev/md0)の操作に影響を与えることなく、進行し、完了します。

次にこのRAID5の設定を下記のコマンドで取得します(下記のコマンドでは/dev/md0は指定されていないことに注意、このヴァージョンは2.6.9、ヴァージョンにより微妙に挙動が異なります)。再起動などして一旦RAIDが開放された後、RAID(/dev/md0)を再構成する時は、「--assmeble」モードでこの設定ファイルを使います。
# mdadm --detail --scan >mdadm.conf
# cat mdadm.conf
ARRAY /dev/md0 level=raid5 num-devices=3 metadata=1.02 name=malva.karing.jp:0 UUID=3a10eafd:c5cd7108:a69dcd51:b150da3e

ここで、一旦、RAID5を停止し、
# mdadm -S /dev/md0
mdadm: stopped /dev/md0

先に作成した設定ファイルで再構成してみます。
# mdadm --assemble /dev/md0 -c mdadm.conf
mdadm: /dev/md0 has been started with 3 drives.

RAIDの再構成は作成時と類似の以下のようなフォーマットでも可能ですが、再起動時にデバイス名が同一とは限らないので設定ファイルを使用した方が何かと安全だと思います。
# mdadm --assemble /dev/md0 -n 3 -l 5 /dev/sdc1 /dev/sdd1 /dev/sde1

最後にスペアデバイス(/dev/sdf1)を追加してみます。このスペアデバイスは上記のRAID5を構成する3台の内の1台が壊れた時、自動的にその代替となります。
# mdadm /dev/md0 --add /dev/sdf1
# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sdc1[0] sdf1[4](S) sde1[3] sdd1[1]
   3906764800 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/3] [UUU]
   bitmap: 0/15 pages [0KB], 65536KB chunk

unused devices: <none>

上記の「sdf1[4](S)」が追加したスペアデバイスです。なお、スペアデバイスの追加によりRAID5の設定が変わっているため再起動時に使用する設定ファイルを更新する必要があります。再度、以下のコマンドを実行して下さい。
# mdadm --detail --scan >mdadm.conf

この項の最後にこのRAID5のパフォーマンスを「hdparm -Tt」で調べてみます。
# hdparm -Tt /dev/md0

/dev/md0:
 Timing cached reads:   4952 MB in  2.00 seconds = 2480.28 MB/sec
 Timing buffered disk reads:  112 MB in  3.01 seconds =  37.17 MB/sec
# hdparm -Tt /dev/sdd

/dev/sdd:
 Timing cached reads:   6130 MB in  2.00 seconds = 3069.22 MB/sec
 Timing buffered disk reads:  104 MB in  3.01 seconds =  34.51 MB/sec
# hdparm -Tt /dev/sda

/dev/sda:
 Timing cached reads:   6000 MB in  2.00 seconds = 3003.34 MB/sec
 Timing buffered disk reads:  192 MB in  3.03 seconds =  63.46 MB/sec
/dev/md0はRAID5の仮想デバイス、/dev/sddはRAID5を構成する物理デバイスの一つでSATAをUSB2.0に変換、接続したもの、/dev/sdaはSATAのシステムドライブです。上記の結果では、RAID5のパフォーマンスは構成する物理デバイス(USB2.0接続)のパフォーマンスとほぼ同じ、/dev/sdd(USB2.0接続)のパフォーマンスはSATAの半分、くらいの感じでしょうか。


5. 管理運用

前項でRAID5が構築されました。すでに仮想デバイスは通常のHDD同様に操作が可能となり、次なる課題は管理運用となります。まずは管理運用の前提としてRAIDの情報を取得します。その情報の取得には大きく二つの方法があります。一つは/proc/mdstatで
# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4]
md0 : active raid5 sdc1[0] sdf1[4](S) sde1[3] sdd1[1]
   3906764800 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/3] [UUU]
   bitmap: 0/15 pages [0KB], 65536KB chunk

unused devices: <none>

もう一つは、mdadmの「--detail(-D)」オプションによるものです。
# mdadm --detail /dev/md0 
/dev/md0:
        Version : 1.02
  Creation Time : Tue Mar 20 18:44:04 2018
     Raid Level : raid5
     Array Size : 3906764800 (3725.78 GiB 4000.53 GB)
  Used Dev Size : 1953382400 (1862.89 GiB 2000.26 GB)
   Raid Devices : 3
  Total Devices : 4
Preferred Minor : 0
    Persistence : Superblock is persistent

  Intent Bitmap : Internal

    Update Time : Tue Sep  4 14:00:44 2018
          State : clean
 Active Devices : 3
Working Devices : 4
 Failed Devices : 0
  Spare Devices : 1

         Layout : left-symmetric
     Chunk Size : 512K

           Name : malva.karing.jp:0
           UUID : 3a10eafd:c5cd7108:a69dcd51:b150da3e
         Events : 31533

    Number   Major   Minor   RaidDevice State
       0       8       33        0      active sync   /dev/sdc1
       1       8       49        1      active sync   /dev/sdd1
       3       8       65        2      active sync   /dev/sde1

       4       8       81        -      spare   /dev/sdf1

情報の取得が出来たなら、次に管理用のデーモンを稼働させます。RAIDの目的は何か障害が起きた場合に柔軟・適切に対応することで、そのために「mdmonitor」をデーモンとして常駐させます。Vineの場合は/etc/init.d/mdmonitorにあります。

mdmonitorの大きな役割はその管理するRAIDに何か異常を感知した際に予め設定された動作を実行することです。その設定ファイルは「/etc/mdadm.conf」になります。この設定ファイルにはRAIDそのものを再構成するための設定(「mdadm -D /dev/md0」の出力)なども記述可能ですが、当環境ではRAIDの再起動時の再構成は独立して実行し(rc.localによる実行)、/etc/mdadm.confには異常時の動作のみを設定しています。

異常時の動作の設定には主に「MAILADDR」と「PROGRAM」があります。記述するのはどちらか一つでもかまいません。「MAILADDR」はmdmonitorが障害メールを送る宛先のメールアドレスを空白で区切って一つだけ記述します。ただし、「MAILADDR」はローカルホストのメールキューにメールをドロップしているだけなのでローカルホストのメールサーバが正常に稼働していないとメールは送信されません。「PROGRAM」は異常時に実行するプログラムを空白で区切って一つだけ記述します。「PROGRAM」の実行時には、その実行理由を示している数単語がそのプログラムに引数として渡されます。実際のプログラムの一例は次項で取り上げます

なお、「MAILADDR」と「PROGRAM」では実行される異常のレベルが異なっており、「MAILADDR」はデバイスの障害などクリティカルな状態にならないとメールを送信しませんが、「PROGRAM」は何かRAIDの状態に変化があった時(RAIDの開始、リビルドの終了など)には逐一実行されます。
ex.
MAILADDR yoshino@rita.karing.jp
PROGRAM /root/bin/mdadm.program.sh

設定ファイルが完成したら以下を実行し、mdmonitorを有効にします。
# chkconfig --level 345 mdmonitor on
# /etc/init.d/mdmonitor start

また、mdadmの設定やOSにおけるソフトウェア的な管理運用を越える問題として、デバイスファイルと物理デバイスの対応があります。この対応が特定できていないと障害時にどの物理デバイスが障害を起こしたのかさえ特定できない事態に陥ります。特にRAIDでは多数の同一デバイスを使用するためその特定は容易ではなく、決定的な特定法はありません。現実的には、HDDを1台ごとに接続し、その度にデバイスファイルを確認するか、何らかの読み書きを実行し、HDDのアクセスランプで確定するという原始的な方法くらいしかないと思います。障害発生後ではこのアクセスランプの挙動もどうなるかは予測不能・不確定であり、正常時に予めデバイスファイルと物理デバイスの対応を確認しておくことは重要です。

・障害時シミュレーション
RAIDの目的は障害発生時に柔軟・適切な対応を可能にすることですが、実際そうなった時にどうなるのかは経験してみないとなかなかわかりづらいものがあります。そこで、障害をシミュレーションして、将来の非常事態に備えます。

まず、ここでRAID5(/dev/md0)を構成しているデバイスの一つ「/dev/sdb1」を「--fail(-f)」で壊れたことにします。
# mdadm /dev/md0 -f /dev/sdb1
mdadm: set /dev/sdb1 faulty in /dev/md0

そうすると「MAILADDR」と「PROGRAM」が実行されるはずです。実行されなければ何か問題があるので設定等を再検証して下さい。また、当環境ではスペアデバイスが設定されているのでこの時点でスペアデバイスがアクティブになり、正常な2台と同期するためのリビルドが開始されます。

次に壊れた「/dev/sdb1」を「--remove(-r)」で外し、
# mdadm /dev/md0 -r /dev/sdb1
mdadm: hot removed /dev/sdb1 from /dev/md0

そして、正常なデバイスを「--add(-a)」で追加します。ここでは「/dev/sdb1」は壊れてはいないので「/dev/sdb1」を、再度、このRAID5に戻しています。実際の障害では「--remove(-r)」で問題のデバイスをRAIDから論理的に削除し、その後にその問題のデバイスを物理的に外します。続いて交換用の正常なデバイスを物理的に接続し、その後にその新しいデバイスを「--add(-a)」でRAIDに追加します。
# mdadm /dev/md0 -a /dev/sdb1
mdadm: added /dev/sdb1

当環境では、この代替として追加された「/dev/sdb1」はスペアデバイスとなりますが、スペアデバイスのないRAID5の環境下ではこの「/dev/sdb1」のリビルドが開始されます。

ここまでの一連の操作では「MAILADDR」でメールが送られるのは「--fail(-f)」のみです。「PROGRAM」は基本的に逐一実行されますが、必ずしもその実行はコマンドライン操作と一対一に対応しているわけではなく、あくまでRAIDの状態に反応しているので想定と微妙に異なる動作をする場合があります。たとえば、スペアデバイスの脱着はRAIDの本体に影響がない場合、「PROGRAM」は実行されません。


6. メールの設定

前述したようにmdmonitorが実装しているメール送信機能(MAILADDR)はローカルのメールキューにメールを投げるだけなのでローカルのメールサーバを正しく設定していないとOP25Bが実施されている現在のインターネット環境ではメールを送信できません。かつてOP25Bが導入される以前は
$ echo "MAIL FROM: <64L118@mail.example.ac.jp>
RCPT TO: <yoshino@rita.karing.jp>
DATA
test mail
.
" >/dev/tcp/rita.karing.jp/25
こんなふうにecho一発で宛先のあるメールサーバへ直接かつ一方的にメールを投げつけるだけでも届いていたので、各種デーモンや自動実行のスクリプトから警告メールなどを送信するのも簡単でした。しかし、さすがにそれではインターネットがスパムまみれになるということでOP25Bが導入されたわけですが、同時にメールの送信はプロバイダ(社会的信用のあるネットワーク事業者)のメールサーバにリレーしてもらうことが事実上の強制となり、そのリレーには適切な認証が求められることとなりました。

というわけで、現在、一般人がメールを送信するためにはこの認証をクリアする必要があります。Linuxでスクリプトなどからメールを送信する場合は、認証をクリアできる設定を施したローカルのメールサーバを利用することが一般的のように見受けられますが、ただ警告メールを送信するためだけにメールサーバを運用するのは鶏に牛刀のようにも思えるので、ここではローカルのメールサーバは使用せず、簡易なメール送信コマンドで場当たり的に処理しています。つまり、ローカルのメールサーバを必須とする「MAILADDR」の機能は使用せず、「PROGRAM」に設定したスクリプトよってメールを送信しています。「MAILADDR」で送信されるイベントでは「PROGRAM」も同時に実行されるので「PROGRAM」だけで十分で、上位のイベントにしか反応しない「MAILADDR」は冗長に思われます。

以下のスクリプトは前項で触れた「PROGRAM」の一例です。このスクリプトは、mdmonitorが何かイベントを感知すると実行され、日付、イベント、/dev/md0の状態(mdadm -D /dev/md0)、/proc/mdstatをメールで知らせてくれます。
#!/bin/sh

ex_YmdHM=`LANG=C date '+%Y-%m-%d %a %H:%M'`
mail_text="$ex_YmdHM

$*

`mdadm -D /dev/md0`
----------
`cat /proc/mdstat`
"

sub="$HOSTNAME RAID INFOMATION, $*"

mail_server=smtp.example.ac.jp
mail_user=64L118
mail_from=64L118@mail.example.ac.jp
rcpt_to=yoshino@rita.karing.jp

clsmtpc -P 587 -M $mail_server -U $mail_user \
    -F $mail_from -T $rcpt_to \
    -A auto -p $HOME/.clpasswd \
    -s "$sub" "$mail_text"

exit 0
件のメール送信コマンドがclsmtpcになります。"-P 587"は通常のSMTPポートである25がOP25Bで使えないための回避手段で25番ポートの代替であるサブミッションポート587番を使用することを指定しています。"-M $mail_server"はメールを送信(リレー)してもらうためのプロバイダなどのメールサーバを指定します。"-U $mail_user"はそのメールサーバの認証用のユーザ名です。"-F $mail_from"は差出人のメールアドレスで"-T $rcpt_to"は受取人のメールアドレスになります。"-A auto"は認証法を指定します。この例ではautoが指定されており、メールサーバが対応している認証法からより強度の強い認証法を選択します(digest-md5>cram-md5>plain>login>none)。"-p $HOME/.clpasswd"では認証用のパスワードファイルを指定します。パスワードファイルのフォーマットは、「username:smtp_server:password」となり、改行で複数記述することも可能です。この例では

64L118:smtp.example.ac.jp:xxxxxxxxxxx

というような感じになります。"-r"オプションを使えばパスワードをベタ書きできますが、セキュリティの観点から推奨されません。そして、"-s $sub"はメールのサブジェクト(件名)、最後の"$mail_text"が本文です。

clsmtpcはたんなるシェルスクリプトですので、動作の修正、独自の改良なども簡単にできると思います。また、SMTPsやTLS、添付ファイルなどにも対応しているので詳細はマニュアルを参照して下さい。
clsmtpc-0.1.5-1pe2.i686.rpm
clsmtpc-0.1.5.tar.gz

非対話的にメールを送信するコマンドとしてはmailxなどもありますが、mailxは多機能なメールスイートでちょっと望むものと違うというか、そもそもOP25Bは日本以外では一般的ではないので、それに対応した適当なマニュアルやチュートリアルがなく、結局、自力でやる方がわかりやすかったのでした。とはいえ、clsmtpcは前述した「echo一発」に機能拡張を重ねに重ねたもので自力でここまで重ねる前に既存のツールに乗り換えるべきだったと、正直、思わないでもないです。ついでなので、OP25Bにおけるメール送信について少し試行した結果を以下でまとめてみました。
OP25Bにおけるメール送信について


7. まとめ

実家に置いてあるメインサーバの旧機は、IBM xSeries 220で、この機体はハードウェアRAIDを搭載しており、さすがIBMのサーバ機というようなカッコ良さはあったものの古さ故の容量不足(77GBx3)とSCAという特殊性で扱いにくくなり、この新機に代換えしました。このIBMサーバでもRAID5で5年ほど運用していたのですが、幸か不幸か一度もHDDが壊れることなく退役することになりました。このハードウェアRAIDにはLinux用のツールも用意されており、ネットワークからも操作可能でそれなりに気に入っていたので何か他に使い道がないかと多少の模索はしましたが、結局、廃棄しかないという結論に至っています。

そんなこんなで、新しく外付けでRAIDを導入したわけですが、HDDケースなんてどれも一緒だろうと多寡をくくり、何も考えずに一番安いヤツで済ませてしまったのはちょっと失敗でした。なんと言っても接続したまま再起動できないというのは遠隔地にあるサーバには致命的ですし、PMPの扱いづらさにも辟易しました。後に調べたところ、CenturyのHDDケース、CRCH35E4ISにしておけば良かったと後悔しました。このHDDケースはHDD4台のケーブルが4本独立しており、HDDの認識が単純なので面倒事が少ないだろうと予想されます。まぁ、HDDケースから4本もケーブルが突き出てるのはバカっぽいと言えばバカっぽいのですが、ウチの環境的にはそのバカが正解だったと思われます。何事をやるにもリサーチは大事だと改めて実感、反省した次第です。

とはいえ、ソフトウェアRAIDの扱い自体は思ったより簡単でした。再起動の問題解決ではHDDケースの製品仕様を無視しているので大手を振って簡単だったとは言いづらくもあるのですが、思ったより簡単に導入できたのでHDDは2TBx4ではなく3TBx4にしておけば良かったと今さらながら思います。


2018-09-20 よしのぶ
yoshino@rita.karing.jp
  index.html


2018-09-20 Thr 12:00