USB HDDをソフトウェアRAIDでミラーリングして家庭内ストレージを作った

MacBook Air をメインにしてから以降、本体のストレージ領域が小さいことから、音楽データや写真データなどは、 外付けの USB HDD に保存するようにしているのだが、1つの HDD にしか保存していなかったので、 こいつが死んだら困るなぁ、と思っていた。

しかし、なんとかしないと、と思いつつもそのままの状態ですでに3年近くたってしまっていた。(笑)

それでも最近夏の暑さのためか、周りで HDD の故障の話をよく聞くようになってきたし、そろそろやらねばさすがにヤバイと、 ようやく重い腰をあげた次第だ。

方法としては、とりあえず、RAID1でミラーリングし、HDD自体の耐障害性のみを高めるということにした。[1]

20130821080256

今までの環境

今までは Mac mini に USB HDD を接続して、それを共有することで NAS 代わりにしていた。 これはだいぶお手軽で、OS X はソフトウェアRAIDもとてもカジュアルに作ることができる[2]ので、 この環境のまま RAID 化するのが一番楽だったと思う。

ただ、うちでは Mac mini の他にも古い Thinkpad を OpenVPN サーバとして使用していて[3]、 常時起動しているマシンが2台あり、これをどちらか片方だけにしたいとずっと思っていたので、 これを機に Thinkpad に統一させることにする。

方法

最初は、 裸族のテラスハウス RAID のような商品でRAIDしてくれるなら楽でいいかな〜と思っていたのだけど、 「安物のRAIDコントローラ使うくらいならソフトウェアRAIDのほうがマシ」という 組長若頭 の教えをうけて、 Thinkpad に入っている ubuntu でソフトウェアRAIDを組むことにした。

なので方法としては、

  • ThinkpadにUSB HDDを2台以上つける
  • それらをRAID1でミラーリングさせる
  • その領域を netatalk で共有する

という流れになる。[4]

買ったもの

UbuntuでのソフトウェアRAID構築

mdadm というコマンドでやるらしい。

  • man 4 md
  • man 8 mdadm

に詳しくのっていた。

mdadmのインストール

sudo apt-get install mdadm

USB HDD 接続

/dev/sdb/dev/sdc として認識される。

fdisk で領域確保

Linux raid autodetect (id: fd) として領域確保する。 今回は sdb sdc それぞれの全領域を割り当て。

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048  3907029167  1953513560   fd  Linux raid autodetect
/dev/sdc1            2048  3907029167  1953513560   fd  Linux raid autodetect

こんな感じで sdb1 と sdc1 ができていればOK。

mdadm でRAID作成

sudo mdadm --create /dev/md0 --level 1 --raid-devices=2 /dev/sdb1 /dev/sdc1

としてソフトウェアRAIDを作成。RAID1で、sdb1とsdc1を、 /dev/md0 という仮想デバイスに作成、という意味。

フォーマット

sudo mkfs -t ext4 /dev/md0

再起動しても /dev/md0 ができるようにする

sudo update-initramfs -u

普通はこれをやる時に、mdadm.conf に ARRAY /dev/md0 ... という設定を書くみたいだが、 USB HDD だからか、これを書いているとなぜか起動時に認識されないので、ARRAY の設定は書かないように設定。[5]

マウント

sudo mkdir /mnt/raid
sudo mount -t ext4 /dev/md0 /mnt/raid

再起動時にも自動でマウントされるようにする

sudo blkid

して、 /dev/md0 の UUID を調べ、 /etc/fstab に、

UUID=そのUUID       /mnt/raid       ext4    defaults        0       0

という行を書いておく。

ここまでで、再起動しても自動的にRAIDボリュームが認識されマウントされるようになる。

RAIDに問題があった時に通知させる

RAIDを組んでもHDDが壊れた場合などに気がつけないと意味がないので通知の設定もしておく。

mdadm.conf

PROGRAM /home/typester/bin/mdadm-notify.sh

とか書いておくと、RAIDのステータスが変わった時にそのプログラムを実行してくれる。 ステータスと対象デバイスは引数でそれぞれ取得できる。

僕は im.kayac.com で通知させる以下のようなスクリプトをおいた。

#!/bin/sh

event=$1
device=$2

curl -s -d "message=[mdadm] $event $device" http://im.kayac.com/api/post/ユーザー名 >/dev/null

通知のテストは、

sudo mdadm --monitor --test /dev/md0

で行なうことができる。

また、通知システムがちゃんと動いているか確認するために、 Ubuntu では cron.daily 時にも通知が来るようになっているみたい。

以上でRAID周りの設定は完了

SMARTの設定

あんまり信用してないけど、念のためSMARTでHDDの状態も監視するようにする。

Smartmontools - Community Ubuntu Documentation

が詳しい。

smartmontoolsインストール

sudo apt-get install smartmontools

有効になってなかったらSMARTを有効にする

sudo smartctl -s on /dev/sda
sudo smartctl -s on /dev/sdb
sudo smartctl -s on /dev/sdc

smartmonが自動起動されるようにする

/etc/default/smartmontoolsstart_smartd=yes のコメントアウトをはずしておけばOK。

SMARTでなにか検知した場合に通知させる

デフォルトでは smartd.conf には通知プログラムとして smartd-runner というのが登録されている。 これは /etc/smartmontools/run.d にあるスクリプトを実行してくれるラッパーのようだ。

以下のようなスクリプトを /etc/smartmontools/run.d/60notify として置き、実行権限をつけておく。

#!/bin/sh
curl -s -d "message=[SMART] $SMARTD_DEVICE may have a problem" http://im.kayac.com/api/post/ユーザー名 >/dev/null

この通知のテストは、 smartd.conf の

DEVICESCAN -d removable -n standby -m root -M exec /usr/share/smartmontools/smartd-runner

という行の末尾に -M test とつけて保存したあと、 sudo service smartmontools restart すると行なうことができる。

netatalkでAFP共有

netatalk を使って Mac からこのRAIDボリュームにアクセスできるようにする。 Ubuntu 12.04 のパッケージは古かったので、ソースからビルドした。

インストール

まず、 libgcrypt-dev をインストールする。これが入ってないと新しめのMacからは認証できなくて接続できない。

sudo apt-get install libgcrypt11-dev

あとは普通にインストール

./configure --with-zeroconf --with-init-style=debian
make
sudo paco -D make install

設定

試行錯誤した結果 afp.conf はこんな感じになった。

[Global]
; Global server settings
save password = no
mimic model = Xserve

;log level = default:debug

[Time Machine]
path = /mnt/raid/tm
time machine = yes
vol size limit = 1000000

[Shared]
path = /mnt/raid/storage/shared

あと追加で、

[Homes]
home name = Private
basedir regex = /home
path = afp-data

という設定もしてあって、これはユーザー毎の ~/afp-data を Private という名前で共有する、という設定だが、

  • home name に $u を含める必要がある
  • ~/afp-data は実際には /var/raid/storage/{username} への symlink なのだが、symlink だと動かない

というようなnetatalkの制限があったので、適当にソースコードを修正してそれらを回避している。

起動

sudo service netatalk start

使用方法

接続するとこのように3つのボリュームが見える。

スクリーンショット 2013-08-21 10.50.36

Time Machine はそのままで、Time Machine バックアップ用、 Shared は家族間で共有するデータを入れる用(アカウントがある人はすべて同じデータにアクセスできる)、 Private はそれぞれのユーザ専用領域、という感じになっている。

まとめ

これでようやく、 Mac mini を常時起動しなくてもよくなった。 Mac mini でやるのと比べるとたぶんだいぶセットアップは面倒だと思うが、細かい通知の設定などはLinuxのほうがしやすいのではないか、と思った。

裸族のテラスハウスは思ったより作りもしっかりしているし、その辺の安物のHDDケースとは違ってずっと使っていても熱くならないので、 だいぶ好印象。

ただ、2TBのRAIDのresyncに10時間くらいかかったので、HDD2つだけだとちょっと不安なところである…。[6]

あと、ミラーリングとは別にバックアップしたいが、その方法はまだ未定。 これは自前でやりたくないのでどこかのサービスを使いたいのだけど、どれも決め手に欠ける。 bitcasa が Linux に対応したら最有力候補なんだけど、いつになることやら。