CentOS7 (1511) で、すぐに起動できるシステムバックアップの作成

NUC(DN2820FYKH)で、起動用のドライブとは別のドライブを用意して、すぐに起動できるシステムバックアップを作成した。USBドライブなどの外付けデバイスでシステムバックアップを作成するときにでもご参考に。

やりたいこと

NUC(DN2820FYKH)で、現在USB3.0なUSBメモリ(32GB)を起動ドライブとしている。USBメモリがいつ壊れるかと気にしながら使い続けるというのもさすがに心もとないので、すぐに起動できるバックアップを用意しておきたい。

前提

用意してあったのは、128GBのSSDと、それを外付けドライブ化するUSB接続のハウジングのみ。ちなみに、DN2820FYKHにはUSB3.0の口が一つしかないので、このドライブはUSB2.0でつなぐ。

検討

btrfsでは、ファイルシステムでRAIDが作成できるが、今はドライブの容量が違うので、RAID1で実現するのはやめた。

その代わり今回はcron.weeklyでrsyncするスクリプトを走らせることにした。

また、今回はbtrfsで使えるsnapshotをバックアップ生成にも便利に使っているが、これについては別の記事で書くので、この記事では触れない。(当然、スナップショット自体もドライブ内のバックアップとして考えることになる。これは、ドライブ故障時のためのバックアップではなくて、設定ファイルの意図しない変更等に備えるもの。)

やったこと

ドライブごとのアクセス速度も違うし容量も違うので、この状況ではさすがにRAID組んでもなぁ、ということで、バックアップの方は、cron.weeklyでrsyncなスクリプトを走らせることした。

で、問題は、起動ドライブに異常があったときに、バックアップからすぐに起動させるのが面倒、ということ。この原因は2点ある。

  1. システムまるごとrsyncでバックアップするので、fstabの中見が同じままである。つまり、バックアップから起動しようにも、ファイルシステムをマウントする段階で、バックアップ側ではなく、本番側を / にマウントしようとしてしまうのが面倒。
  2. grub2の設定ファイルに、パーティションのUUIDが書いてある。ここを書き換えておかないと、起動すら怪しくなる。もっと具体的にいうと、grub.cfgの中で、linux16コマンドの引数で、root=UUID=hogehoge という感じで、こちらもUUIDで指定してあり、このドライブがないと起動しないことが予想される。

これらを解決するため、cron.weekyでのrsyncでのバックアップスクリプトの中に、別に用意したfstabファイルをコピーするコマンドと、chroot環境下でgrub2-mkconfigして、バックアップ中のgrub.cfgを適切に構築するスクリプトを走らせることにした。

fstab関係

fstabでのドライブの指定はUUIDではなくてLABELで行う。ドライブ交換のときにLABELをふる手間はあるが、UUIDを調べてその都度fstabを書き換えるのは面倒だし、順番が保証されないデバイスファイル名(/dev/sda1 など)で指定するのも怖いので、単純なやり方としてはこれがよい。

まずはファイルシステムにラベルをふることになるのだが、btrfsでは、ファイルシステムをマウントしたままでラベルを変更できる。(本当は、mkfsするときにラベルをふっておくほうがよかったのだけれども、いまさらしょうがない。SSDの方は、mkfsのときに -L オプションで LABEL を指定しましたが、USBメモリの方はすでに稼働していた、、、。)

ラベルの変更はこんな感じのコマンドで。

btrfs filesystem label /dirname_of_mountpoint USB_DATA # マウントしたままでOK
xfs_admin -L "USB_BOOT" /dev/sda1 # /boot を置いているxfsファイルシステムは、
                                  # 事前にアンマウントする必要あり
swapoff  /dev/sda3   # スワップは、作り直す。
mkswap -L USB_SWAP /dev/sda3
swapon LABEL=USB_SWAP

/ にマウントする、rootサブボリューム、/homeのhomeサブボリュームがあり、他に、スナップショットを格納するためのsnapshotsサブボリュームを、/root/snapshots にマウントする形にした。

(今回の作業では手でサブボリュームを追加しました。別の記事で書きます。)

また、/mnt/backup 以下はSSDドライブに保存したものをマウントしてある。fstabの中身はこちら(長いので改行されてしまいますが、うまく解釈してください。意味があるのかよくわからないオプションもついていますが、あまり気にしないでくださいませ、、、。ここにある通り、btrfsでは、fsckは不要のようです。別の記事にも書きました。)


LABEL=USB_DATA / btrfs subvol=root,ssd,space_cache,compress=lzo,discard 1 0
LABEL=USB_BOOT /boot xfs defaults        1 2
LABEL=USB_DATA /home btrfs subvol=home,ssd,space_cache,compress=lzo,discard 1 0
LABEL=USB_DATA /root/snapshots btrfs subvol=snapshots,ssd,space_cache,compress=lzo,discard 1 0
LABEL=USB_SWAP swap swap    defaults        0 0
LABEL=HDD /mnt/disk ext4    defaults                 1 2
LABEL=SSD_DATA /mnt/backup btrfs subvol=root,ssd,space_cache,compress=lzo,discard 1 0
LABEL=SSD_DATA /mnt/backup/home btrfs subvol=home,ssd,space_cache,compress=lzo,discard 1 0
LABEL=SSD_DATA /mnt/backup/root/snapshots btrfs subvol=snapshots,ssd,space_cache,compress=lzo,discard 1 0
LABEL=SSD_BOOT /mnt/backup/boot xfs defaults 1 2

このfstabファイルがそのままバックアップされてしまうと、厄介なことに、OS起動時に、USB_DATAの方を / にマウントしてしまうため、なんとか対応する必要がある。対応策としては、適当な場所にバックアップ用の別のfstabファイルを置いておき、rsyncが走った直後にそれをバックアップにコピーする、という手段をとった。

バックアップ用fstab_backup

LABEL=SSD_DATA / btrfs subvol=root,ssd,space_cache,compress=lzo,discard 1 0
LABEL=SSD_DATA /home btrfs subvol=home,ssd,space_cache,compress=lzo,discard 1 0
LABEL=SSD_DATA /root/snapshots btrfs subvol=snapshots,ssd,space_cache,compress=lzo,discard 1 0
LABEL=SSD_BOOT /boot xfs defaults 1 2
LABEL=HDD /mnt/disk ext4 defaults 1 2

見ての通り、SSD_DATAを / にマウントし、USB_DATAの方は認識されるとは限らないので、マウントしない。

これで一つ目の問題は解決。

grub.cfgの再作成

単純にシステムワイドなバックアップを作成すると、grubの設定ファイルまでコピーされてしまい、いざというときにドライブが見つかりませんで起動できなくては困る。
/boot以下はバックアップしないという手もあるが、CentOS7でもカーネルのアップデートはちょくちょくあるのであり、それらのときにいちいち手で/bootをバックアップするというのもあまりよくない。

というわけで、今回は、rsyncでのバックアップ直後に、同時にgrubの設定ファイルも作成することにした。
そのためのスクリプト(/root/grubconfig が、 /mnt/backup/root/grubconfig にバックアップされ、これが動く)がこちら。

#!/bin/bash -e
cp /root/fstab_backup /etc/fstab
#touch /.autorelabel
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev
mount -t proc proc /proc
mount -t tmpfs tmpfs /tmp
mount -t tmpfs tmpfs /run
grub2-mkconfig -o /boot/grub2/grub.cfg 2> /dev/null
umount /tmp /run /sys /dev
umount /proc # /proc/mounts がないとumountが動かない
exit

バックアップ系の方の設定ファイルを作成するといいつつ、本番系の/boot/に書こうとしているのではないか、と思うかもしれないが、これは、chrootで実行するためにそのように書いてある。

grub2-mkconfigは、procやらdevやらがないと動かないわけだが、本番系の方で動かしてしまうと、当然本番系の設定ファイルを作成してしまう。

どうせバックアップの方には、実行ファイルも含めて必要なものはすべてあるのだから、バックアップ用の設定ファイルを作成するために、chroot でバックアップ先に入って実行してしまうことで対応できる(マウントコマンドは、chrootの外側で叩こうとすると、すでにマウント済み、ということで/sysがマウントできません。)。

なお、バックアップのrsyncのときに、-AX のオプションを忘れると、SELinuxのコンテキストがコピーされず、起動できなくなってしまう。その場合は、/.aoutorelabelをtouchしておけば、起動時に再作成され、起動できるようになるはずである(その分、起動が相当遅くなりますので、毎回やるものではありません。)。これはおそらくrsyncに-AXオプションを付ければ全く不要と思うが、自分は最初にrsyncをしたときにうっかり忘れてしまい、後から.autorelabelで修正したので、それだけでうまくいくかどうかはわからないし、自分で試すほどの元気もない。

これで2つ目の問題もOK

rsyncスクリプト

バックアップから起動させるための小細工を終えたところで、肝心のバックアップスクリプトはこちら。

/etc/cron.weekly/10backup_with_rsync

#!/usr/bin/bash -e
DEST=/mnt/backup/
if [ -d ${DEST}/root ]; then
    rsync -aHAXSx --delete /root/snapshots/root_last/ $DEST
    rsync -aHAXSx --delete /root/snapshots/home_last/ ${DEST}/home
    rsync -aHAX --delete /boot ${DEST}
    chroot $DEST /root/grubconfig
    chroot $DEST /etc/cron.daily/make_snapshots
fi
exit 0

/root/snapshots/root_last と /root/snapshots/home_last には、1日1回のバックアップのうち、最新の1回分が常に格納されているもの。

ポイントは、

  1. SELinux対策の、rsyncの-AXオプション
  2. $DEST/{home,boot,root/snapshots} を消去しないための、rsyncの-xオプション(ファイルシステムをまたいで動作しない)
  3. 上で書いた、chrootでの /mnt/backup/root/grubconfig の実行で、fstabファイルの差し替えとgrubの設定ファイルの書き換え
  4. bashの-eオプションで、エラーが出たらそこでスクリプトを終了

のあたりと思う。

これで、いきなりUSBメモリがだめになっても、最大でも1週間前の状態の、すぐに起動できるバックアップは残っているので、修復作業なり、新しいUSBメモリにデータを移すなりができるようになった。

これとは別に1日1回のsnapshot作成も行っているが、長くなったので記事を改めて書く

参考
man rsync
man btrfs

参考URL
https://wiki.archlinuxjp.org/index.php/Btrfs#.E3.82.B9.E3.83.8A.E3.83.83.E3.83.97.E3.82.B7.E3.83.A7.E3.83.83.E3.83.88
https://btrfs.wiki.kernel.org/index.php/Main_Page
https://docs.oracle.com/cd/E39368_01/b71105/ol_btrfs.html

CentOS7 (1511) で、すぐに起動できるシステムバックアップの作成」への1件のフィードバック

コメントを残す