目標
- Ubuntu 16.04 Server がインストールされた 2 台のサーバー
host1
とhost2
がある。 host1
とhost2
の間で/home/foo/share
ディレクトリの内容を常に同期する。- 一般ユーザー(
root
以外のユーザー)でrsync
コマンドを実行する。
準備作業
RSA鍵ペアの作成
foo
ユーザーで host1
と host2
に ssh でログインし、それぞれ次のコマンドを実行する。
$ ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa.rsync
RSA鍵公開鍵を設置
host1
の~/.ssh/id_rsa.rsync.pub
の中身をhost2
の~/.ssh/authorized_keys
の末尾に貼り付ける。host2
の~/.ssh/id_rsa.rsync.pub
の中身をhost1
の~/.ssh/authorized_keys
の末尾に貼り付ける。
注意: ~/.ssh
のパーミッションが 700 であり、~/.ssh/authorized_keys
のパーミッションが 400 または 600 であることを確認すること。
接続確認
$ ssh -i ~/.ssh/id_rsa.rsync host2 # host1 から
$ ssh -i ~/.ssh/id_rsa.rsync host1 # host2 から
rsync コマンドの動作確認
host1
で次のコマンドを群を実行する。
$ mkdir ~/share
$ echo TEST ~/share/test.txt
$ rsync -av -e ssh ~/share/ foo@host2:/home/foo/share
~/share/
の末尾のスラッシュ(/
)は必須である。
host2
の /home/foo/share
ディレクトリに test.txt
というファイルができていればOK。
lsyncd のセットアップ
ソフトウェアのインストール
$ sudo apt-get install -y lsyncd
設定ファイルの作成
/etc/lsyncd/lsyncd.conf.lua
を作成。
settings { logfile = "/var/log/lsyncd.log", statusFile = "/tmp/lsyncd.stat", delay = 1 } sync { default.rsync, source="/home/foo/share/", target="foo@host2:/home/foo/share/", delete=false, rsync = { rsh = "/usr/bin/ssh -i /home/foo/.ssh/id_rsa.rsync -o UserKnownHostsFile=/home/foo/.ssh/known_hosts" } }
注意事項:
delay
の値(デフォルト: 15)は、ファイル更新イベント発生から rsync 実行までの遅延時間(秒単位)である。リアルタイム性を追求するなら値は小さいほうがよいが、ファイル更新イベントが頻発するサーバーでこの値を小さくし過ぎると、かえって更新に時間がかかるかもしれない。source
の末尾のスラッシュ(/
)は必須である。host2
側のlsyncd.conf.lua
では、target
の値を"foo@host1:/home/foo/share/"
とする。delete=false
については本稿末尾の「備考」を参照。-o UserKnownHostsFile-...
の記述を省略すると、Host Key Verification Failed
というエラーが発生する。
lsyncd の起動
lsyncd を起動。
$ sudo systemctl restart lsyncd
動作確認
host1
の/home/foo/shared
ディレクトリに新しいファイルを追加し、host2
の/home/foo/shared
ディレクトリにそのファイルが転送されることを確認。host2
の/home/foo/shared
ディレクトリに新しいファイルを追加し、host1
の/home/foo/shared
ディレクトリにそのファイルが転送されることを確認。
うまく行かない場合は、/var/log/lsyncd.log
を見て調べる。
備考
本稿で使用した lsyncd の設定では delete=false
オプションを使用しているため、host1
または host2
でファイルが削除されても、もう一方の側でそのファイルは削除されない。
ファイルが削除される可能性のある環境で lsyncd による「双方向同期」を使用する場合の注意点については、lsyncdで双方向同期するなら、delete='running' がいいを参照せよ。
追記
「備考」で触れたが、lsyncd で双方向同期を行う場合、ファイル削除の扱いが難しい。
host1
がダウンしている間に host2
に追加されたファイル X があるとき、host1
の再起動時に X が削除される可能性がある、ということだ。
この問題を回避するため、参照したブログ記事では「lsyncd の起動時にファイルの同期をしない(delete="running"
)」という設定を勧めている。
しかし、そもそもなぜファイルを削除するのかを考えると、この回避策でよいだろうか。
host1
がダウンしている間に host2
でファイル Y が削除されたとする。「lsyncd の起動時にファイルの同期をしない」設定の場合、host1
の再起動後も host1
上でファイル Y が残り続けることになる。
おそらく、ファイル Y を削除する目的は、ディスクスペースの節約かファイル Y の内容を残したくない(内容がまずい)かのどちらかだろう。
つまり、「lsyncd の起動時にファイルの同期をしない」設定では、この目的が達成されない。
とすれば、正しい回避策は、「lsyncd の起動時にファイルの同期をするが、ファイルの削除はしない(delete=false
)」設定にしておいて、ファイル Y を削除したいときにはファイル Y を空にする(ファイルサイズを 0 にする)運用をすることではないだろうか。これならば、host1
が復活したときに、host1
上のファイル Y が消える。
ちなみに、サイズが 0 のファイルも一定のディスクスペースを占めるし、あまりに数が多いと「inode枯渇」という別の問題を引き起こす。
だから、ファイル削除が頻繁に行われる環境では、サイズが 0 のファイルを削除する仕組みを別途考えたほうがいいだろう。
例えば、毎朝 4:01 に host1
と host2
の両方が動いていることを確かめた上で、4:00 以前に書き換えられたサイズ 0 のファイルをすべて削除するような処理を cron にやらせればいい。
なお、この「追記」の内容は筆者が頭の中で考えたことに過ぎず、実績があるわけではない。参考にされる方は、この点に留意していただきたい。