Linux RAID: RAID1 で取り残されたコンポーネントを全コピーすることなく復旧する


原理的にできそうだと思ってやったところ実際に成功した。
(特殊ケースなので参考になるか不明)

前提

  • Ubuntu16.04.1
  • RAID1 のアレイ(2コンポーネントで構成)について、正常状態→1コンポーネントが(特にデータ含め壊れていないものの)正常に接続・認識されていない状態で、(運悪く)アレイがstartされてしまい、かつそのアレイに対しwriteがあった(「片割れ」発生後の差分は多くはない)
    • 上記の正常に接続・認識されなかったコンポーネントを「片割れ」と呼ぶことにする
  • 「片割れ」のデータは片割れ発生直前時までは正常(であるはず)のため、そのデータをなるべく生かして復旧したい
    • 今回は「片割れ」がSSDで起こったため、そのSSDへの書き込みをなるべく減らしたいという思い
  • HDDなど書き込みがあっても許容できるストレージ(安いストレージ; 空きストレージ)を持っている必要あり

簡易手順

  1. 空きストレージを mdadm --add して、resync 完了まで待つ(クローン元と呼ぶ)
  2. アレイをstop、mdadm のモニタリングプロセスを殺す
  3. クローン元から「片割れ」に対し、差分のみコピーを実施
  4. クローン元を接続解除後、アレイをstart(assemble)する

説明

  • 普通に mdadm --add {アレイ} {「片割れ」} でいきなり復旧するとresyncがかかり「片割れ」に対し全部書き込みが発生してしまうので、その戦略はとらない
  • なぜ中間のディスク(上記でいうと「クローン元」)を使用するのか? - 実験環境にていきなり生存コンポーネントから「片割れ」に対し差分のみコピーを実施したが、それらを用いてうまくassemble できなかったため、やむを得ず
    • コンポーネントとなるパーティションの領域のなかに、実データ以外のメタデータとして、例えば「自分は何番のコンポーネント」とかの情報を持っている。生存アレイのクローンはその情報までクローンされてしまい、mdadm側がうまくassembleできないのではないかと推測
  • 当然といえば当然ながら、アレイがルート(/)パーティションとなっている場合は、別ディスクのOSを準備してやったほうが無難(それ以外の方法は試していない)

    • アレイがルートパーティションの場合は、1. 〜3.は別ディスクOS上で実施し、シャットダウン後、4. を実施
    1. の差分のみコピーのやり方について。適したツールとかあるかもしれないが、今回は以下のスクリプトで実施
    • ループ回数とかは環境により要見積り。必要数より大きくなるのは問題ない
    • 今回は使えるパーティションがなかったため中間ディスクとしてループバックデバイスを使用
      • 前準備概要: 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