2017年3月19日日曜日

Raspberry Pi の autofs で NAS のバックアップ

自宅の全てのデータを NAS に保存しています。
NAS は RAID でミラーリングしているとは言え、飛ぶときはミラーもろとも飛ぶので
2台体制で定期的にコピーするようにしています。

2台のメーカーが違っていたり、特定のフォルダだけコピーしたいようなケースでは
NAS が持っているネットワークバックアップ機能では対応できないことがあります。

そこで、我が家では Raspberry Pi で NAS 間のデータバックアップを動かしています。

滅多に変更しないもので、毎回やり方を忘れがちなので備忘録としてメモしておきます。

バックアップの前提

  • NAS2台ともWindowsファイル共有。
  • いつも1台(稼働系)に書き込み。もう1台(冗長系)はバックアップ専用。
  • 冗長系が壊れたら、新しく購入したNASを稼働系にして、元の稼働系を冗長系に置き換える。
  • 稼働系が壊れたら、新しく購入したNASを稼働系にして、冗長系から書き戻す。
    (常に冗長系を旧機種にするため。)
  • NASを再起動しても Raspberry Pi のバックアップ機能には影響がないようにしたい。


IP アドレスの設定

NAS2台には固定IPを割り当てます。
DHCPでも何とかなりそうな気はしますが、何かの拍子に稼働系と冗長系が
入れ替わってバックアップされると悲惨なので。

固定IPの設定方法はNASやルータの設定次第なので省略。

今回は、次のように設定したものとして説明します。
コマンドのオプション等は適宜読み替えてください。
  • 稼働系IPアドレス: 192.168.1.1
  • 稼働系ホスト名: active_nas
  • 冗長系IPアドレス: 192.168.1.2
  • 冗長系ホスト名: standby_nas


Raspberry Pi 上でのホスト名設定

NAS2台のIPアドレスにRaspberry Pi上で名前を付けます。
Raspberry Pi に SSH で接続して次のコマンドを実行。
pi@raspberrypi ~ $ sudo -s
root@raspberrypi /home/pi $ cp /etc/hosts /etc/hosts.`date +%Y%m%d`
root@raspberrypi /home/pi $ echo '192.168.1.1    active_nas' >> /etc/hosts
root@raspberrypi /home/pi $ echo '192.168.1.2    standby_nas' >> /etc/hosts
root@raspberrypi /home/pi $ cat /etc/hosts
127.0.0.1 localhost
::1  localhost ip6-localhost ip6-loopback
fe00::0  ip6-localnet
ff00::0  ip6-mcastprefix
ff02::1  ip6-allnodes
ff02::2  ip6-allrouters

127.0.1.1 raspberrypi
192.168.1.1 active_nas
192.168.1.2 standby_nas


autofs を設定

Raspberry Pi で NAS の領域をマウントするのですが、
普通に smbmount してしまうと、NAS を再起動した時に再マウントが必要になります。

そこで、autofs を使って必要な時にだけ自動マウントし、NAS の再起動の影響を回避します。
また、autofs なら NAS が故障してマウント異常になっても大丈夫です。

まずは autofs と smbmount に必要なパッケージのインストール。
root@raspberrypi /home/pi $ apt-get install autofs smbclient

次に、autofs でマウントできるように設定します。
root@raspberrypi /home/pi $ cp /etc/auto.master /etc/auto.master.`date +%Y%m%d`
root@raspberrypi /home/pi $ echo '/smb    /etc/auto.smb' >> /etc/auto.master
root@raspberrypi /home/pi $ mkdir /smb
root@raspberrypi /home/pi $ mkdir /etc/creds
root@raspberrypi /home/pi $ echo 'username=USER_NAME
password=PASSWORD' > /etc/creds/active_nas
root@raspberrypi /home/pi $ chmod 600 /etc/creds/active_nas
root@raspberrypi /home/pi $ echo 'username=USER_NAME
password=PASSWORD' > /etc/creds/standby_nas
root@raspberrypi /home/pi $ chmod 600 /etc/creds/standby_nas
root@raspberrypi /home/pi $ service autofs restart

ここで「USER_NAME」と「PASSWORD」はNASのフォルダにアクセスするユーザ名とパスワードです。
2台のNASでアカウント情報が異なっている場合はそれぞれのアカウントを記入します。
/etc/creds フォルダにアカウント情報を書いたファイルを入れて、ファイル名をホスト名にしておくと、
autofs がマウント時に自動的に参照してくれます。
パーミッションは600(オーナーだけが読み書き可能)で。

ここまで出来たら、一般ユーザでもNASのデータにアクセスできるはずです。
例えば、I-O Data の LANDISK なら、次のようにになると思います。

root@raspberrypi /home/pi $ exit
pi@raspberrypi ~ $ ls /smb/active_nas
contents  disk  itunes
pi@raspberrypi ~ $ ls /smb/active_nas/disk
TrashBox quickcopy
pi@raspberrypi ~ $ ls /smb/standby_nas
contents  disk  itunes
pi@raspberrypi ~ $ ls /smb/standby_nas/disk
TrashBox quickcopy
pi@raspberrypi ~ $ df
Filesystem      1K-blocks      Used  Available Use% Mounted on
/dev/root        15021296   2428732   11949656  17% /
devtmpfs           437048         0     437048   0% /dev
tmpfs              441384         0     441384   0% /dev/shm
tmpfs              441384     11556     429828   3% /run
tmpfs                5120         4       5116   1% /run/lock
tmpfs              441384         0     441384   0% /sys/fs/cgroup
/dev/mmcblk0p1      61384     21368      40016  35% /boot
//active_nas/disk   1949057984 846123472 1102934512  44% /smb/active_nas/disk
//standby_nas/disk      972305984 839236008  133069976  87% /smb/standby_nas/disk

しばらくしてから再度 df すると NAS のマウントが外れているはずです。


バックアップする

rsync でバックアップします。
コピー元とコピー先を間違うと大変なことになるので、ひとまず dry run で試します。
pi@raspberry ~$ /usr/bin/rsync -n -rltv --max-size=100m --size-only /smb/active_nas/disk/ /smb/standby_nas/disk/

巨大なNASの場合、差分チェックの時間が馬鹿にならないので
ひとまず「--size-only」オプションでサイズ違いのファイルだけを対象にします。
出力を確認して、期待通りであれば「-n」オプションを外して実際にバックアップを実行。
ただし、まだ怖いのでファイル削除はしません。差分の追記だけ。かつ、100MBだけ。

pi@raspberry ~$ /usr/bin/rsync -rltv --max-size=100m --size-only /smb/active_nas/disk/ /smb/standby_nas/disk/

実行後、ログに出ているファイルが正しくコピーされていることを確認します。
問題なければ、全ファイルをバックアップし、稼働系で削除されたものは冗長系からも削除します。
pi@raspberry ~$ /usr/bin/rsync -rltv --delete /smb/active_nas/disk/ /smb/standby_nas/disk/


バックアップを定期実行

先ほどのコマンドをスクリプトにして crontab で週に一度実行します。
pi@raspberry ~$ cat rsync.sh
#!/bin/sh

echo '/usr/bin/rsync -rltv --delete $1 $2
pi@raspberry ~$ crontab -e
15 05 * * 1 /root/bin/rsync.sh /smb/active_nas/disk/ /smb/standby_nas/disk/

ただし、このコマンドには1つ致命的な問題があります。
万が一、稼働系のNASが故障して空のフォルダが出来上がってしまった場合、
空のフォルダをそのままバックアップして全データが消えます。
そこで、異常な状態だったらファイル削除しないなどの対策を行います。
対策後のスクリプトはこんな感じです。
#!/bin/bash

THRES=-10
SRC=$1
DST=$2

/bin/ls $SRC
/bin/ls $DST

# コピー元フォルダがなければ異常終了
if [ ! -d $SRC ]
then
  echo "$SRC Not Found" >&2
  exit 1
fi

# コピー先フォルダがなければ異常終了
if [ ! -d $DST ]
then
  echo "$DST Not Found" >&2
  exit 1
fi

# リストア中に「/tmp/restore」というファイルを置いておくと、
# cron でのバックアップ実行をスキップする。
if [ -f /tmp/restore ]
then
  echo "Restoring" >&2
  exit 1
fi

# マウントした領域のサイズを確認する。
srcsize=`/bin/df $SRC | /bin/grep / | /usr/bin/awk '{print $3}'`
dstsize=`/bin/df $DST | /bin/grep / | /usr/bin/awk '{print $3}'`
let diff=(${srcsize}-${dstsize})/1048576
if [ $diff -lt $THRES ]
then
  # コピー元のディスクサイズが極端に小さかったら以上終了。
  echo "Source data size is too small" >&2
  exit 1
elif [ $diff -lt 0 ]
then
  # コピー元のディスクサイズの方が小さかったら、ファイル削除しない。
  echo "Sync without delete" >&2
  /usr/bin/rsync -rltv $SRC $DST
else
  /usr/bin/rsync -rltv --delete $SRC $DST
  echo 2
fi


これで多少の障害があってもそこそこ安全にバックアップできるようになりました。

0 件のコメント:

コメントを投稿