treedown’s Report

システム管理者に巻き起こる様々な事象を読者の貴方へ報告するブログです。会社でも家庭でも"システム"に携わるすべての方の共感を目指しています。

※https化しました。その影響でしばらくリンク切れなどがあるかもしれませんが徐々に修正していきます。 リンク切れなどのお気づきの点がございましたらコメントなどでご指摘いただけますと助かります。

Raspberry Piのddバックアップとリストアテストをやってみる

Raspberry Piは小型・省電力と小規模Linuxサーバとして便利に使っていますが、SDカードからのブートなのでSSDより寿命が早いのが心配、バックアップとリストアについて早目に考えておこうと試したことをご報告です。

動機としては、<DebianのRAID1ディスクでエラー発生 - treedown’s Report>と言う障害を体験して、Raspberry Piも何かしら対策したいなぁと考えたことがきっかけとなっています。

ddバックアップ

いままでは、Raspberry Piをシャットダウンして、オフラインでmicroSDのイメージを取得してバックアップとしていました。
これだとRaspberry Piの目の前で作業しなくてはいけないため、毎回現地で作業できないこともあり、コマンドで定期的にバックアップを取得することを目標に、いくつか検証をしてみました。

ddバックアップ:コマンドで

ddコマンドでのバックアップ取得は、以前にRaspberry Pi以外のDebian環境で何度かやっていました。

blog.treedown.net

ちょっと復習。

ddコマンドは、「if=」で始まるバックアップソースと、「of=」で始まるコピー先の組み合わせでバックアップを取得します。

単純にバックアップを取得するコマンドラインは下記のようになります。

dd if=/dev/mmcblk0 of=/home/backup/os-sdcard_dd.img

if=ファイル名&デバイス名:
バックアップ元として読み込むデータソース、バックアップを取得した対象で、ここにバックアップ元となるデータが記憶されたデバイスを記述してバックアップを取得することになります。
Raspberry PiのmicroSDを指定するには"/dev/mmcblk0"と指定します。

of=ファイル名:
出力ファイルを指定します。イメージバックアップではフルパスでファイル名までを記述することでファイルにmicroSDのイメージバックアップを取得することができます。(例では"/home/backup/"ディレクトリにファイル名:os-sdcard_dd.imgを取得します。

場合によって使えるオプション

自分用に三つのオプションを備忘しておきます。

■オプションその1:「bs=1M」
前回<(2/2)ディスクの増設先にddでイメージバックアップ取得 - treedown’s Report>には、「bs=4M」で使っていました。
「bs」はブロックサイズの略(と思われる)で、データが書き込まれたメディアのサイズをさします。これを大きく「bs=1M」や「bs=4M」のように指定することで、ddバックアップに掛かる時間が短縮できるのですが、ファイルシステムに問題が発生していたらイメージバックアップデータも破損データとなってしまうことがあります。またRaspberry PiのmicroSDスロットもそれほどアクセスが速くないので、Raspberry Piでは無指定=512バイトでもよい、という結論に達しました。

■オプションその2:「conv=sync,noerror」
「conv=sync,noerror」をddコマンド実行時に付与すると、不良セクタなどで読み取り不良が発生していた場合でもその領域に「0」を書き込んでバックアップを継続するオプション。
データが記憶された領域がこうなっているとファイルなどが破損してしまいますが、前回<DebianのRAID1ディスクでエラー発生 - treedown’s Report>のように空き領域で不具合が出ていたとしてもバックアップが途中で停止してしまうので、定期実行時にはこのオプションを付与しておくようにします。
ちなみに、不良セクタなどで読み取り不良が発生していた場合、上記「bs=」で指定したブロックサイズの分だけデータは(たぶん)消えてしまいます。

■オプションその3:「status=progress」
主に手動でddコマンドを実行するときに使ったオプション。
「status=progress」を付けると、画面上にddコマンドで取得したバックアップの進行状況が表示されます。定期実行時にはこのオプションは外して使うことになります。

バックアップ取得からリストア

前述のオプションを付与して前述のコマンドを記載すると、

dd if=/dev/mmcblk0 of=/home/backup/os-sdcard_dd.img conv=sync,noerror status=progress

という具合になります。

f:id:treedown:20211117182448p:plain
これで取得したRaspberry PiのmicroSDのイメージファイルを、WindowsにコピーしてきてDD for Windowsを使ってmicroSDに書き込んでいきます。

f:id:treedown:20211117182504p:plain
※通常はddコマンドでif=とof=を逆にして書き込むと思いますが、障害でRaspberry Piが起動しない状況を想定し、取得したddイメージのバックアップファイルをリストアする手順として上記で実施しています。

使うmicroSDは以下

f:id:treedown:20211117182326p:plainTranscendの16GBがRaspberry Piで稼働するRaspbianがインストールされたmicroSDカードで、TOSHIBA 16GBとTranscend 32Gにそれぞれイメージを展開してみることにしました。

いざイメージを展開してみると、同容量となるTOSHIBA 16GBでは容量不足となってしまい、取得したイメージが全て書き込めない(リストアの処理自体は完了する)という結果になってしまいました。これのmicroSDで起動しても正常にOSが起動しませんでした。

いっぽうで、より容量の多い32GBのmicroSDへのリストアは正常終了し、無事OSの起動まで確認できました。ただ、dfコマンドで容量を見ると、

f:id:treedown:20211117182529p:plain

"/dev/root         15G  2.0G   12G   15% /"となっており、当然ながら、32GBのmicroSDカードを使っていてもddでバックアップしたパーティションである16GBのSDのイメージが展開されていますので、ディスク使用量はそのままとなっています。※ちなみに、(記憶の限りでは)これをddバックアップすると、イメージファイルは32GBのイメージファイルが生成されました。

容量がより大きいmicroSDにしかリストアができない、という結果となってしまい、これはどうにかならないものか、調べてみることにしました。

PiShrinkを使ってイメージを縮小

16GBのSDカードから取得したddイメージを展開するにあたり、16BGのSDを使うと、同一メーカでも容量不足となってしまうので、単純に16GBのSDカードのイメージを取得したものを32GBのSDカードに展開するとうまく起動する、しかし32GB全容量は使われておらず無駄が多いうえ、今後ddで世代を重ねて行くにつれて容量が大きいmicroSDカードを用意しなくてはならない、というのはちょっとバックアップとしどうかと思い、調べてみると、「pishrink.sh」を使うのがスマートのようでした。

■PiShrink
https://github.com/Drewsif/PiShrink

ここの「Installation」に使い方の記載があります。(以下抜粋)
--------------------------------------------------------------
# wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
# chmod +x pishrink.sh
# sudo mv pishrink.sh /usr/local/bin
--------------------------------------------------------------

三行目のmvコマンドは、ddイメージ保存先と同じ場所に置くようにしました。

ここでダウンロード可能なシェルを使うと、イメージ容量を縮小し、リストアとしてmicroSDカードに書き込んだ後に、書き込んだmicroSDカード容量一杯まで拡張する動作が初回起動時に一回だけ実行されてRaspberry Piが起動してきます。

さっそくやってみます。カレントディレクトリを変更して、

# ./pishrink.sh ./os-sdcard_dd.img

実行すると
--------------------------------------------------------------
自動的に、画面が進んでいき、

f:id:treedown:20211117182749p:plain
縮小動作を始めます。しばらく待つと、

f:id:treedown:20211117182804p:plain

「pishrink.sh: Shrunk ./os-sdcard_dd.img from 15G to 3.5G ...」のメッセージで完了します。
--------------------------------------------------------------
このように16GBのイメージが3.5GB(実使用容量)に圧縮されました。

f:id:treedown:20211117182836p:plain
ではこのイメージを使ってdd for WindowsでイメージファイルをSDカードに書き出し、イメージの書き込みが完了したSDカードでRaspberry Piを起動します。

リストアした別のmicroSDカードで起動

※注:テストのため、同じ16GBだけど、ちょっとだけ容量が小さい16GBのmicroSDカードが使われています。

初回起動:pishrink.shで縮小したイメージファイルの容量(3.5G)で起動しますが、初回起動時にSDカードの容量限界まで容量を拡張⇒再起動、と動作し、
再起動後:通常のOSブートが開始します。容量を確認すると
$ df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/root         14G  2.0G   12G   15% /
devtmpfs         430M     0  430M    0% /dev
(※以下略)

SDカード限界の容量まで拡張されていることが確認できました。前回起動に失敗した16GBのSDカードで無事OSを起動することができたばかりか、容量一杯まで自動調整してくれています。

いろいろ試行錯誤した結果、必要な内容だけ抜き出して作成しましたので、駆け足ですが、ひとまず、バックアップの取得(手動だけど)と容量縮小&次回同一容量のmicroSDカードでリストアして起動する、というところまで

これなら、ddバックアップで自動化してよさそう。