目次
はじめに
こんにちは。
最近サーバ構築系の案件がありまして、そちらでlsyncdを使ってファイルを同期させました。
分散型のサーバ構成でシステムを組む必要がありまして、それらの分散されたサーバで同一のファイルを同期させました。
今まで同期が必要な場面ではNFSを使っていました。NFSもすごく便利で好きなのですが、今回は色々と諸事情がありlsyncを使って同期しました。
(ちなみにlsyncの公式ってどこなんでしょうね。)
lsyncについて基本的なこと
lsyncは”Live Sync daemon”という名前がついています。ただ恐らく、ファイル同期プログラムとして有名なrsyncのオマージュとして、「r」に対しての「l」を冠しているとおもいます。
「Copyright」と「Copy left」、「more」と「less」などは有名ですね。
lsync自体ではファイルの同期機能を使いません。実際の同期はrsyncなどのファイル転送のプログラムに任せ、lsyncではファイルの変更を検知しrsyncなどを呼び出します。
rsyncはファイル同士に更新があったかどうか、圧縮をどうするか、転送のスピードアップはどうするかなど、転送自体の多くの機能があります。
ただlsyncのオプションには「direct」という項目もありますので、lsync同士での通信も可能かと思います。
今回採用した方法ではありませんが、最も基本的な使い方としてはlsyncはlsyncdが立っているサーバ側からファイルを転送します。
受け側から引き出すのではなく、送信側から送ります。
というのもファイル送信側のOSの機能を冠しして変更を検出するのでそういった形になっています。
ファイルを取り出すポーリング型ではなくて、ファイルを送り出すプッシュ型なモデルですね。
rsyncとsshとinetd
lsyncdのファイル転送で利用されるrsyncには、ssh越しに動作するモードとrsync自体がデーモンとして動作するモードがあります。
lsyncdは情報が豊富なため、このrsyncについての記述ではrsyncをデーモンとして動作させる紹介記事が多かったです。
ですが最近ではrsyncをデーモンとして動作させることは一般的ではなく、ssh越しにrsyncを動作させる方が一般的です。
rsyncはinet(xinet)と呼ばれるデーモン化ツールを使って動作させていました。
しかし10年ほど前からこのinetはあまり使わないようにしましょう、という風潮が広まって以降、特にrsyncはssh越しで使われることが多くなりました。
(ちょうど僕はそのころFreeBSD5あたりを使っていて、inetd関連が減ってきていました。もしかすると最近はxinetdが復権していたのかもしれませんが…)
不要にrsyncのポートを待ち受ける必要もありませんし、sshは脆弱性のメンテナンスも多く信頼されたプロトコルです。
今回はssh+rsyncをlsyncdに使わせる、という方針で行きました。
インストールと設定など
環境はCentos7です。
コンフィグファイルなどを調整するので、lsyncdのインストール前に/etcのGit化(VCS化)ができるetckeeperを入れておくと便利です。
今回は双方向で同期させるので両方に同じような設定を行います。
ここでは一台だけの設定を紹介します。
$ sudo yum install -y lsyncd rsync
設定ファイルはデフォルトで/etc/lsyncd.conf
に入ります。
こちらを編集します。
デフォルトではこんな感じで入っています。
----
-- User configuration file for lsyncd.
--
-- Simple example for default rsync, but executing moves through on the target.
--
-- For more examples, see /usr/share/doc/lsyncd*/examples/
--
-- sync{default.rsyncssh, source="/var/www/html", host="localhost", targetdir="/tmp/htmlcopy/"}
コメントはSQLとかと同じ--
のようですね。
Luaとして書けるようです。
今回は srv1.example.comというホストの /var/html から srv2の同じ場所に送ります。
settings {
logfile = "/var/log/lsyncd.log",
statusFile = "/tmp/lsyncd.stat",
statusInterval = 1,
insist = 1,
}
sync{
default.rsync,
delay = 0,
source="/var/html",
target="srv2.example.com:/var/html",
delete="running",
rsync = {
archive = true,
links = true,
update = true,
verbose = true,
rsh = "/bin/ssh -l www -i /home/www/.ssh/id_rsa"
}
}
settings
ブロックとsync
ブロックに分かれています。
settings
ではlsyncdの基本的な設定を、sync
では行いたい動作を記述します。
sync
は複数の記述が可能です。
sync.rsync.rsh のところでrsyncを行うユーザ、秘密鍵を指定しています。
デフォルトではlsyncdをrootで動かしますので、そのままだとrsyncを動作させるユーザもrootになってしまいます。
これを上書きします。
テスト動作など
コンフィグファイルの記述が正しいかチェックを行います。
通常のlsyncd
はデーモンとして動作させるのでCentOSではsystemctlを使って起動しますが、まずは手動で動作させてコンフィグチェックを行います。
lsyncd
コマンドが存在しますのでそちらを呼び出します。
$ sudo lsyncd -nodaemon -log scarce /etc/lsyncd.conf
-nodaemon
で対話モードとして、-log scarce
でログを出力します。
最後の引数でコンフィグファイルの指定が必要です。
うまく行けばrsyncの同期ログが流れます。
だめな場合にはエラーが出ます。
特に初回起動時にはsshのフィンガープリント受け入れの対話が出るかもしれないです。
その場合には一度rootになってknown_hostsに追加しておきます。
$ sudo su
# ssh srv2.example.com
yes
ちなみにこのフィンガープリントを無視するオプションを昔から探しているのですが、未だに見つけられていません…。
うまく動作するようでしたらデーモンとして起動します。
$ sudo systemctl start lsyncd.service
また自動起動するようにしておきます。
$ sudo systemctl enable lsyncd.service
エラーが出ていないかチェックしておきます。
$ sudo systemctl status lsyncd.service
CentOS7からはsystemctlで発生したエラーはjournalという仕組みで保存されるようになりました。
以前は/var/log/messagesに書かれることが多かったですが、それを集約したようですね。
journalはjournalctlというコマンドで行います。
詳細オプションのxe、tail -f
と同じ順次表示モードを付けて別ターミナルで表示しておくと便利です。
$ sudo journalctl -xef
思った以上にlsyncdが動かなくてログ表示が助かりました。
トラブルなど
監視するファイルが多すぎてエラーが発生していました。
$ sudo lsyncd -log scarce -nodaemon /etc/lsyncd.conf
10:06:59 Error: Terminating since out of inotify watches.
Consider increasing /proc/sys/fs/inotify/max_user_watches
max_user_watches
というシステム環境変数の値が足りないようでした。
下記の記事を参考に値を変更しておきます。
$ cat /proc/sys/fs/inotify/max_user_watches
8192
$ sudo sh -c 'echo "fs.inotify.max_user_watches=1024000" >> /etc/sysctl.conf'
$ sudo sysctl -p
net.ipv4.conf.all.arp_notify = 1
net.ipv6.conf.all.disable_ipv6 = 1
fs.inotify.max_user_watches = 1024000
$ cat /proc/sys/fs/inotify/max_user_watches
1024000
まとめ
以上がlsyncを使った双方向ファイル同期についてでした。
nfsもv4が出てから高速化、安定化したかなと思いますが、もっと上のレイヤーで動くlsyncdはお手軽ですね。
ただちょっとパッケージが古い感があり、オプション周りでは苦労しました。
良い同期生活を送れると良いですね。