見出し画像

samba + rsync を使って遠隔バックアップ機能付きファイルサーバを構築する

情報がオンライン化され集積されるようになって久しい昨今ですが、それに伴って増加するのがデータ消去のリスク。ハードディスクやコンピュータ本体の物理的クラッシュによるデータ逸失もあれば、ミスによるデータ消去も無くなることはありません(人間ですもの)。また、3.11の大震災から早いもので10年も経過したわけですが、震災や火災、場合によっては機器類の盗難など、やはりデータ消去・逸失のリスクは常に我々に付いて回ります。そこで、オープンソースの定番sambaと、ファイル同期ソフトrsyncを使い、遠隔バックアップ機能付きファイルサーバを構築したので記録しておきます。

今回のシステムの諸元は次の通りです。
1.メインサーバ
・場所は自宅。ネットワークアドレスは192.168.x0.0/24
・OSはFreeBSD
・データ領域は8TBのHDDを4台、raidz2にて構築
・基本的にはこちらをメインに使用

2.バックアップサーバ
・場所は別荘。ネットワークアドレスは192.168.x1.0/24
・自宅ネットワークとの間は、VPNにて相互に疎通可能
・OSはFreeBSD
・データ領域は14TBのHDDを4台、raidz2にて構築
・別荘滞在時にはこちらにアクセスして仕事などをする
・したがって、バックアップサーバに新規に書き込んだデータは、メインサーバに向けて反映すること重要!

この最後の項目さえ無ければ簡単なのです。バックアップサーバから定期的にrsyncで差分を取得し、反映させればいいんです。しかし、これを実現するため、例えばrsyncにてメインサーバとバックアップサーバを同時に相互に同期しあうとします。すると、メインサーバに新しいファイルを書き込んだ直後にバックアップサーバからメインサーバに向けての更新が走ってしまうと、書き込んだファイルが消されてしまうことになります。それを防ぐためには、inodeが更新されたタイミングを見て同期を掛けるような仕組みが必要となり、
https://qiita.com/kaihei777/items/5bb4f381c6b4c31be055
のようにrsync+lsyncdを組み合わせるような工夫が必要になるわけです。
ふむふむ、そうなのか…と思ってlsyncdを試そうと思いましたが、これは私の環境では上手く行きませんでした…。

ではどうするか。いろいろと考えた結果、

・メインサーバをミラー元、バックアップサーバをミラー先として定期的に同期プログラムを走らせる。
・バックアップサーバ側に存在しメインサーバ側に存在しないファイルは、ミラーリングによって削除してしまうのではなく、削除済みフォルダに移動することにして、不要であれば後日手動にて削除。
・バックアップサーバには、バックアップサーバ側で新規に更新したファイルを保存する領域を作り、別荘滞在中に仕事をして保存するファイルはそのフォルダに書き込むことにする。ここに書かれたデータは、バックアップサーバからメインサーバに向けて一方的に更新される。

…だいたいこんな仕様でしょうか。運用上の注意点として、バックアップサーバの新規ファイル保存領域に保存したファイルはメインサーバに転送されるのですが、このとき新規ファイル保存領域にファイルが残ったままメインサーバでそのファイルを削除してしまうと、何度削除してもバックアップサーバ側から転送が掛かってファイルが復活してしまう点でしょうか。これを解決するため、メインサーバに向けては一方的な移動にして、移動が終わればバックアップサーバの新規ファイル保存領域からは削除、という風にしても良いのですが、Wordなどでファイルを編集中に(ファイルがロックされるとはいえ)そんな作業が裏で走るのも嫌だし、バックアップサーバ側で新しく文書を作成するような仕事をしている最中、定期的にどんどんファイルが転送されてその領域から消えていくのもアレなので、その辺は手動で対応すればよいことにしました(まあ現実的な妥協点だと思ってます)。

以上、長くなりましたが、メインサーバとバックアップサーバのconfigです。

メインサーバの/etc/sync_backup_to_main_renew_data.sh
#!/usr/local/bin/php
<?php
define ("SRC_DIR","rsync://192.168.x1.1/home/hogehoge/koushin_data/") ;
define ("RSYNC_OPTION","-auz --exclude='*RECYCLE.BIN*'");
define ("DST_DIR","/home/hogehoge/") ;
define ("PID_FILE","/tmp/.rsync_backup_to_main_kousin");
define ("RSYNC_CMD","/usr/local/bin/rsync") ;
date_default_timezone_set('Asia/Tokyo');
if(file_exists(PID_FILE))
{
exit(-1);
}else{
$cmd="touch ".PID_FILE;
system($cmd);
$cmd=RSYNC_CMD." ".RSYNC_OPTION." ".SRC_DIR." ".DST_DIR."\n";
system($cmd);
unlink(PID_FILE);
}
?>

バックアップサーバの/etc/sync_main_to_backup.sh
#!/usr/local/bin/php
<?php
define ("SRC_DIR","rsync://192.168.x0.1/home/hogehoge/") ;
define ("DST_DIR","/home/hogehoge/") ;
define ("RSYNC_CMD","/usr/local/bin/rsync") ;
define ("RSYNC_OPTION","-auz --delete --backup --backup-dir=\"../backup/backup-$(date +%Y%m%d)\"");
define ("PID_FILE","/tmp/.rsync_main_to_backup");
date_default_timezone_set('Asia/Tokyo');
if(file_exists(PID_FILE))
{
exit(-1);
}else{
$cmd="touch ".PID_FILE;
system($cmd);
$cmd=RSYNC_CMD." ".RSYNC_OPTION." ".SRC_DIR." ".DST_DIR."\n";
system($cmd);
unlink(PID_FILE);
}
?>

これらのスクリプトをcrontabでブン回せばOK。(ブン回すの「ブン」って何だろうね。考えるたびに笑える)
ポイントは、/tmpに一時ファイルを作る点でして、これで大量にrsyncが起動してしまうのを防ぐという良くある手。それから、

define ("RSYNC_OPTION","-auz --delete --backup --backup-dir=\"../backup/backup-$(date +%Y%m%d)\"");

ここですね。同期元になく同期先に存在するファイルは、削除してしまうのではなく一階層上のbackupディレクトリの中にbackup-日付というディレクトリを掘ってそこに移動。

メインサーバとバックアップサーバの/etc/rsyncd.confは省略します。これは互いに相手からしか接続できないように適宜設定してくださいな。

以上。

この記事が気に入ったらサポートをしてみませんか?