原理的にできそうだと思ってやったところ実際に成功した。
(特殊ケースなので参考になるか不明)
#前提
- Ubuntu16.04.1
- RAID1 のアレイ(2コンポーネントで構成)について、正常状態→1コンポーネントが(特にデータ含め壊れていないものの)正常に接続・認識されていない状態で、(運悪く)アレイがstartされてしまい、かつそのアレイに対しwriteがあった(「片割れ」発生後の差分は多くはない)
- 上記の正常に接続・認識されなかったコンポーネントを「片割れ」と呼ぶことにする
- 「片割れ」のデータは片割れ発生直前時までは正常(であるはず)のため、そのデータをなるべく生かして復旧したい
- 今回は「片割れ」がSSDで起こったため、そのSSDへの書き込みをなるべく減らしたいという思い
- HDDなど書き込みがあっても許容できるストレージ(安いストレージ; 空きストレージ)を持っている必要あり
#簡易手順
- 空きストレージを mdadm --add して、resync 完了まで待つ(クローン元と呼ぶ)
- アレイをstop、mdadm のモニタリングプロセスを殺す
- クローン元から「片割れ」に対し、差分のみコピーを実施
- クローン元を接続解除後、アレイをstart(assemble)する
#説明
-
普通に mdadm --add {アレイ} {「片割れ」} でいきなり復旧するとresyncがかかり「片割れ」に対し全部書き込みが発生してしまうので、その戦略はとらない
-
なぜ中間のディスク(上記でいうと「クローン元」)を使用するのか?
- 実験環境にていきなり生存コンポーネントから「片割れ」に対し差分のみコピーを実施したが、それらを用いてうまくassemble できなかったため、やむを得ず- コンポーネントとなるパーティションの領域のなかに、実データ以外のメタデータとして、例えば「自分は何番のコンポーネント」とかの情報を持っている。生存アレイのクローンはその情報までクローンされてしまい、mdadm側がうまくassembleできないのではないかと推測
-
当然といえば当然ながら、アレイがルート(/)パーティションとなっている場合は、別ディスクのOSを準備してやったほうが無難(それ以外の方法は試していない)
- アレイがルートパーティションの場合は、1. 〜3.は別ディスクOS上で実施し、シャットダウン後、4. を実施
-
- の差分のみコピーのやり方について。適したツールとかあるかもしれないが、今回は以下のスクリプトで実施
-
ループ回数とかは環境により要見積り。必要数より大きくなるのは問題ない
-
今回は使えるパーティションがなかったため中間ディスクとしてループバックデバイスを使用
- 前準備概要: losetup でデバイス作って parted で全く同じサイズのパーティションを作る
-
効率分析用の echo があるが消してよい
FROM=/dev/loop7p1
TO=/dev/sdh1
for i in $(seq 95800); do
skips=$((i-1))
FROM_MD5=$(dd if=$FROM bs=5M count=1 skip=$skips | md5sum | awk '{print $1}')
TO_MD5=$(dd if=$TO bs=5M count=1 skip=$skips | md5sum | awk '{print $1}')
result=$([ "$FROM_MD5" = "$TO_MD5" ]; echo "$?")
echo RESULT $result $FROM_MD5 $TO_MD5
if [ "$result" = 1 ]; then
dd if=$FROM of=$TO bs=5M count=1 skip=$skips seek=$skips
fi
done